summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/00-Common.cmake8
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake4
-rw-r--r--indra/edit-me-to-trigger-new-build.txt1
-rw-r--r--indra/llaudio/CMakeLists.txt4
-rw-r--r--indra/llaudio/llaudioengine_openal.cpp2
-rw-r--r--indra/llcharacter/lljoint.cpp6
-rw-r--r--indra/llcharacter/lljoint.h6
-rw-r--r--indra/llcommon/llapp.cpp2
-rw-r--r--indra/llcommon/llapr.cpp2
-rw-r--r--indra/llcommon/llcleanup.cpp7
-rw-r--r--indra/llcommon/llcleanup.h13
-rw-r--r--indra/llcommon/llcommon.cpp2
-rw-r--r--indra/llcommon/llerror.cpp84
-rw-r--r--indra/llcommon/llerrorcontrol.h5
-rw-r--r--indra/llcommon/llsingleton.cpp31
-rw-r--r--indra/llcorehttp/_httpoprequest.cpp19
-rw-r--r--indra/llinventory/llinventory.cpp349
-rw-r--r--indra/llinventory/llinventory.h9
-rw-r--r--indra/llinventory/llinventorysettings.cpp26
-rw-r--r--indra/llinventory/llinventorysettings.h13
-rw-r--r--indra/llinventory/llpermissions.cpp142
-rw-r--r--indra/llinventory/llpermissions.h4
-rw-r--r--indra/llinventory/llsaleinfo.cpp73
-rw-r--r--indra/llinventory/llsaleinfo.h5
-rw-r--r--indra/llinventory/llsettingsbase.h1
-rw-r--r--indra/llinventory/llsettingssky.cpp3
-rw-r--r--indra/llinventory/tests/inventorymisc_test.cpp72
-rw-r--r--indra/llmath/llvector4a.h5
-rw-r--r--indra/llmessage/llcoproceduremanager.cpp30
-rw-r--r--indra/llmessage/llexperiencecache.cpp16
-rw-r--r--indra/llmessage/llexperiencecache.h2
-rw-r--r--indra/llmessage/llteleportflags.h2
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp6
-rw-r--r--indra/llplugin/llpluginclassmedia.h2
-rw-r--r--indra/llplugin/llpluginprocesschild.cpp12
-rw-r--r--indra/llprimitive/lldaeloader.cpp139
-rw-r--r--indra/llprimitive/lldaeloader.h2
-rw-r--r--indra/llprimitive/llmodelloader.cpp38
-rw-r--r--indra/llprimitive/llmodelloader.h18
-rw-r--r--indra/llrender/llgl.cpp7
-rw-r--r--indra/llrender/llimagegl.cpp80
-rw-r--r--indra/llrender/llrender.cpp88
-rw-r--r--indra/llrender/llrendertarget.cpp10
-rw-r--r--indra/llrender/llshadermgr.cpp2
-rw-r--r--indra/llrender/llvertexbuffer.cpp32
-rw-r--r--indra/llui/llaccordionctrl.cpp32
-rw-r--r--indra/llui/llaccordionctrl.h5
-rw-r--r--indra/llui/llaccordionctrltab.cpp29
-rw-r--r--indra/llui/llaccordionctrltab.h1
-rw-r--r--indra/llui/llbadgeowner.cpp8
-rw-r--r--indra/llui/llbadgeowner.h1
-rw-r--r--indra/llui/llbutton.cpp27
-rw-r--r--indra/llui/llbutton.h1
-rw-r--r--indra/llui/llcombobox.cpp8
-rw-r--r--indra/llui/llcombobox.h2
-rw-r--r--indra/llui/llfolderview.cpp4
-rw-r--r--indra/llui/llfolderviewitem.cpp74
-rw-r--r--indra/llui/llfolderviewitem.h10
-rw-r--r--indra/llui/llfolderviewmodel.cpp3
-rw-r--r--indra/llui/llfolderviewmodel.h12
-rw-r--r--indra/llui/lllineeditor.cpp1
-rw-r--r--indra/llui/llmultisliderctrl.cpp1
-rw-r--r--indra/llui/llnotifications.cpp32
-rw-r--r--indra/llui/llnotifications.h2
-rw-r--r--indra/llui/llscrolllistctrl.cpp3
-rw-r--r--indra/llui/llscrolllistctrl.h1
-rw-r--r--indra/llui/llsliderctrl.cpp1
-rw-r--r--indra/llui/llspellcheck.cpp8
-rw-r--r--indra/llui/llspellcheck.h1
-rw-r--r--indra/llui/llspinctrl.cpp3
-rw-r--r--indra/llui/lltabcontainer.cpp13
-rw-r--r--indra/llui/lltabcontainer.h8
-rw-r--r--indra/llui/lltextbase.cpp45
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/lluictrl.cpp3
-rw-r--r--indra/llui/llurlentry.cpp16
-rw-r--r--indra/llui/llview.cpp10
-rw-r--r--indra/llui/llview.h1
-rw-r--r--indra/llwindow/llopenglview-objc.mm4
-rw-r--r--indra/llwindow/llwindowwin32.cpp21
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp25
-rw-r--r--indra/newview/CMakeLists.txt27
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/settings.xml19
-rw-r--r--indra/newview/app_settings/settings_per_account.xml11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl280
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl49
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialF.glsl882
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/moonF.glsl39
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/moonV.glsl11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl203
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyV.glsl182
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl34
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl16
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/previewV.glsl1
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleV.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl168
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/moonF.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/moonV.glsl9
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/skyF.glsl149
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl193
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl277
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/skyV.glsl184
-rw-r--r--indra/newview/llaccountingcostmanager.h6
-rw-r--r--indra/newview/llagent.cpp4
-rw-r--r--indra/newview/llagent.h7
-rw-r--r--indra/newview/llagentcamera.cpp12
-rw-r--r--indra/newview/llagentwearables.cpp7
-rw-r--r--indra/newview/llaisapi.cpp48
-rw-r--r--indra/newview/llaisapi.h4
-rw-r--r--indra/newview/llappcorehttp.cpp22
-rw-r--r--indra/newview/llappdelegate-objc.mm1
-rw-r--r--indra/newview/llappearancemgr.cpp57
-rw-r--r--indra/newview/llappviewer.cpp85
-rw-r--r--indra/newview/llappviewer.h7
-rw-r--r--indra/newview/llappviewerlistener.cpp2
-rw-r--r--indra/newview/llappviewermacosx-for-objc.h1
-rw-r--r--indra/newview/llappviewermacosx.cpp9
-rw-r--r--indra/newview/llappviewerwin32.cpp3
-rw-r--r--indra/newview/llattachmentsmgr.h2
-rw-r--r--indra/newview/llavatariconctrl.h1
-rw-r--r--indra/newview/llavatarlistitem.h2
-rw-r--r--indra/newview/llchatbar.cpp1
-rw-r--r--indra/newview/llchathistory.cpp1
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp1
-rw-r--r--indra/newview/llchatitemscontainerctrl.h3
-rw-r--r--indra/newview/llchiclet.cpp5
-rw-r--r--indra/newview/llcofwearables.cpp21
-rw-r--r--indra/newview/llcolorswatch.h1
-rw-r--r--indra/newview/llcommandlineparser.cpp31
-rw-r--r--indra/newview/llcompilequeue.cpp18
-rw-r--r--indra/newview/llcompilequeue.h3
-rw-r--r--indra/newview/llconversationlog.cpp16
-rw-r--r--indra/newview/llconversationmodel.cpp17
-rw-r--r--indra/newview/llconversationmodel.h1
-rw-r--r--indra/newview/llconversationview.cpp8
-rw-r--r--indra/newview/llconversationview.h1
-rw-r--r--indra/newview/lldrawable.cpp55
-rw-r--r--indra/newview/lldrawpool.cpp15
-rw-r--r--indra/newview/lldrawpool.h13
-rw-r--r--indra/newview/lldrawpoolalpha.cpp6
-rw-r--r--indra/newview/lldrawpoolavatar.cpp35
-rw-r--r--indra/newview/lldrawpoolavatar.h4
-rw-r--r--indra/newview/lldrawpoolground.cpp5
-rw-r--r--indra/newview/lldrawpoolground.h2
-rw-r--r--indra/newview/lldrawpoolsky.cpp16
-rw-r--r--indra/newview/lldrawpoolsky.h2
-rw-r--r--indra/newview/lldrawpoolterrain.cpp7
-rw-r--r--indra/newview/lldrawpoolterrain.h2
-rw-r--r--indra/newview/lldrawpooltree.cpp5
-rw-r--r--indra/newview/lldrawpooltree.h2
-rw-r--r--indra/newview/lldrawpoolwater.cpp9
-rw-r--r--indra/newview/lldrawpoolwater.h1
-rw-r--r--indra/newview/lldrawpoolwlsky.cpp19
-rw-r--r--indra/newview/lldrawpoolwlsky.h2
-rw-r--r--indra/newview/lldynamictexture.cpp10
-rw-r--r--indra/newview/llenvironment.cpp86
-rw-r--r--indra/newview/llenvironment.h5
-rw-r--r--indra/newview/llface.cpp24
-rw-r--r--indra/newview/llface.h10
-rw-r--r--indra/newview/llfloaterbuycurrency.cpp37
-rw-r--r--indra/newview/llfloaterconversationpreview.cpp2
-rw-r--r--indra/newview/llfloatereditextdaycycle.cpp2
-rw-r--r--indra/newview/llfloaterfixedenvironment.cpp2
-rw-r--r--indra/newview/llfloaterimagepreview.cpp11
-rw-r--r--indra/newview/llfloaterimcontainer.cpp90
-rw-r--r--indra/newview/llfloaterimcontainer.h6
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp15
-rw-r--r--indra/newview/llfloaterimsessiontab.h2
-rw-r--r--indra/newview/llfloaterloadprefpreset.cpp10
-rw-r--r--indra/newview/llfloatermodelpreview.cpp3918
-rw-r--r--indra/newview/llfloatermodelpreview.h270
-rw-r--r--indra/newview/llfloaterperms.cpp3
-rw-r--r--indra/newview/llfloaterpreference.cpp37
-rw-r--r--indra/newview/llfloaterreporter.cpp2
-rw-r--r--indra/newview/llfloatersaveprefpreset.cpp5
-rw-r--r--indra/newview/llfloatersnapshot.h1
-rw-r--r--indra/newview/llfloaterworldmap.h1
-rw-r--r--indra/newview/llgroupmgr.cpp100
-rw-r--r--indra/newview/llgroupmgr.h6
-rw-r--r--indra/newview/llhudnametag.cpp61
-rw-r--r--indra/newview/llhudnametag.h2
-rw-r--r--indra/newview/llhudobject.h2
-rw-r--r--indra/newview/llhudtext.cpp5
-rw-r--r--indra/newview/llimprocessing.cpp4
-rw-r--r--indra/newview/llimview.cpp7
-rw-r--r--indra/newview/llinventorybridge.cpp27
-rw-r--r--indra/newview/llinventoryfilter.cpp90
-rw-r--r--indra/newview/llinventoryfunctions.cpp45
-rw-r--r--indra/newview/llinventoryfunctions.h4
-rw-r--r--indra/newview/llinventorymodel.cpp215
-rw-r--r--indra/newview/llinventorypanel.cpp152
-rw-r--r--indra/newview/llinventorypanel.h78
-rw-r--r--indra/newview/lllandmarklist.cpp45
-rw-r--r--indra/newview/lllandmarklist.h7
-rw-r--r--indra/newview/lllogchat.cpp20
-rw-r--r--indra/newview/llmaniprotate.cpp23
-rw-r--r--indra/newview/llmaniprotate.h1
-rw-r--r--indra/newview/llmeshrepository.cpp212
-rw-r--r--indra/newview/llmeshrepository.h11
-rw-r--r--indra/newview/llmodelpreview.cpp3570
-rw-r--r--indra/newview/llmodelpreview.h313
-rw-r--r--indra/newview/lloutfitgallery.cpp1
-rw-r--r--indra/newview/llpanelavatar.cpp1
-rw-r--r--indra/newview/llpanelexperiences.cpp13
-rw-r--r--indra/newview/llpanelexperiences.h2
-rw-r--r--indra/newview/llpanelface.cpp34
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp55
-rw-r--r--indra/newview/llpanellandmarkinfo.h2
-rw-r--r--indra/newview/llpanellandmarks.cpp6
-rw-r--r--indra/newview/llpanellogin.cpp18
-rw-r--r--indra/newview/llpanelmarketplaceinboxinventory.cpp74
-rw-r--r--indra/newview/llpanelmarketplaceinboxinventory.h19
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp2
-rw-r--r--indra/newview/llpanelplaceinfo.cpp65
-rw-r--r--indra/newview/llpanelplaceinfo.h2
-rw-r--r--indra/newview/llpanelplaceprofile.cpp8
-rw-r--r--indra/newview/llpanelplaceprofile.h2
-rw-r--r--indra/newview/llpanelplaces.cpp15
-rw-r--r--indra/newview/llpanelplaces.h1
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp13
-rw-r--r--indra/newview/llpanelprimmediacontrols.h4
-rw-r--r--indra/newview/llpanelwearing.cpp48
-rw-r--r--indra/newview/llplacesinventorypanel.cpp3
-rw-r--r--indra/newview/llplacesinventorypanel.h8
-rw-r--r--indra/newview/llpresetsmanager.h1
-rw-r--r--indra/newview/llpreviewnotecard.cpp1
-rw-r--r--indra/newview/llprogressview.cpp13
-rw-r--r--indra/newview/llremoteparcelrequest.h2
-rw-r--r--indra/newview/llsearchableui.cpp14
-rw-r--r--indra/newview/llsearchableui.h1
-rw-r--r--indra/newview/llsecapi.cpp9
-rw-r--r--indra/newview/llsecapi.h17
-rw-r--r--indra/newview/llsechandler_basic.cpp18
-rw-r--r--indra/newview/llselectmgr.cpp105
-rw-r--r--indra/newview/llselectmgr.h9
-rw-r--r--indra/newview/llsettingsvo.cpp11
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp36
-rw-r--r--indra/newview/llspatialpartition.cpp12
-rw-r--r--indra/newview/llspatialpartition.h24
-rw-r--r--indra/newview/llstartup.cpp28
-rw-r--r--indra/newview/lltexturecache.cpp7
-rw-r--r--indra/newview/lltexturectrl.cpp36
-rw-r--r--indra/newview/lltexturectrl.h6
-rw-r--r--indra/newview/lltexturefetch.cpp5
-rw-r--r--indra/newview/lltexturefetch.h1
-rw-r--r--indra/newview/lltextureview.cpp2
-rw-r--r--indra/newview/lltoolgrab.cpp5
-rw-r--r--indra/newview/lltoolgrab.h1
-rw-r--r--indra/newview/lltoolpie.cpp4
-rw-r--r--indra/newview/llviewerassetstorage.cpp1
-rw-r--r--indra/newview/llviewercontrol.cpp10
-rw-r--r--indra/newview/llviewerdisplay.cpp111
-rw-r--r--indra/newview/llviewerinventory.cpp133
-rw-r--r--indra/newview/llviewerinventory.h13
-rw-r--r--indra/newview/llviewerjointmesh.cpp16
-rw-r--r--indra/newview/llviewermedia.cpp17
-rw-r--r--indra/newview/llviewermediafocus.cpp8
-rw-r--r--indra/newview/llviewermediafocus.h2
-rw-r--r--indra/newview/llviewermenu.cpp70
-rw-r--r--indra/newview/llviewermenu.h5
-rw-r--r--indra/newview/llviewermenufile.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp4
-rw-r--r--indra/newview/llviewerobject.cpp26
-rw-r--r--indra/newview/llviewerobject.h3
-rw-r--r--indra/newview/llviewerparcelaskplay.cpp5
-rw-r--r--indra/newview/llviewerparcelmgr.cpp5
-rw-r--r--indra/newview/llviewerregion.cpp45
-rw-r--r--indra/newview/llviewerregion.h8
-rw-r--r--indra/newview/llviewershadermgr.cpp9
-rw-r--r--indra/newview/llviewertexlayer.cpp2
-rw-r--r--indra/newview/llviewertexture.cpp9
-rw-r--r--indra/newview/llviewerwindow.cpp13
-rw-r--r--indra/newview/llvoavatar.cpp110
-rw-r--r--indra/newview/llvoavatar.h5
-rw-r--r--indra/newview/llvoavatarself.cpp5
-rw-r--r--indra/newview/llvocache.cpp51
-rw-r--r--indra/newview/llvoiceclient.cpp7
-rw-r--r--indra/newview/llvoiceclient.h6
-rw-r--r--indra/newview/llvoicevivox.cpp87
-rw-r--r--indra/newview/llvoicevivox.h2
-rw-r--r--indra/newview/llvovolume.cpp55
-rw-r--r--indra/newview/llvovolume.h2
-rw-r--r--indra/newview/llvowater.cpp2
-rw-r--r--indra/newview/llvowlsky.cpp3
-rw-r--r--indra/newview/llwearableitemslist.cpp18
-rw-r--r--indra/newview/llworld.cpp20
-rw-r--r--indra/newview/llxmlrpctransaction.cpp10
-rw-r--r--indra/newview/pipeline.cpp2327
-rw-r--r--indra/newview/pipeline.h5
-rwxr-xr-xindra/newview/res/viewerRes.rc2
-rw-r--r--indra/newview/skins/default/colors.xml3
-rw-r--r--indra/newview/skins/default/textures/containers/TabTop_Right_Flashing.pngbin0 -> 252 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/da/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/da/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/da/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/da/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/da/menu_wearing_tab.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/de/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/de/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/de/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/de/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/de/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/de/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/de/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/de/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml8
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_setup.xml2
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml16
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_currency.xml42
-rw-r--r--indra/newview/skins/default/xui/en/floater_image_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_inspect.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml591
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_debug.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_ctrl.xml60
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_cof_attachment.xml20
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml24
-rw-r--r--indra/newview/skins/default/xui/en/menu_script_chiclet.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml10
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearable_list_item.xml19
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_gear.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_wearing_tab.xml25
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml37
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml87
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_place_profile.xml51
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml93
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml4
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_appearance.xml6
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_item_info.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/es/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/es/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/es/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/es/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/es/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/es/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/es/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/es/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_advanced.xml2
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml8
-rw-r--r--indra/newview/skins/default/xui/es/strings.xml7
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/fr/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/fr/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/fr/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/fr/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/fr/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml8
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml16
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/it/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/it/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/it/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/it/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/it/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/it/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/it/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/it/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml6
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_setup.xml2
-rw-r--r--indra/newview/skins/default/xui/it/strings.xml16
-rw-r--r--indra/newview/skins/default/xui/ja/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/ja/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/ja/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/ja/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/ja/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/ja/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml16
-rw-r--r--indra/newview/skins/default/xui/pl/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml11
-rw-r--r--indra/newview/skins/default/xui/pl/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/pl/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/pl/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/pl/menu_wearing_tab.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/pt/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/pt/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/pt/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/pt/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/pt/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml8
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_setup.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml10
-rw-r--r--indra/newview/skins/default/xui/ru/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/ru/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/ru/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/ru/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/ru/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/ru/notifications.xml46
-rw-r--r--indra/newview/skins/default/xui/ru/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/ru/panel_preferences_advanced.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/strings.xml16
-rw-r--r--indra/newview/skins/default/xui/tr/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/tr/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/tr/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/tr/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/tr/menu_wearing_tab.xml3
-rw-r--r--indra/newview/skins/default/xui/tr/notifications.xml38
-rw-r--r--indra/newview/skins/default/xui/tr/panel_people.xml4
-rw-r--r--indra/newview/skins/default/xui/tr/strings.xml10
-rw-r--r--indra/newview/skins/default/xui/zh/floater_buy_currency.xml5
-rw-r--r--indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml12
-rw-r--r--indra/newview/skins/default/xui/zh/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/default/xui/zh/menu_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml1
-rw-r--r--indra/newview/skins/default/xui/zh/menu_wearing_gear.xml4
-rw-r--r--indra/newview/skins/default/xui/zh/menu_wearing_tab.xml3
-rw-r--r--indra/newview/tests/llsechandler_basic_test.cpp8
-rwxr-xr-xindra/newview/viewer_manifest.py8
-rw-r--r--indra/test/llpermissions_tut.cpp50
-rw-r--r--indra/test/llsaleinfo_tut.cpp52
440 files changed, 11747 insertions, 9123 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 865c057e33..8aea50e02b 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -63,7 +63,13 @@ if (WINDOWS)
# Without PreferredToolArchitecture=x64, as of 2020-06-26 the 32-bit
# compiler on our TeamCity build hosts has started running out of virtual
# memory for the precompiled header file.
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /p:PreferredToolArchitecture=x64")
+ # CP changed to only append the flag for 32bit builds - on 64bit builds,
+ # locally at least, the build output is spammed with 1000s of 'D9002'
+ # warnings about this switch being ignored.
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+ if( ADDRESS_SIZE EQUAL 32 )
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
+ endif()
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo"
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 429bda473b..8efad33f71 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -82,6 +82,10 @@ if(WINDOWS)
set(release_files ${release_files} fmod.dll)
endif (FMODSTUDIO)
+ if (OPENAL)
+ list(APPEND release_files openal32.dll alut.dll)
+ endif (OPENAL)
+
#*******************************
# Copy MS C runtime dlls, required for packaging.
if (MSVC80)
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index e69de29bb2..48082f72f0 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -0,0 +1 @@
+12
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index 8b628a058e..558ede7bf6 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -60,6 +60,10 @@ if (FMODSTUDIO)
endif (FMODSTUDIO)
if (OPENAL)
+ include_directories(
+ ${OPENAL_LIBRARIES}
+ )
+
list(APPEND llaudio_SOURCE_FILES
llaudioengine_openal.cpp
lllistener_openal.cpp
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
index a38d8291fa..3bdd0302ee 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -55,7 +55,7 @@ LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata, const std::string &app_title)
{
mWindGen = NULL;
- LLAudioEngine::init(num_channels, userdata);
+ LLAudioEngine::init(num_channels, userdata, app_title);
if(!alutInit(NULL, NULL))
{
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index a685df5925..dee642310e 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -408,7 +408,7 @@ void showJointScaleOverrides( const LLJoint& joint, const std::string& note, con
bool LLJoint::aboveJointPosThreshold(const LLVector3& pos) const
{
LLVector3 diff = pos - getDefaultPosition();
- const F32 max_joint_pos_offset = 0.0001f; // 0.1 mm
+ const F32 max_joint_pos_offset = LL_JOINT_TRESHOLD_POS_OFFSET; // 0.1 mm
return diff.lengthSquared() > max_joint_pos_offset * max_joint_pos_offset;
}
@@ -511,7 +511,7 @@ void LLJoint::clearAttachmentPosOverrides()
// getAllAttachmentPosOverrides()
//--------------------------------------------------------------------
void LLJoint::getAllAttachmentPosOverrides(S32& num_pos_overrides,
- std::set<LLVector3>& distinct_pos_overrides)
+ std::set<LLVector3>& distinct_pos_overrides) const
{
num_pos_overrides = m_attachmentPosOverrides.count();
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentPosOverrides.getMap().begin();
@@ -525,7 +525,7 @@ void LLJoint::getAllAttachmentPosOverrides(S32& num_pos_overrides,
// getAllAttachmentScaleOverrides()
//--------------------------------------------------------------------
void LLJoint::getAllAttachmentScaleOverrides(S32& num_scale_overrides,
- std::set<LLVector3>& distinct_scale_overrides)
+ std::set<LLVector3>& distinct_scale_overrides) const
{
num_scale_overrides = m_attachmentScaleOverrides.count();
LLVector3OverrideMap::map_type::const_iterator it = m_attachmentScaleOverrides.getMap().begin();
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index aa997a4cf7..1b646b641f 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -53,6 +53,8 @@ const U32 LL_FACE_JOINT_NUM = (LL_CHARACTER_MAX_ANIMATED_JOINTS-2);
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
const F32 LL_MAX_PELVIS_OFFSET = 5.f;
+const F32 LL_JOINT_TRESHOLD_POS_OFFSET = 0.0001f; //0.1 mm
+
class LLVector3OverrideMap
{
public:
@@ -287,9 +289,9 @@ public:
void showAttachmentScaleOverrides(const std::string& av_info) const;
void getAllAttachmentPosOverrides(S32& num_pos_overrides,
- std::set<LLVector3>& distinct_pos_overrides);
+ std::set<LLVector3>& distinct_pos_overrides) const;
void getAllAttachmentScaleOverrides(S32& num_scale_overrides,
- std::set<LLVector3>& distinct_scale_overrides);
+ std::set<LLVector3>& distinct_scale_overrides) const;
// These are used in checks of whether a pos/scale override is considered significant.
bool aboveJointPosThreshold(const LLVector3& pos) const;
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 3dab632aef..a90b294550 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -180,7 +180,7 @@ LLApp::~LLApp()
if(mExceptionHandler != 0) delete mExceptionHandler;
- SUBSYSTEM_CLEANUP(LLCommon);
+ SUBSYSTEM_CLEANUP_DBG(LLCommon);
}
// static
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 984e90f376..db94765871 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -68,7 +68,7 @@ void ll_cleanup_apr()
{
gAPRInitialized = false;
- LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
+ LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL;
LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
diff --git a/indra/llcommon/llcleanup.cpp b/indra/llcommon/llcleanup.cpp
index c5283507bf..1f34c2036a 100644
--- a/indra/llcommon/llcleanup.cpp
+++ b/indra/llcommon/llcleanup.cpp
@@ -20,10 +20,13 @@
#include "llerror.h"
#include "llerrorcontrol.h"
-void log_subsystem_cleanup(const char* file, int line, const char* function,
+void log_subsystem_cleanup(LLError::ELevel level,
+ const char* file,
+ int line,
+ const char* function,
const char* classname)
{
- LL_INFOS("Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): "
+ LL_VLOGS(level, "Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): "
<< "calling " << classname << "::cleanupClass() in "
<< function << LL_ENDL;
}
diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h
index a319171b5f..0f567ed5f6 100644
--- a/indra/llcommon/llcleanup.h
+++ b/indra/llcommon/llcleanup.h
@@ -21,13 +21,22 @@
// shutdown schemes.
#define SUBSYSTEM_CLEANUP(CLASSNAME) \
do { \
- log_subsystem_cleanup(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \
+ log_subsystem_cleanup(LLError::LEVEL_INFO, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \
+ CLASSNAME::cleanupClass(); \
+ } while (0)
+
+#define SUBSYSTEM_CLEANUP_DBG(CLASSNAME) \
+ do { \
+ log_subsystem_cleanup(LLError::LEVEL_DEBUG, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \
CLASSNAME::cleanupClass(); \
} while (0)
// Use ancient do { ... } while (0) macro trick to permit a block of
// statements with the same syntax as a single statement.
-void log_subsystem_cleanup(const char* file, int line, const char* function,
+void log_subsystem_cleanup(LLError::ELevel level,
+ const char* file,
+ int line,
+ const char* function,
const char* classname);
#endif /* ! defined(LL_LLCLEANUP_H) */
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 2d665c611b..96be913d17 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -63,7 +63,7 @@ void LLCommon::cleanupClass()
sMasterThreadRecorder = NULL;
LLTrace::set_master_thread_recorder(NULL);
LLThreadSafeRefCount::cleanupThreadSafeRefCount();
- SUBSYSTEM_CLEANUP(LLTimer);
+ SUBSYSTEM_CLEANUP_DBG(LLTimer);
if (sAprInitialized)
{
ll_cleanup_apr();
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 411412c883..f876b8ee4a 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -332,12 +332,9 @@ namespace LLError
}
// huh, that's odd, we should see one or the other prefix -- but don't
// try to log unless logging is already initialized
- if (is_available())
- {
- // in Python, " or ".join(vector) -- but in C++, a PITB
- LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '"
- << name << "'" << LL_ENDL;
- }
+ // in Python, " or ".join(vector) -- but in C++, a PITB
+ LL_DEBUGS() << "Did not see 'class' or 'struct' prefix on '"
+ << name << "'" << LL_ENDL;
return name;
#else // neither GCC nor Visual Studio
@@ -438,9 +435,12 @@ namespace
typedef std::vector<LLError::RecorderPtr> Recorders;
typedef std::vector<LLError::CallSite*> CallSiteVector;
- class Globals : public LLSingleton<Globals>
+ class Globals
{
- LLSINGLETON(Globals);
+ public:
+ static Globals* getInstance();
+ protected:
+ Globals();
public:
std::ostringstream messageStream;
bool messageStreamInUse;
@@ -460,6 +460,16 @@ namespace
{
}
+ Globals* Globals::getInstance()
+ {
+ // According to C++11 Function-Local Initialization
+ // of static variables is supposed to be thread safe
+ // without risk of deadlocks.
+ static Globals inst;
+
+ return &inst;
+ }
+
void Globals::addCallSite(LLError::CallSite& site)
{
callSites.push_back(&site);
@@ -512,14 +522,17 @@ namespace LLError
typedef LLPointer<SettingsConfig> SettingsConfigPtr;
- class Settings : public LLSingleton<Settings>
+ class Settings
{
- LLSINGLETON(Settings);
+ public:
+ static Settings* getInstance();
+ protected:
+ Settings();
public:
SettingsConfigPtr getSettingsConfig();
void reset();
- SettingsStoragePtr saveAndReset();
+ SettingsStoragePtr saveAndReset();
void restore(SettingsStoragePtr pSettingsStorage);
private:
@@ -553,6 +566,16 @@ namespace LLError
{
}
+ Settings* Settings::getInstance()
+ {
+ // According to C++11 Function-Local Initialization
+ // of static variables is supposed to be thread safe
+ // without risk of deadlocks.
+ static Settings inst;
+
+ return &inst;
+ }
+
SettingsConfigPtr Settings::getSettingsConfig()
{
return mSettingsConfig;
@@ -577,11 +600,6 @@ namespace LLError
SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
mSettingsConfig = newSettingsConfig;
}
-
- bool is_available()
- {
- return Settings::instanceExists() && Globals::instanceExists();
- }
}
namespace LLError
@@ -1028,7 +1046,7 @@ namespace LLError
std::pair<boost::shared_ptr<RECORDER>, Recorders::iterator>
findRecorderPos()
{
- SettingsConfigPtr s = Settings::instance().getSettingsConfig();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
// Since we promise to return an iterator, use a classic iterator
// loop.
auto end{s->mRecorders.end()};
@@ -1071,7 +1089,7 @@ namespace LLError
auto found = findRecorderPos<RECORDER>();
if (found.first)
{
- SettingsConfigPtr s = Settings::instance().getSettingsConfig();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
s->mRecorders.erase(found.second);
}
return bool(found.first);
@@ -1307,14 +1325,6 @@ namespace LLError
return false;
}
- // If we hit a logging request very late during shutdown processing,
- // when either of the relevant LLSingletons has already been deleted,
- // DO NOT resurrect them.
- if (Settings::wasDeleted() || Globals::wasDeleted())
- {
- return false;
- }
-
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
s->mShouldLogCallCounter++;
@@ -1353,10 +1363,8 @@ namespace LLError
std::ostringstream* Log::out()
{
LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
- // If we hit a logging request very late during shutdown processing,
- // when either of the relevant LLSingletons has already been deleted,
- // DO NOT resurrect them.
- if (lock.isLocked() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
+
+ if (lock.isLocked())
{
Globals* g = Globals::getInstance();
@@ -1378,14 +1386,6 @@ namespace LLError
return;
}
- // If we hit a logging request very late during shutdown processing,
- // when either of the relevant LLSingletons has already been deleted,
- // DO NOT resurrect them.
- if (Settings::wasDeleted() || Globals::wasDeleted())
- {
- return;
- }
-
if(strlen(out->str().c_str()) < 128)
{
strcpy(message, out->str().c_str());
@@ -1418,14 +1418,6 @@ namespace LLError
return;
}
- // If we hit a logging request very late during shutdown processing,
- // when either of the relevant LLSingletons has already been deleted,
- // DO NOT resurrect them.
- if (Settings::wasDeleted() || Globals::wasDeleted())
- {
- return;
- }
-
Globals* g = Globals::getInstance();
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index bfa2269025..25786d5457 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -203,11 +203,6 @@ namespace LLError
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
LL_COMMON_API int shouldLogCallCount();
-
- // Check whether Globals exists. This should only be used by LLSingleton
- // infrastructure to avoid trying to log when our internal LLSingleton is
- // unavailable -- circularity ensues.
- LL_COMMON_API bool is_available();
};
#endif // LL_LLERRORCONTROL_H
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index d3d25201b2..83a4b64e8f 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -28,7 +28,7 @@
#include "llsingleton.h"
#include "llerror.h"
-#include "llerrorcontrol.h" // LLError::is_available()
+#include "llerrorcontrol.h"
#include "lldependencies.h"
#include "llexception.h"
#include "llcoros.h"
@@ -41,8 +41,6 @@
namespace {
void log(LLError::ELevel level,
const char* p1, const char* p2, const char* p3, const char* p4);
-
-bool oktolog();
} // anonymous namespace
// Our master list of all LLSingletons is itself an LLSingleton. We used to
@@ -279,8 +277,6 @@ void LLSingletonBase::reset_initializing(list_t::size_type size)
void LLSingletonBase::MasterList::LockedInitializing::log(const char* verb, const char* name)
{
- if (oktolog())
- {
LL_DEBUGS("LLSingleton") << verb << ' ' << demangle(name) << ';';
if (mList)
{
@@ -292,7 +288,6 @@ void LLSingletonBase::MasterList::LockedInitializing::log(const char* verb, cons
}
}
LL_ENDL;
- }
}
void LLSingletonBase::capture_dependency()
@@ -455,33 +450,11 @@ void LLSingletonBase::deleteAll()
/*---------------------------- Logging helpers -----------------------------*/
namespace {
-bool oktolog()
-{
- // See comments in log() below.
- return LLError::is_available();
-}
void log(LLError::ELevel level,
const char* p1, const char* p2, const char* p3, const char* p4)
{
- // The is_available() test below ensures that we'll stop logging once
- // LLError has been cleaned up. If we had a similar portable test for
- // std::cerr, this would be a good place to use it.
-
- // Check LLError::is_available() because some of LLError's infrastructure
- // is itself an LLSingleton. If that LLSingleton has not yet been
- // initialized, trying to log will engage LLSingleton machinery... and
- // around and around we go.
- if (LLError::is_available())
- {
- LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL;
- }
- else
- {
- // Caller may be a test program, or something else whose stderr is
- // visible to the user.
- std::cerr << p1 << p2 << p3 << p4 << std::endl;
- }
+ LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL;
}
} // anonymous namespace
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 0f76ff23ea..7bea8e9f9c 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -1007,11 +1007,20 @@ CURLcode HttpOpRequest::curlSslCtxCallback(CURL *curl, void *sslctx, void *userd
{
HttpOpRequest::ptr_t op(HttpOpRequest::fromHandle<HttpOpRequest>(userdata));
- if (op->mCallbackSSLVerify)
- {
- SSL_CTX * ctx = (SSL_CTX *)sslctx;
- // disable any default verification for server certs
- SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+ if (op->mCallbackSSLVerify)
+ {
+ SSL_CTX * ctx = (SSL_CTX *)sslctx;
+ if (op->mReqOptions && op->mReqOptions->getSSLVerifyPeer())
+ {
+ // verification for ssl certs
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+ }
+ else
+ {
+ // disable any default verification for server certs
+ // Ex: setting urls (assume non-SL) for parcel media in LLFloaterURLEntry
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+ }
// set the verification callback.
SSL_CTX_set_cert_verify_callback(ctx, sslCertVerifyCallback, userdata);
// the calls are void
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 11647c5518..18bc1b5a91 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -41,7 +41,7 @@
/// Exported functions
///----------------------------------------------------------------------------
static const std::string INV_ITEM_ID_LABEL("item_id");
-static const std::string INV_FOLDER_ID_LABEL("folder_id");
+static const std::string INV_FOLDER_ID_LABEL("cat_id");
static const std::string INV_PARENT_ID_LABEL("parent_id");
static const std::string INV_ASSET_TYPE_LABEL("type");
static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
@@ -228,22 +228,6 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
return TRUE;
}
-// exportFile should be replaced with exportLegacyStream
-// not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get icramented...
-BOOL LLInventoryObject::exportFile(LLFILE* fp, BOOL) const
-{
- std::string uuid_str;
- fprintf(fp, "\tinv_object\t0\n\t{\n");
- mUUID.toString(uuid_str);
- fprintf(fp, "\t\tobj_id\t%s\n", uuid_str.c_str());
- mParentUUID.toString(uuid_str);
- fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
- fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
- fprintf(fp,"\t}\n");
- return TRUE;
-}
-
BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) const
{
std::string uuid_str;
@@ -604,215 +588,6 @@ BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32
}
// virtual
-BOOL LLInventoryItem::importFile(LLFILE* fp)
-{
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
- char junk[MAX_STRING]; /* Flawfinder: ignore */
- BOOL success = TRUE;
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
-
- mInventoryType = LLInventoryType::IT_NONE;
- mAssetUUID.setNull();
- while(success && (!feof(fp)))
- {
- if (fgets(buffer, MAX_STRING, fp) == NULL)
- {
- buffer[0] = '\0';
- }
-
- sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("item_id", keyword))
- {
- mUUID.set(valuestr);
- }
- else if(0 == strcmp("parent_id", keyword))
- {
- mParentUUID.set(valuestr);
- }
- else if(0 == strcmp("permissions", keyword))
- {
- success = mPermissions.importFile(fp);
- }
- else if(0 == strcmp("sale_info", keyword))
- {
- // Sale info used to contain next owner perm. It is now in
- // the permissions. Thus, we read that out, and fix legacy
- // objects. It's possible this op would fail, but it
- // should pick up the vast majority of the tasks.
- BOOL has_perm_mask = FALSE;
- U32 perm_mask = 0;
- success = mSaleInfo.importFile(fp, has_perm_mask, perm_mask);
- if(has_perm_mask)
- {
- if(perm_mask == PERM_NONE)
- {
- perm_mask = mPermissions.getMaskOwner();
- }
- // fair use fix.
- if(!(perm_mask & PERM_COPY))
- {
- perm_mask |= PERM_TRANSFER;
- }
- mPermissions.setMaskNext(perm_mask);
- }
- }
- else if(0 == strcmp("shadow_id", keyword))
- {
- mAssetUUID.set(valuestr);
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
- }
- else if(0 == strcmp("asset_id", keyword))
- {
- mAssetUUID.set(valuestr);
- }
- else if(0 == strcmp("type", keyword))
- {
- mType = LLAssetType::lookup(valuestr);
- }
- else if(0 == strcmp("inv_type", keyword))
- {
- mInventoryType = LLInventoryType::lookup(std::string(valuestr));
- }
- else if(0 == strcmp("flags", keyword))
- {
- sscanf(valuestr, "%x", &mFlags);
- }
- else if(0 == strcmp("name", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s%254[\t]%254[^|]",
- keyword, junk, valuestr);
-
- // IW: sscanf chokes and puts | in valuestr if there's no name
- if (valuestr[0] == '|')
- {
- valuestr[0] = '\000';
- }
-
- mName.assign(valuestr);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
- else if(0 == strcmp("desc", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s%254[\t]%254[^|]",
- keyword, junk, valuestr);
-
- if (valuestr[0] == '|')
- {
- valuestr[0] = '\000';
- }
-
- disclaimMem(mDescription);
- mDescription.assign(valuestr);
- claimMem(mDescription);
- LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
- /* TODO -- ask Ian about this code
- const char *donkey = mDescription.c_str();
- if (donkey[0] == '|')
- {
- LL_ERRS() << "Donkey" << LL_ENDL;
- }
- */
- }
- else if(0 == strcmp("creation_date", keyword))
- {
- S32 date;
- sscanf(valuestr, "%d", &date);
- mCreationDate = date;
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in inventory import of item " << mUUID << LL_ENDL;
- }
- }
-
- // Need to convert 1.0 simstate files to a useful inventory type
- // and potentially deal with bad inventory tyes eg, a landmark
- // marked as a texture.
- if((LLInventoryType::IT_NONE == mInventoryType)
- || !inventory_and_asset_types_match(mInventoryType, mType))
- {
- LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL;
- mInventoryType = LLInventoryType::defaultForAssetType(mType);
- }
-
- mPermissions.initMasks(mInventoryType);
-
- return success;
-}
-
-BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const
-{
- std::string uuid_str;
- fprintf(fp, "\tinv_item\t0\n\t{\n");
- mUUID.toString(uuid_str);
- fprintf(fp, "\t\titem_id\t%s\n", uuid_str.c_str());
- mParentUUID.toString(uuid_str);
- fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
- mPermissions.exportFile(fp);
-
- // Check for permissions to see the asset id, and if so write it
- // out as an asset id. Otherwise, apply our cheesy encryption.
- if(include_asset_key)
- {
- U32 mask = mPermissions.getMaskBase();
- if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- || (mAssetUUID.isNull()))
- {
- mAssetUUID.toString(uuid_str);
- fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str());
- }
- else
- {
- LLUUID shadow_id(mAssetUUID);
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.encrypt(shadow_id.mData, UUID_BYTES);
- shadow_id.toString(uuid_str);
- fprintf(fp, "\t\tshadow_id\t%s\n", uuid_str.c_str());
- }
- }
- else
- {
- LLUUID::null.toString(uuid_str);
- fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str());
- }
- fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
- fprintf(fp, "\t\tflags\t%08x\n", mFlags);
- mSaleInfo.exportFile(fp);
- fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
- fprintf(fp, "\t\tdesc\t%s|\n", mDescription.c_str());
- fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate);
- fprintf(fp,"\t}\n");
- return TRUE;
-}
-
-// virtual
BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream)
{
// *NOTE: Changing the buffer size will require changing the scanf
@@ -1463,90 +1238,7 @@ void LLInventoryCategory::unpackMessage(LLMessageSystem* msg,
msg->getStringFast(block, _PREHASH_Name, mName, block_num);
LLStringUtil::replaceNonstandardASCII(mName, ' ');
}
-
-// virtual
-BOOL LLInventoryCategory::importFile(LLFILE* fp)
-{
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
- keyword[0] = '\0';
- valuestr[0] = '\0';
- while(!feof(fp))
- {
- if (fgets(buffer, MAX_STRING, fp) == NULL)
- {
- buffer[0] = '\0';
- }
-
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254s",
- keyword, valuestr);
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("cat_id", keyword))
- {
- mUUID.set(valuestr);
- }
- else if(0 == strcmp("parent_id", keyword))
- {
- mParentUUID.set(valuestr);
- }
- else if(0 == strcmp("type", keyword))
- {
- mType = LLAssetType::lookup(valuestr);
- }
- else if(0 == strcmp("pref_type", keyword))
- {
- mPreferredType = LLFolderType::lookup(valuestr);
- }
- else if(0 == strcmp("name", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254[^|]",
- keyword, valuestr);
- mName.assign(valuestr);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in inventory import category " << mUUID << LL_ENDL;
- }
- }
- return TRUE;
-}
-
-BOOL LLInventoryCategory::exportFile(LLFILE* fp, BOOL) const
-{
- std::string uuid_str;
- fprintf(fp, "\tinv_category\t0\n\t{\n");
- mUUID.toString(uuid_str);
- fprintf(fp, "\t\tcat_id\t%s\n", uuid_str.c_str());
- mParentUUID.toString(uuid_str);
- fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
- fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str());
- fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
- fprintf(fp,"\t}\n");
- return TRUE;
-}
-
-
// virtual
BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream)
{
@@ -1625,6 +1317,45 @@ BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL)
return TRUE;
}
+LLSD LLInventoryCategory::exportLLSD() const
+{
+ LLSD cat_data;
+ cat_data[INV_FOLDER_ID_LABEL] = mUUID;
+ cat_data[INV_PARENT_ID_LABEL] = mParentUUID;
+ cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
+ cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
+ cat_data[INV_NAME_LABEL] = mName;
+
+ return cat_data;
+}
+
+bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
+{
+ if (cat_data.has(INV_FOLDER_ID_LABEL))
+ {
+ setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID());
+ }
+ if (cat_data.has(INV_PARENT_ID_LABEL))
+ {
+ setParent(cat_data[INV_PARENT_ID_LABEL].asUUID());
+ }
+ if (cat_data.has(INV_ASSET_TYPE_LABEL))
+ {
+ setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString()));
+ }
+ if (cat_data.has(INV_PREFERRED_TYPE_LABEL))
+ {
+ setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
+ }
+ if (cat_data.has(INV_NAME_LABEL))
+ {
+ mName = cat_data[INV_NAME_LABEL].asString();
+ LLStringUtil::replaceNonstandardASCII(mName, ' ');
+ LLStringUtil::replaceChar(mName, '|', ' ');
+ }
+
+ return true;
+}
///----------------------------------------------------------------------------
/// Local function definitions
///----------------------------------------------------------------------------
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 70b200e139..024afc109c 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -95,8 +95,7 @@ public:
// Implemented here so that a minimal information set can be transmitted
// between simulator and viewer.
//--------------------------------------------------------------------
- // virtual BOOL importFile(LLFILE* fp);
- virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const;
+
virtual BOOL importLegacyStream(std::istream& input_stream);
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
@@ -197,8 +196,6 @@ public:
// File Support
//--------------------------------------------------------------------
public:
- virtual BOOL importFile(LLFILE* fp);
- virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const;
virtual BOOL importLegacyStream(std::istream& input_stream);
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
@@ -269,11 +266,11 @@ public:
// File Support
//--------------------------------------------------------------------
public:
- virtual BOOL importFile(LLFILE* fp);
- virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const;
virtual BOOL importLegacyStream(std::istream& input_stream);
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
+ LLSD exportLLSD() const;
+ bool importLLSD(const LLSD& cat_data);
//--------------------------------------------------------------------
// Member Variables
//--------------------------------------------------------------------
diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp
index fdad50e8d4..81485b3a97 100644
--- a/indra/llinventory/llinventorysettings.cpp
+++ b/indra/llinventory/llinventorysettings.cpp
@@ -33,10 +33,6 @@
#include "llsingleton.h"
#include "llinvtranslationbrdg.h"
-//=========================================================================
-namespace {
- LLTranslationBridge::ptr_t sTranslator;
-}
//=========================================================================
struct SettingsEntry : public LLDictionaryEntry
@@ -49,7 +45,7 @@ struct SettingsEntry : public LLDictionaryEntry
mLabel(name),
mIconName(iconName)
{
- std::string transdname = sTranslator->getString(mLabel);
+ std::string transdname = LLSettingsType::getInstance()->mTranslator->getString(mLabel);
if (!transdname.empty())
{
mLabel = transdname;
@@ -84,6 +80,16 @@ void LLSettingsDictionary::initSingleton()
//=========================================================================
+LLSettingsType::LLSettingsType(LLTranslationBridge::ptr_t &trans)
+{
+ mTranslator = trans;
+}
+
+LLSettingsType::~LLSettingsType()
+{
+ mTranslator.reset();
+}
+
LLSettingsType::type_e LLSettingsType::fromInventoryFlags(U32 flags)
{
return (LLSettingsType::type_e)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK);
@@ -104,13 +110,3 @@ std::string LLSettingsType::getDefaultName(LLSettingsType::type_e type)
return getDefaultName(ST_INVALID);
return entry->mDefaultNewName;
}
-
-void LLSettingsType::initClass(LLTranslationBridge::ptr_t &trans)
-{
- sTranslator = trans;
-}
-
-void LLSettingsType::cleanupClass()
-{
- sTranslator.reset();
-}
diff --git a/indra/llinventory/llinventorysettings.h b/indra/llinventory/llinventorysettings.h
index 906540689c..6b6685d088 100644
--- a/indra/llinventory/llinventorysettings.h
+++ b/indra/llinventory/llinventorysettings.h
@@ -30,9 +30,15 @@
#include "llinventorytype.h"
#include "llinvtranslationbrdg.h"
+#include "llsingleton.h"
-class LLSettingsType
+class LLSettingsType : public LLParamSingleton<LLSettingsType>
{
+ LLSINGLETON(LLSettingsType, LLTranslationBridge::ptr_t &trans);
+ ~LLSettingsType();
+
+ friend struct SettingsEntry;
+
public:
enum type_e
{
@@ -48,8 +54,9 @@ public:
static LLInventoryType::EIconName getIconName(type_e type);
static std::string getDefaultName(type_e type);
- static void initClass(LLTranslationBridge::ptr_t &trans);
- static void cleanupClass();
+protected:
+
+ LLTranslationBridge::ptr_t mTranslator;
};
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index e79b753514..0359d2f554 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -565,148 +565,6 @@ void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 b
}
-//
-// File support
-//
-
-BOOL LLPermissions::importFile(LLFILE* fp)
-{
- init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
- const S32 BUFSIZE = 16384;
-
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[BUFSIZE]; /* Flawfinder: ignore */
- char keyword[256]; /* Flawfinder: ignore */
- char valuestr[256]; /* Flawfinder: ignore */
- char uuid_str[256]; /* Flawfinder: ignore */
- U32 mask;
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
-
- while (!feof(fp))
- {
- if (fgets(buffer, BUFSIZE, fp) == NULL)
- {
- buffer[0] = '\0';
- }
-
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %255s %255s",
- keyword, valuestr);
- if (!strcmp("{", keyword))
- {
- continue;
- }
- if (!strcmp("}",keyword))
- {
- break;
- }
- else if (!strcmp("creator_mask", keyword))
- {
- // legacy support for "creator" masks
- sscanf(valuestr, "%x", &mask);
- mMaskBase = mask;
- fixFairUse();
- }
- else if (!strcmp("base_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskBase = mask;
- //fixFairUse();
- }
- else if (!strcmp("owner_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskOwner = mask;
- }
- else if (!strcmp("group_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskGroup = mask;
- }
- else if (!strcmp("everyone_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskEveryone = mask;
- }
- else if (!strcmp("next_owner_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskNextOwner = mask;
- }
- else if (!strcmp("creator_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mCreator.set(uuid_str);
- }
- else if (!strcmp("owner_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mOwner.set(uuid_str);
- }
- else if (!strcmp("last_owner_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mLastOwner.set(uuid_str);
- }
- else if (!strcmp("group_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mGroup.set(uuid_str);
- }
- else if (!strcmp("group_owned", keyword))
- {
- sscanf(valuestr, "%d", &mask);
- if(mask) mIsGroupOwned = true;
- else mIsGroupOwned = false;
- }
- else
- {
- LL_INFOS() << "unknown keyword " << keyword << " in permissions import" << LL_ENDL;
- }
- }
- fix();
- return TRUE;
-}
-
-
-BOOL LLPermissions::exportFile(LLFILE* fp) const
-{
- std::string uuid_str;
-
- fprintf(fp, "\tpermissions 0\n");
- fprintf(fp, "\t{\n");
-
- fprintf(fp, "\t\tbase_mask\t%08x\n", mMaskBase);
- fprintf(fp, "\t\towner_mask\t%08x\n", mMaskOwner);
- fprintf(fp, "\t\tgroup_mask\t%08x\n", mMaskGroup);
- fprintf(fp, "\t\teveryone_mask\t%08x\n", mMaskEveryone);
- fprintf(fp, "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner);
-
- mCreator.toString(uuid_str);
- fprintf(fp, "\t\tcreator_id\t%s\n", uuid_str.c_str());
-
- mOwner.toString(uuid_str);
- fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str());
-
- mLastOwner.toString(uuid_str);
- fprintf(fp, "\t\tlast_owner_id\t%s\n", uuid_str.c_str());
-
- mGroup.toString(uuid_str);
- fprintf(fp, "\t\tgroup_id\t%s\n", uuid_str.c_str());
-
- if(mIsGroupOwned)
- {
- fprintf(fp, "\t\tgroup_owned\t1\n");
- }
- fprintf(fp,"\t}\n");
- return TRUE;
-}
-
-
BOOL LLPermissions::importLegacyStream(std::istream& input_stream)
{
init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 89c66f6ebd..27252f7b97 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -311,10 +311,6 @@ public:
void packMessage(LLMessageSystem* msg) const;
void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
- // Load/save support
- BOOL importFile(LLFILE* fp);
- BOOL exportFile(LLFILE* fp) const;
-
BOOL importLegacyStream(std::istream& input_stream);
BOOL exportLegacyStream(std::ostream& output_stream) const;
diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp
index 63e34d188e..b7231ee239 100644
--- a/indra/llinventory/llsaleinfo.cpp
+++ b/indra/llinventory/llsaleinfo.cpp
@@ -78,16 +78,6 @@ U32 LLSaleInfo::getCRC32() const
return rv;
}
-
-BOOL LLSaleInfo::exportFile(LLFILE* fp) const
-{
- fprintf(fp, "\tsale_info\t0\n\t{\n");
- fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType));
- fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice);
- fprintf(fp,"\t}\n");
- return TRUE;
-}
-
BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
{
output_stream << "\tsale_info\t0\n\t{\n";
@@ -129,69 +119,6 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask)
return true;
}
-// Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML()
-// because I can't find any non-test code references to it. 2009-05-04 JC
-
-BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask)
-{
- has_perm_mask = FALSE;
-
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
- BOOL success = TRUE;
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
- while(success && (!feof(fp)))
- {
- if (fgets(buffer, MAX_STRING, fp) == NULL)
- {
- buffer[0] = '\0';
- }
-
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254s",
- keyword, valuestr);
- if(!keyword[0])
- {
- continue;
- }
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("sale_type", keyword))
- {
- mSaleType = lookup(valuestr);
- }
- else if(0 == strcmp("sale_price", keyword))
- {
- sscanf(valuestr, "%d", &mSalePrice);
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
- }
- else if (!strcmp("perm_mask", keyword))
- {
- //LL_INFOS() << "found deprecated keyword perm_mask" << LL_ENDL;
- has_perm_mask = TRUE;
- sscanf(valuestr, "%x", &perm_mask);
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in sale info import" << LL_ENDL;
- }
- }
- return success;
-}
-
BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask)
{
has_perm_mask = FALSE;
diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h
index 4e98ccf6ff..3c8952838b 100644
--- a/indra/llinventory/llsaleinfo.h
+++ b/indra/llinventory/llsaleinfo.h
@@ -84,11 +84,6 @@ public:
void setSalePrice(S32 price);
//void setNextOwnerPermMask(U32 mask) { mNextOwnerPermMask = mask; }
-
- // file serialization
- BOOL exportFile(LLFILE* fp) const;
- BOOL importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask);
-
BOOL exportLegacyStream(std::ostream& output_stream) const;
LLSD asLLSD() const;
operator LLSD() const { return asLLSD(); }
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index 1d118f0789..f7a9d5b7cd 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -359,7 +359,6 @@ protected:
virtual parammapping_t getParameterMap() const { return parammapping_t(); }
LLSD mSettings;
- bool mIsValid;
LLSD cloneSettings() const;
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 306c732920..81937dbda5 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -1295,6 +1295,9 @@ void LLSettingsSky::clampColor(LLColor3& color, F32 gamma, F32 scale) const
color = linear;
}
+// Similar/Shared Algorithms:
+// indra\llinventory\llsettingssky.cpp -- LLSettingsSky::calculateLightSettings()
+// indra\newview\app_settings\shaders\class1\windlight\atmosphericsFuncs.glsl -- calcAtmosphericVars()
void LLSettingsSky::calculateLightSettings() const
{
// Initialize temp variables
diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp
index 7b15552f24..e8b063bffe 100644
--- a/indra/llinventory/tests/inventorymisc_test.cpp
+++ b/indra/llinventory/tests/inventorymisc_test.cpp
@@ -28,9 +28,9 @@
#include "linden_common.h"
#include "llsd.h"
+#include "llsdserialize.h"
#include "../llinventory.h"
-
#include "../test/lltut.h"
@@ -320,27 +320,39 @@ namespace tut
template<> template<>
void inventory_object::test<7>()
{
- LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
- if(!fp)
+ std::string filename("linden_file.dat");
+ llofstream fileXML(filename.c_str());
+ if (!fileXML.is_open())
{
LL_ERRS() << "file could not be opened\n" << LL_ENDL;
return;
}
LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
- src1->exportFile(fp, TRUE);
- fclose(fp);
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->asLLSD()) << std::endl;
+ fileXML.close();
- LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
- fp = LLFile::fopen("linden_file.dat","r+");
- if(!fp)
+
+ LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
+ llifstream file(filename.c_str());
+ if (!file.is_open())
{
LL_ERRS() << "file could not be opened\n" << LL_ENDL;
return;
}
-
- src2->importFile(fp);
- fclose(fp);
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ std::getline(file, line);
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ LL_ERRS()<< "Parsing cache failed" << LL_ENDL;
+ return;
+ }
+ src2->fromLLSD(s_item);
+
+ file.close();
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
@@ -457,27 +469,39 @@ namespace tut
template<> template<>
void inventory_object::test<13>()
{
- LLFILE* fp = LLFile::fopen("linden_file.dat","w");
- if(!fp)
+ std::string filename("linden_file.dat");
+ llofstream fileXML(filename.c_str());
+ if (!fileXML.is_open())
{
- LL_ERRS() << "file coudnt be opened\n" << LL_ENDL;
+ LL_ERRS() << "file could not be opened\n" << LL_ENDL;
return;
}
-
+
LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
- src1->exportFile(fp, TRUE);
- fclose(fp);
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->exportLLSD()) << std::endl;
+ fileXML.close();
- LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
- fp = LLFile::fopen("linden_file.dat","r");
- if(!fp)
+ llifstream file(filename.c_str());
+ if (!file.is_open())
{
- LL_ERRS() << "file coudnt be opened\n" << LL_ENDL;
+ LL_ERRS() << "file could not be opened\n" << LL_ENDL;
return;
}
-
- src2->importFile(fp);
- fclose(fp);
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ std::getline(file, line);
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ LL_ERRS()<< "Parsing cache failed" << LL_ENDL;
+ return;
+ }
+
+ file.close();
+
+ LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
+ src2->importLLSD(s_item);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h
index 222f3cf235..27abf39537 100644
--- a/indra/llmath/llvector4a.h
+++ b/indra/llmath/llvector4a.h
@@ -46,10 +46,10 @@ class LLRotation;
// of this writing, July 08, 2010) about getting it implemented before you resort to
// LLVector3/LLVector4.
/////////////////////////////////
-class LLVector4a;
+struct LLVector4a;
LL_ALIGN_PREFIX(16)
-class LLVector4a
+struct LLVector4a
{
public:
@@ -92,6 +92,7 @@ public:
// CONSTRUCTORS
////////////////////////////////////
+ //LLVector4a is plain data which should never have a default constructor or destructor(malloc&free won't trigger it)
LLVector4a()
{ //DO NOT INITIALIZE -- The overhead is completely unnecessary
ll_assert_aligned(this,16);
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index 42c19e3b1c..a4fe3a2a8e 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -77,12 +77,12 @@ public:
///
inline size_t countActive() const
{
- return mActiveCoprocs.size();
+ return mActiveCoprocsCount;
}
/// Returns the total number of coprocedures either queued or in active processing.
///
- inline size_t count() const
+ inline S32 count() const
{
return countPending() + countActive();
}
@@ -113,12 +113,10 @@ private:
// because the consuming coroutine might outlive this LLCoprocedurePool
// instance.
typedef boost::shared_ptr<CoprocQueue_t> CoprocQueuePtr;
- typedef std::map<LLUUID, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> ActiveCoproc_t;
std::string mPoolName;
- size_t mPoolSize, mPending{0};
+ size_t mPoolSize, mActiveCoprocsCount, mPending;
CoprocQueuePtr mPendingCoprocs;
- ActiveCoproc_t mActiveCoprocs;
LLTempBoundListener mStatusListener;
typedef std::map<std::string, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> CoroAdapterMap_t;
@@ -191,8 +189,13 @@ LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const s
void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn)
{
+ // functions to discover and store the pool sizes
mPropertyQueryFn = queryfn;
mPropertyDefineFn = updatefn;
+
+ // workaround until we get mutex into initializePool
+ initializePool("VAssetStorage");
+ initializePool("Upload");
}
//-------------------------------------------------------------------------
@@ -276,6 +279,8 @@ void LLCoprocedureManager::close(const std::string &pool)
LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
mPoolName(poolName),
mPoolSize(size),
+ mActiveCoprocsCount(0),
+ mPending(0),
mPendingCoprocs(boost::make_shared<CoprocQueue_t>(DEFAULT_QUEUE_SIZE)),
mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mCoroMapping()
@@ -355,7 +360,7 @@ LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoproced
}
// The queue should never fill up.
- LL_ERRS("CoProcMgr") << "Enqueue failed (" << unsigned(pushed) << ")" << LL_ENDL;
+ LL_ERRS("CoProcMgr") << "Enqueue into '" << name << "' failed (" << unsigned(pushed) << ")" << LL_ENDL;
return {}; // never executed, pacify the compiler
}
@@ -401,8 +406,7 @@ void LLCoprocedurePool::coprocedureInvokerCoro(
}
// we actually popped an item
--mPending;
-
- ActiveCoproc_t::iterator itActive = mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)).first;
+ mActiveCoprocsCount++;
LL_DEBUGS("CoProcMgr") << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\" (" << mPending << " left)" << LL_ENDL;
@@ -410,19 +414,25 @@ void LLCoprocedurePool::coprocedureInvokerCoro(
{
coproc->mProc(httpAdapter, coproc->mId);
}
+ catch (const LLCoros::Stop &e)
+ {
+ LL_INFOS("LLCoros") << "coprocedureInvokerCoro terminating because "
+ << e.what() << LL_ENDL;
+ throw; // let toplevel handle this as LLContinueError
+ }
catch (...)
{
LOG_UNHANDLED_EXCEPTION(STRINGIZE("Coprocedure('" << coproc->mName
<< "', id=" << coproc->mId.asString()
<< ") in pool '" << mPoolName << "'"));
// must NOT omit this or we deplete the pool
- mActiveCoprocs.erase(itActive);
+ mActiveCoprocsCount--;
continue;
}
LL_DEBUGS("CoProcMgr") << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL;
- mActiveCoprocs.erase(itActive);
+ mActiveCoprocsCount--;
}
}
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index 7d96ac4b02..64c01bd9eb 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -85,15 +85,15 @@ const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0;
const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes
const int LLExperienceCache::SEARCH_PAGE_SIZE = 30;
+bool LLExperienceCache::sShutdown = false;
+
//=========================================================================
-LLExperienceCache::LLExperienceCache():
- mShutdown(false)
+LLExperienceCache::LLExperienceCache()
{
}
LLExperienceCache::~LLExperienceCache()
{
-
}
void LLExperienceCache::initSingleton()
@@ -122,7 +122,7 @@ void LLExperienceCache::cleanup()
{
cache_stream << (*this);
}
- mShutdown = true;
+ sShutdown = true;
}
//-------------------------------------------------------------------------
@@ -344,7 +344,7 @@ void LLExperienceCache::requestExperiences()
ostr << urlBase << "?page_size=" << PAGE_SIZE1;
RequestQueue_t requests;
- while (!mRequestQueue.empty())
+ while (!mRequestQueue.empty() && !sShutdown)
{
RequestQueue_t::iterator it = mRequestQueue.begin();
LLUUID key = (*it);
@@ -398,8 +398,6 @@ void LLExperienceCache::idleCoro()
LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL;
do
{
- llcoro::suspendUntilTimeout(SECS_BETWEEN_REQUESTS);
-
if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
{
eraseExpired();
@@ -410,7 +408,9 @@ void LLExperienceCache::idleCoro()
requestExperiences();
}
- } while (!mShutdown);
+ llcoro::suspendUntilTimeout(SECS_BETWEEN_REQUESTS);
+
+ } while (!sShutdown);
// The coroutine system will likely be shut down by the time we get to this point
// (or at least no further cycling will occur on it since the user has decided to quit.)
diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index f9ff69c2b6..1c97133723 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -142,7 +142,7 @@ private:
LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache
CapabilityQuery_t mCapability;
std::string mCacheFileName;
- bool mShutdown;
+ static bool sShutdown; // control for coroutines, they exist out of LLExperienceCache's scope, so they need a static control
void idleCoro();
void eraseExpired();
diff --git a/indra/llmessage/llteleportflags.h b/indra/llmessage/llteleportflags.h
index b3fcad036e..fd1e702832 100644
--- a/indra/llmessage/llteleportflags.h
+++ b/indra/llmessage/llteleportflags.h
@@ -44,6 +44,8 @@ const U32 TELEPORT_FLAGS_VIA_REGION_ID = 1 << 12;
const U32 TELEPORT_FLAGS_IS_FLYING = 1 << 13;
const U32 TELEPORT_FLAGS_SHOW_RESET_HOME = 1 << 14;
const U32 TELEPORT_FLAGS_FORCE_REDIRECT = 1 << 15; // used to force a redirect to some random location - used when kicking someone from land.
+const U32 TELEPORT_FLAGS_VIA_GLOBAL_COORDS = 1 << 16;
+const U32 TELEPORT_FLAGS_WITHIN_REGION = 1 << 17;
const U32 TELEPORT_FLAGS_MASK_VIA = TELEPORT_FLAGS_VIA_LURE
| TELEPORT_FLAGS_VIA_LANDMARK
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 58069afdf9..6d51adc685 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -857,12 +857,12 @@ void LLPluginClassMedia::paste()
}
void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache,
- const std::string &user_data_path_cookies,
+ const std::string &username,
const std::string &user_data_path_cef_log)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
- message.setValue("cache_path", user_data_path_cache);
- message.setValue("cookies_path", user_data_path_cookies);
+ message.setValue("cache_path", user_data_path_cache);
+ message.setValue("username", username); // cef shares cache between users but creates user-based contexts
message.setValue("cef_log_file", user_data_path_cef_log);
bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog");
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 9d11ee0421..382f891e0c 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -195,7 +195,7 @@ public:
bool canPaste() const { return mCanPaste; };
// These can be called before init(), and they will be queued and sent before the media init message.
- void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_cef_log);
+ void setUserDataPath(const std::string &user_data_path_cache, const std::string &username, const std::string &user_data_path_cef_log);
void setLanguageCode(const std::string &language_code);
void setPluginsEnabled(const bool enabled);
void setJavascriptEnabled(const bool enabled);
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index c5304d2ccf..d93ec8cf4b 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -225,6 +225,18 @@ void LLPluginProcessChild::idle(void)
}
setState(STATE_UNLOADED);
}
+
+ if (mInstance)
+ {
+ // Provide some time to the plugin
+ // example: CEF on "cleanup" sets shutdown request, but it still needs idle loop to actually shutdown
+ LLPluginMessage message("base", "idle");
+ message.setValueReal("time", PLUGIN_IDLE_SECONDS);
+ sendMessageToPlugin(message);
+
+ mInstance->idle();
+ }
+
break;
case STATE_UNLOADED:
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 139f48fef8..d2aa3d8dc6 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -343,7 +343,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
return LLModel::NO_ERRORS ;
}
-LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly)
+LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly, LLSD& log_msg)
{
domPRef p = poly->getP();
domListOfUInts& idx = p->getValue();
@@ -403,6 +403,7 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
LLVolumeFace::VertexMapData::PointMap point_map;
U32 cur_idx = 0;
+ bool log_tc_msg = true;
for (U32 i = 0; i < vcount.getCount(); ++i)
{ //for each polygon
U32 first_index = 0;
@@ -426,8 +427,21 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (tc_source)
{
- cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
- tc[idx[cur_idx+tc_offset]*2+1]);
+ U64 idx_x = idx[cur_idx + tc_offset] * 2 + 0;
+ U64 idx_y = idx[cur_idx + tc_offset] * 2 + 1;
+
+ if (idx_y < tc.getCount())
+ {
+ cv.mTexCoord.setVec(tc[idx_x], tc[idx_y]);
+ }
+ else if (log_tc_msg)
+ {
+ log_tc_msg = false;
+ LL_WARNS() << "Texture coordinates data is not complete." << LL_ENDL;
+ LLSD args;
+ args["Message"] = "IncompleteTC";
+ log_msg.append(args);
+ }
}
if (norm_source)
@@ -1215,7 +1229,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
for (S32 i = 0; i < childCount; ++i)
{
domNode* pNode = daeSafeCast<domNode>(children[i]);
- if ( isNodeAJoint( pNode ) )
+ if (pNode)
{
processJointNode( pNode, mJointList );
}
@@ -1470,6 +1484,12 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
}
}
+ U32 bind_count = model->mSkinInfo.mAlternateBindMatrix.size();
+ if (bind_count > 0 && bind_count != jointCnt)
+ {
+ LL_WARNS("Mesh") << "Model " << model->mLabel << " has invalid joint bind matrix list." << LL_ENDL;
+ }
+
//grab raw position array
domVertices* verts = mesh->getVertices();
@@ -1834,59 +1854,61 @@ void LLDAELoader::processJointNode( domNode* pNode, JointTransformMap& jointTran
//LL_WARNS()<<"ProcessJointNode# Node:" <<pNode->getName()<<LL_ENDL;
//1. handle the incoming node - extract out translation via SID or element
+ if (isNodeAJoint(pNode))
+ {
+ LLMatrix4 workingTransform;
- LLMatrix4 workingTransform;
-
- //Pull out the translate id and store it in the jointTranslations map
- daeSIDResolver jointResolverA( pNode, "./translate" );
- domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() );
- daeSIDResolver jointResolverB( pNode, "./location" );
- domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() );
+ //Pull out the translate id and store it in the jointTranslations map
+ daeSIDResolver jointResolverA(pNode, "./translate");
+ domTranslate* pTranslateA = daeSafeCast<domTranslate>(jointResolverA.getElement());
+ daeSIDResolver jointResolverB(pNode, "./location");
+ domTranslate* pTranslateB = daeSafeCast<domTranslate>(jointResolverB.getElement());
- //Translation via SID was successful
- if ( pTranslateA )
- {
- extractTranslation( pTranslateA, workingTransform );
- }
- else
- if ( pTranslateB )
- {
- extractTranslation( pTranslateB, workingTransform );
- }
- else
- {
- //Translation via child from element
- daeElement* pTranslateElement = getChildFromElement( pNode, "translate" );
- if ( !pTranslateElement || pTranslateElement->typeID() != domTranslate::ID() )
- {
- //LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
- daeSIDResolver jointResolver( pNode, "./matrix" );
- domMatrix* pMatrix = daeSafeCast<domMatrix>( jointResolver.getElement() );
- if ( pMatrix )
- {
- //LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL;
- domFloat4x4 domArray = pMatrix->getValue();
- for ( int i = 0; i < 4; i++ )
- {
- for( int j = 0; j < 4; j++ )
- {
- workingTransform.mMatrix[i][j] = domArray[i + j*4];
- }
- }
- }
- else
- {
- LL_WARNS()<< "The found element is not translate or matrix node - most likely a corrupt export!" <<LL_ENDL;
- }
- }
- else
- {
- extractTranslationViaElement( pTranslateElement, workingTransform );
- }
- }
+ //Translation via SID was successful
+ if (pTranslateA)
+ {
+ extractTranslation(pTranslateA, workingTransform);
+ }
+ else
+ if (pTranslateB)
+ {
+ extractTranslation(pTranslateB, workingTransform);
+ }
+ else
+ {
+ //Translation via child from element
+ daeElement* pTranslateElement = getChildFromElement(pNode, "translate");
+ if (!pTranslateElement || pTranslateElement->typeID() != domTranslate::ID())
+ {
+ //LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL;
+ daeSIDResolver jointResolver(pNode, "./matrix");
+ domMatrix* pMatrix = daeSafeCast<domMatrix>(jointResolver.getElement());
+ if (pMatrix)
+ {
+ //LL_INFOS()<<"A matrix SID was however found!"<<LL_ENDL;
+ domFloat4x4 domArray = pMatrix->getValue();
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ workingTransform.mMatrix[i][j] = domArray[i + j * 4];
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS() << "The found element is not translate or matrix node - most likely a corrupt export!" << LL_ENDL;
+ }
+ }
+ else
+ {
+ extractTranslationViaElement(pTranslateElement, workingTransform);
+ }
+ }
- //Store the working transform relative to the nodes name.
- jointTransforms[ pNode->getName() ] = workingTransform;
+ //Store the working transform relative to the nodes name.
+ jointTransforms[pNode->getName()] = workingTransform;
+ }
//2. handle the nodes children
@@ -2356,7 +2378,7 @@ LLColor4 LLDAELoader::getDaeColor(daeElement* element)
return value;
}
-bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh)
+bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD& log_msg)
{
LLModel::EModelStatus status = LLModel::NO_ERRORS;
domTriangles_Array& tris = mesh->getTriangles_array();
@@ -2378,7 +2400,7 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh)
for (U32 i = 0; i < polys.getCount(); ++i)
{
domPolylistRef& poly = polys.get(i);
- status = load_face_from_dom_polylist(pModel->getVolumeFaces(), pModel->getMaterialList(), poly);
+ status = load_face_from_dom_polylist(pModel->getVolumeFaces(), pModel->getMaterialList(), poly, log_msg);
if(status != LLModel::NO_ERRORS)
{
@@ -2442,7 +2464,7 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
// Get the whole set of volume faces
//
- addVolumeFacesFromDomMesh(ret, mesh);
+ addVolumeFacesFromDomMesh(ret, mesh, mWarningsArray);
U32 volume_faces = ret->getNumVolumeFaces();
@@ -2515,7 +2537,8 @@ bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh)
{
pModel->ClearFacesAndMaterials();
- addVolumeFacesFromDomMesh(pModel, mesh);
+ LLSD placeholder;
+ addVolumeFacesFromDomMesh(pModel, mesh, placeholder);
if (pModel->getNumVolumeFaces() > 0)
{
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 4e990dbe5e..2b211343e1 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -89,7 +89,7 @@ protected:
//Verify that a controller matches vertex counts
bool verifyController( domController* pController );
- static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh);
+ static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg);
static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
static LLModel* loadModelFromDomMesh(domMesh* mesh);
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 4e468ff45f..5171621007 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -127,7 +127,7 @@ LLModelLoader::LLModelLoader(
, mStateCallback(state_cb)
, mOpaqueData(opaque_userdata)
, mRigValidJointUpload(true)
-, mLegacyRigValid(true)
+, mLegacyRigFlags(0)
, mNoNormalize(false)
, mNoOptimize(false)
, mCacheOnlyHitIfRigged(false)
@@ -136,6 +136,7 @@ LLModelLoader::LLModelLoader(
{
assert_main_thread();
sActiveLoaderList.push_back(this) ;
+ mWarningsArray = LLSD::emptyArray();
}
LLModelLoader::~LLModelLoader()
@@ -146,6 +147,7 @@ LLModelLoader::~LLModelLoader()
void LLModelLoader::run()
{
+ mWarningsArray.clear();
doLoadModel();
doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
}
@@ -387,7 +389,7 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::st
//2. It is suitable for upload as standard av with just skin weights
bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
- bool isRigLegacyOK = isRigLegacy( jointListFromAsset );
+ U32 legacy_rig_flags = determineRigLegacyFlags( jointListFromAsset );
// It's OK that both could end up being true.
@@ -401,19 +403,16 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::st
setRigValidForJointPositionUpload( false );
}
- if ( !isRigLegacyOK)
- {
- // This starts out true, becomes false if false for any loaded
- // mesh.
- setLegacyRigValid( false );
- }
+ legacy_rig_flags |= getLegacyRigFlags();
+ // This starts as 0, changes if any loaded mesh has issues
+ setLegacyRigFlags(legacy_rig_flags);
}
//-----------------------------------------------------------------------------
-// isRigLegacy()
+// determineRigLegacyFlags()
//-----------------------------------------------------------------------------
-bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
+U32 LLModelLoader::determineRigLegacyFlags( const std::vector<std::string> &jointListFromAsset )
{
//No joints in asset
if ( jointListFromAsset.size() == 0 )
@@ -426,7 +425,12 @@ bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAs
{
LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL;
LL_WARNS() << "Skinning disabled due to too many joints" << LL_ENDL;
- return false;
+ LLSD args;
+ args["Message"] = "TooManyJoint";
+ args["[JOINTS]"] = LLSD::Integer(jointListFromAsset.size());
+ args["[MAX]"] = LLSD::Integer(mMaxJointsPerMesh);
+ mWarningsArray.append(args);
+ return LEGACY_RIG_FLAG_TOO_MANY_JOINTS;
}
// Unknown joints in asset
@@ -437,16 +441,24 @@ bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAs
if (mJointMap.find(*it)==mJointMap.end())
{
LL_WARNS() << "Rigged to unrecognized joint name " << *it << LL_ENDL;
+ LLSD args;
+ args["Message"] = "UnrecognizedJoint";
+ args["[NAME]"] = *it;
+ mWarningsArray.append(args);
unknown_joint_count++;
}
}
if (unknown_joint_count>0)
{
LL_WARNS() << "Skinning disabled due to unknown joints" << LL_ENDL;
- return false;
+ LLSD args;
+ args["Message"] = "UnknownJoints";
+ args["[COUNT]"] = LLSD::Integer(unknown_joint_count);
+ mWarningsArray.append(args);
+ return LEGACY_RIG_FLAG_UNKNOWN_JOINT;
}
- return true;
+ return LEGACY_RIG_OK;
}
//-----------------------------------------------------------------------------
// isRigSuitableForJointPositionUpload()
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
index 643c45a6d8..fbc74554a0 100644
--- a/indra/llprimitive/llmodelloader.h
+++ b/indra/llprimitive/llmodelloader.h
@@ -42,6 +42,10 @@ typedef std::deque<std::string> JointNameSet;
const S32 SLM_SUPPORTED_VERSION = 3;
const S32 NUM_LOD = 4;
+const U32 LEGACY_RIG_OK = 0;
+const U32 LEGACY_RIG_FLAG_TOO_MANY_JOINTS = 1;
+const U32 LEGACY_RIG_FLAG_UNKNOWN_JOINT = 2;
+
class LLModelLoader : public LLThread
{
public:
@@ -166,7 +170,7 @@ public:
void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
//Determines if a rig is a legacy from the joint list
- bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );
+ U32 determineRigLegacyFlags( const std::vector<std::string> &jointListFromAsset );
//Determines if a rig is suitable for upload
bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
@@ -174,8 +178,9 @@ public:
const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
- const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
- void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
+ const bool isLegacyRigValid(void) const { return mLegacyRigFlags == 0; }
+ U32 getLegacyRigFlags() const { return mLegacyRigFlags; }
+ void setLegacyRigFlags( U32 rigFlags ) { mLegacyRigFlags = rigFlags; }
//-----------------------------------------------------------------------------
// isNodeAJoint()
@@ -185,6 +190,9 @@ public:
return name != NULL && mJointMap.find(name) != mJointMap.end();
}
+ const LLSD logOut() const { return mWarningsArray; }
+ void clearLog() { mWarningsArray.clear(); }
+
protected:
LLModelLoader::load_callback_t mLoadCallback;
@@ -194,13 +202,15 @@ protected:
void* mOpaqueData;
bool mRigValidJointUpload;
- bool mLegacyRigValid;
+ U32 mLegacyRigFlags;
bool mNoNormalize;
bool mNoOptimize;
JointTransformMap mJointTransformMap;
+ LLSD mWarningsArray; // preview floater will pull logs from here
+
static std::list<LLModelLoader*> sActiveLoaderList;
static bool isAlive(LLModelLoader* loader) ;
};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 498dfca1a3..604fb4e946 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -2700,10 +2700,11 @@ LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_w
}
#if LL_WINDOWS
-// Expose desired use of high-performance graphics processor to Optimus driver
+// Expose desired use of high-performance graphics processor to Optimus driver and to AMD driver
extern "C"
-{
- _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
+{
+ __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
+ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ff74380217..3b6a49735e 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -985,38 +985,56 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
return FALSE;
}
- if( !mHasExplicitFormat )
- {
- switch (mComponents)
- {
- case 1:
- // Use luminance alpha (for fonts)
- mFormatInternal = GL_LUMINANCE8;
- mFormatPrimary = GL_LUMINANCE;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- case 2:
- // Use luminance alpha (for fonts)
- mFormatInternal = GL_LUMINANCE8_ALPHA8;
- mFormatPrimary = GL_LUMINANCE_ALPHA;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- case 3:
- mFormatInternal = GL_RGB8;
- mFormatPrimary = GL_RGB;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- case 4:
- mFormatInternal = GL_RGBA8;
- mFormatPrimary = GL_RGBA;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- default:
- LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL;
- }
- }
+ if (!mHasExplicitFormat)
+ {
+ switch (mComponents)
+ {
+ case 1:
+ // Use luminance alpha (for fonts)
+ mFormatInternal = GL_LUMINANCE8;
+ mFormatPrimary = GL_LUMINANCE;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 2:
+ // Use luminance alpha (for fonts)
+ mFormatInternal = GL_LUMINANCE8_ALPHA8;
+ mFormatPrimary = GL_LUMINANCE_ALPHA;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 3:
+#if USE_SRGB_DECODE
+ if (gGLManager.mHasTexturesRGBDecode)
+ {
+ mFormatInternal = GL_SRGB8;
+ }
+ else
+#endif
+ {
+ mFormatInternal = GL_RGB8;
+ }
+ mFormatPrimary = GL_RGB;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ case 4:
+#if USE_SRGB_DECODE
+ if (gGLManager.mHasTexturesRGBDecode)
+ {
+ mFormatInternal = GL_SRGB8_ALPHA8;
+ }
+ else
+#endif
+ {
+ mFormatInternal = GL_RGBA8;
+ }
+ mFormatPrimary = GL_RGBA;
+ mFormatType = GL_UNSIGNED_BYTE;
+ break;
+ default:
+ LL_ERRS() << "Bad number of components for texture: " << (U32) getComponents() << LL_ENDL;
+ }
+ }
- mCurrentDiscardLevel = discard_level;
+ mCurrentDiscardLevel = discard_level;
mDiscardLevelInAtlas = discard_level;
mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
mLastBindTime = sLastFrameTime;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index ebc4659bcf..11d9ef3f57 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -849,26 +849,32 @@ void LLTexUnit::debugTextureUnit(void)
}
}
-void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) {
+void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
+{
mTexColorSpace = space;
#if USE_SRGB_DECODE
- if (gGLManager.mHasTexturesRGBDecode) {
-
- if (space == TCS_SRGB) {
+ if (gGLManager.mHasTexturesRGBDecode)
+ {
+ if (space == TCS_SRGB)
+ {
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
}
- else {
+ else
+ {
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
}
- if (gDebugGL) {
+ if (gDebugGL)
+ {
assert_glerror();
}
}
+ else
#endif
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
-
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+ }
}
LLLightState::LLLightState(S32 index)
@@ -1192,46 +1198,46 @@ void LLRender::refreshState(void)
void LLRender::syncLightState()
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ LLGLSLShader *shader = LLGLSLShader::sCurBoundShaderPtr;
- if (!shader)
- {
- return;
- }
+ if (!shader)
+ {
+ return;
+ }
- if (shader->mLightHash != mLightHash)
- {
- shader->mLightHash = mLightHash;
+ if (shader->mLightHash != mLightHash)
+ {
+ shader->mLightHash = mLightHash;
- LLVector4 position[8];
- LLVector3 direction[8];
- LLVector4 attenuation[8];
- LLVector3 diffuse[8];
- LLVector3 diffuse_b[8];
- bool sun_primary[8];
+ LLVector4 position[LL_NUM_LIGHT_UNITS];
+ LLVector3 direction[LL_NUM_LIGHT_UNITS];
+ LLVector4 attenuation[LL_NUM_LIGHT_UNITS];
+ LLVector3 diffuse[LL_NUM_LIGHT_UNITS];
+ LLVector3 diffuse_b[LL_NUM_LIGHT_UNITS];
+ bool sun_primary[LL_NUM_LIGHT_UNITS];
- for (U32 i = 0; i < 8; i++)
- {
- LLLightState* light = mLightState[i];
+ for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; i++)
+ {
+ LLLightState *light = mLightState[i];
- position[i] = light->mPosition;
- direction[i] = light->mSpotDirection;
+ position[i] = light->mPosition;
+ direction[i] = light->mSpotDirection;
attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[2], light->mSpecular.mV[3]);
- diffuse[i].set(light->mDiffuse.mV);
+ diffuse[i].set(light->mDiffuse.mV);
diffuse_b[i].set(light->mDiffuseB.mV);
sun_primary[i] = light->mSunIsPrimary;
- }
+ }
- shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, 8, position[0].mV);
- shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV);
- shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV);
- shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV);
- shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
+ shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, LL_NUM_LIGHT_UNITS, position[0].mV);
+ shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, LL_NUM_LIGHT_UNITS, direction[0].mV);
+ shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, LL_NUM_LIGHT_UNITS, attenuation[0].mV);
+ shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, LL_NUM_LIGHT_UNITS, diffuse[0].mV);
+ shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0);
shader->uniform4fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
- }
+ }
}
void LLRender::syncMatrices()
@@ -1539,11 +1545,17 @@ void LLRender::matrixMode(eMatrixMode mode)
{
U32 tex_index = gGL.getCurrentTexUnitIndex();
// the shaders don't actually reference anything beyond texture_matrix0/1 outside of terrain rendering
- llassert_always(tex_index <= 3);
- mode = eMatrixMode(MM_TEXTURE0 + gGL.getCurrentTexUnitIndex());
+ llassert(tex_index <= 3);
+ mode = eMatrixMode(MM_TEXTURE0 + tex_index);
+ if (mode > MM_TEXTURE3)
+ {
+ // getCurrentTexUnitIndex() can go as high as 32 (LL_NUM_TEXTURE_LAYERS)
+ // Large value will result in a crash at mMatrix
+ LL_WARNS_ONCE() << "Attempted to assign matrix mode out of bounds: " << mode << LL_ENDL;
+ mode = MM_TEXTURE0;
+ }
}
- llassert(mode < NUM_MATRIX_MODES);
mMatrixMode = mode;
}
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 9fb4f7f2b0..e3c0255290 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -501,23 +501,23 @@ U32 LLRenderTarget::getNumTextures() const
return mTex.size();
}
-
void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
{
- gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
+ gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
bool isSRGB = false;
llassert(mInternalFormat.size() > index);
switch (mInternalFormat[index])
{
- case GL_SRGB_ALPHA:
case GL_SRGB:
+ case GL_SRGB8:
+ case GL_SRGB_ALPHA:
case GL_SRGB8_ALPHA8:
isSRGB = true;
- break;
+ break;
default:
- break;
+ break;
}
gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 1383020873..236ebbd78f 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1180,7 +1180,7 @@ void LLShaderMgr::initAttribsAndUniforms()
llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1);
-
+ //NOTE: MUST match order in eGLSLReservedUniforms
mReservedUniforms.push_back("proj_mat");
mReservedUniforms.push_back("proj_near");
mReservedUniforms.push_back("proj_p");
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 6a02cd9c19..7d2b09ca4a 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -1193,7 +1193,7 @@ bool LLVertexBuffer::createGLBuffer(U32 size)
return true;
}
- bool sucsess = true;
+ bool success = true;
mEmpty = true;
@@ -1215,9 +1215,9 @@ bool LLVertexBuffer::createGLBuffer(U32 size)
if (!mMappedData)
{
- sucsess = false;
+ success = false;
}
- return sucsess;
+ return success;
}
bool LLVertexBuffer::createGLIndices(U32 size)
@@ -1232,7 +1232,7 @@ bool LLVertexBuffer::createGLIndices(U32 size)
return true;
}
- bool sucsess = true;
+ bool success = true;
mEmpty = true;
@@ -1257,9 +1257,9 @@ bool LLVertexBuffer::createGLIndices(U32 size)
if (!mMappedIndexData)
{
- sucsess = false;
+ success = false;
}
- return sucsess;
+ return success;
}
void LLVertexBuffer::destroyGLBuffer()
@@ -1306,7 +1306,7 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts)
{
llassert(nverts >= 0);
- bool sucsess = true;
+ bool success = true;
if (nverts > 65536)
{
@@ -1318,34 +1318,34 @@ bool LLVertexBuffer::updateNumVerts(S32 nverts)
if (needed_size > mSize || needed_size <= mSize/2)
{
- sucsess &= createGLBuffer(needed_size);
+ success &= createGLBuffer(needed_size);
}
sVertexCount -= mNumVerts;
mNumVerts = nverts;
sVertexCount += mNumVerts;
- return sucsess;
+ return success;
}
bool LLVertexBuffer::updateNumIndices(S32 nindices)
{
llassert(nindices >= 0);
- bool sucsess = true;
+ bool success = true;
U32 needed_size = sizeof(U16) * nindices;
if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
{
- sucsess &= createGLIndices(needed_size);
+ success &= createGLIndices(needed_size);
}
sIndexCount -= mNumIndices;
mNumIndices = nindices;
sIndexCount += mNumIndices;
- return sucsess;
+ return success;
}
bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
@@ -1358,10 +1358,10 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL;
}
- bool sucsess = true;
+ bool success = true;
- sucsess &= updateNumVerts(nverts);
- sucsess &= updateNumIndices(nindices);
+ success &= updateNumVerts(nverts);
+ success &= updateNumIndices(nindices);
if (create && (nverts || nindices))
{
@@ -1377,7 +1377,7 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
}
}
- return sucsess;
+ return success;
}
static LLTrace::BlockTimerStatHandle FTM_SETUP_VERTEX_ARRAY("Setup VAO");
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index edcbc3fbb7..809d72208f 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -55,6 +55,7 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
, mTabComparator( NULL )
, mNoVisibleTabsHelpText(NULL)
, mNoVisibleTabsOrigString(params.no_visible_tabs_text.initial_value().asString())
+ , mSkipScrollToChild(false)
{
initNoTabsWidget(params.no_matched_tabs_text);
@@ -655,6 +656,37 @@ void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
{
updateLayout(getRect().getWidth(),getRect().getHeight());
}
+
+// virtual
+void LLAccordionCtrl::onUpdateScrollToChild(const LLUICtrl *cntrl)
+{
+ if (mScrollbar && mScrollbar->getVisible() && !mSkipScrollToChild)
+ {
+ // same as scrollToShowRect
+ LLRect rect;
+ cntrl->localRectToOtherView(cntrl->getLocalRect(), &rect, this);
+
+ // Translate to parent coordinatess to check if we are in visible rectangle
+ rect.translate(getRect().mLeft, getRect().mBottom);
+
+ if (!getRect().contains(rect))
+ {
+ // for accordition's scroll, height is in pixels
+ // Back to local coords and calculate position for scroller
+ S32 bottom = mScrollbar->getDocPos() - rect.mBottom + getRect().mBottom;
+ S32 top = mScrollbar->getDocPos() - rect.mTop + getRect().mTop;
+
+ S32 scroll_pos = llclamp(mScrollbar->getDocPos(),
+ bottom, // min vertical scroll
+ top); // max vertical scroll
+
+ mScrollbar->setDocPos(scroll_pos);
+ }
+ }
+
+ LLUICtrl::onUpdateScrollToChild(cntrl);
+}
+
void LLAccordionCtrl::onOpen (const LLSD& key)
{
for(size_t i=0;i<mAccordionTabs.size();++i)
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
index 1fe64c472e..2828254472 100644
--- a/indra/llui/llaccordionctrl.h
+++ b/indra/llui/llaccordionctrl.h
@@ -111,6 +111,7 @@ public:
void draw();
void onScrollPosChangeCallback(S32, LLScrollbar*);
+ virtual void onUpdateScrollToChild(const LLUICtrl * cntrl);
void onOpen (const LLSD& key);
S32 notifyParent(const LLSD& info);
@@ -137,6 +138,8 @@ public:
bool getFitParent() const {return mFitParent;}
+ void setSkipScrollToChild(bool skip) { mSkipScrollToChild = skip; }
+
private:
void initNoTabsWidget(const LLTextBox::Params& tb_params);
void updateNoTabsHelpTextVisibility();
@@ -182,6 +185,8 @@ private:
F32 mAutoScrollRate;
LLTextBox* mNoVisibleTabsHelpText;
+ bool mSkipScrollToChild;
+
std::string mNoMatchedTabsOrigString;
std::string mNoVisibleTabsOrigString;
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 1034a21905..098621b543 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -452,6 +452,35 @@ void LLAccordionCtrlTab::onVisibilityChange(BOOL new_visibility)
notifyParent(LLSD().with("child_visibility_change", new_visibility));
}
+// virtual
+void LLAccordionCtrlTab::onUpdateScrollToChild(const LLUICtrl *cntrl)
+{
+ if (mScrollbar && mScrollbar->getVisible())
+ {
+ LLRect rect;
+ cntrl->localRectToOtherView(cntrl->getLocalRect(), &rect, this);
+
+ // Translate to parent coordinatess to check if we are in visible rectangle
+ rect.translate(getRect().mLeft, getRect().mBottom);
+
+ if (!getRect().contains(rect))
+ {
+ // for accordition's scroll, height is in pixels
+ // Back to local coords and calculate position for scroller
+ S32 bottom = mScrollbar->getDocPos() - rect.mBottom + getRect().mBottom;
+ S32 top = mScrollbar->getDocPos() - rect.mTop + getRect().mTop;
+
+ S32 scroll_pos = llclamp(mScrollbar->getDocPos(),
+ bottom, // min vertical scroll
+ top); // max vertical scroll
+
+ mScrollbar->setDocPos(scroll_pos);
+ }
+ }
+
+ LLUICtrl::onUpdateScrollToChild(cntrl);
+}
+
BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
{
if(mCollapsible && mHeaderVisible && mCanOpenClose)
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index 0263bce4be..2c72e8c036 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -159,6 +159,7 @@ public:
* Raises notifyParent event with "child_visibility_change" = new_visibility
*/
void onVisibilityChange(BOOL new_visibility);
+ virtual void onUpdateScrollToChild(const LLUICtrl * cntrl);
// Changes expand/collapse state and triggers expand/collapse callbacks
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
index 0557cd4375..5f11c383ef 100644
--- a/indra/llui/llbadgeowner.cpp
+++ b/indra/llui/llbadgeowner.cpp
@@ -56,6 +56,14 @@ void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
}
}
+void LLBadgeOwner::reshapeBadge(const LLRect& new_rect)
+{
+ if (mBadge)
+ {
+ mBadge->setShape(new_rect);
+ }
+}
+
void LLBadgeOwner::setBadgeVisibility(bool visible)
{
if (mBadge)
diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h
index 01ed95f3a3..4ce208fa0d 100644
--- a/indra/llui/llbadgeowner.h
+++ b/indra/llui/llbadgeowner.h
@@ -46,6 +46,7 @@ public:
bool hasBadgeHolderParent() const { return mHasBadgeHolderParent; };
void setBadgeVisibility(bool visible);
void setDrawBadgeAtTop(bool draw_at_top);
+ void reshapeBadge(const LLRect& new_rect);
private:
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 27444b7f5b..9682c3bc10 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -643,7 +643,8 @@ void LLButton::draw()
LLColor4 highlighting_color = LLColor4::white;
LLColor4 glow_color = LLColor4::white;
LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA;
- LLUIImage* imagep = NULL;
+ LLUIImage* imagep = NULL;
+ LLUIImage* image_glow = NULL;
// Cancel sticking of color, if the button is pressed,
// or when a flashing of the previously selected button is ended
@@ -710,17 +711,18 @@ void LLButton::draw()
imagep = mImageDisabled;
}
+ image_glow = imagep;
+
if (mFlashing)
{
- // if button should flash and we have icon for flashing, use it as image for button
- if(flash && mImageFlash)
+ if (flash && mImageFlash)
{
- // setting flash to false to avoid its further influence on glow
- flash = false;
- imagep = mImageFlash;
+ // if button should flash and we have icon for flashing, use it as image for button
+ image_glow = mImageFlash;
}
- // else use usual flashing via flash_color
- else if (mFlashingTimer)
+
+ // provide fade-in and fade-out via flash_color
+ if (mFlashingTimer)
{
LLColor4 flash_color = mFlashBgColor.get();
use_glow_effect = TRUE;
@@ -734,6 +736,11 @@ void LLButton::draw()
{
glow_color = highlighting_color;
}
+ else
+ {
+ // will fade from highlight color
+ glow_color = flash_color;
+ }
}
}
@@ -806,7 +813,7 @@ void LLButton::draw()
if (mCurGlowStrength > 0.01f)
{
gGL.setSceneBlendType(glow_type);
- imagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha));
+ image_glow->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), glow_color % (mCurGlowStrength * alpha));
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
@@ -817,7 +824,7 @@ void LLButton::draw()
if (mCurGlowStrength > 0.01f)
{
gGL.setSceneBlendType(glow_type);
- imagep->drawSolid(0, y, glow_color % (mCurGlowStrength * alpha));
+ image_glow->drawSolid(0, y, glow_color % (mCurGlowStrength * alpha));
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 7629ed1fea..572d36996c 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -205,6 +205,7 @@ public:
void setFlashing( bool b, bool force_flashing = false );
BOOL getFlashing() const { return mFlashing; }
LLFlashTimer* getFlashTimer() {return mFlashingTimer;}
+ void setFlashColor(const LLUIColor &color) { mFlashBgColor = color; };
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
LLFontGL::HAlign getHAlign() const { return mHAlign; }
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index c7f0326ed4..52dc908655 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -514,6 +514,14 @@ S32 LLComboBox::getCurrentIndex() const
return -1;
}
+void LLComboBox::setEnabledByValue(const LLSD& value, BOOL enabled)
+{
+ LLScrollListItem *found = mList->getItem(value);
+ if (found)
+ {
+ found->setEnabled(enabled);
+ }
+}
void LLComboBox::createLineEditor(const LLComboBox::Params& p)
{
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 7d38c051a5..4af3313162 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -158,6 +158,8 @@ public:
BOOL setCurrentByIndex( S32 index );
S32 getCurrentIndex() const;
+ void setEnabledByValue(const LLSD& value, BOOL enabled);
+
void createLineEditor(const Params&);
//========================================================================
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index e718fcec46..0c1dcc301b 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -342,7 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View");
void LLFolderView::filter( LLFolderViewFilter& filter )
{
LL_RECORD_BLOCK_TIME(FTM_FILTER);
- filter.resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32(mParentPanel.get()->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100));
+ static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
+ static LLCachedControl<S32> filter_hidden(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
+ filter.resetTime(llclamp(mParentPanel.get()->getVisible() ? filter_visible() : filter_hidden(), 1, 100));
// Note: we filter the model, not the view
getViewModelItem()->filter(filter);
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 9a1f7de73b..1c6c7b1b35 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -122,6 +122,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
: LLView(p),
mLabelWidth(0),
mLabelWidthDirty(false),
+ mSuffixNeedsRefresh(false),
mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT),
mParentFolder( NULL ),
mIsSelected( FALSE ),
@@ -181,11 +182,25 @@ LLFolderViewItem::~LLFolderViewItem()
BOOL LLFolderViewItem::postBuild()
{
- refresh();
+ LLFolderViewModelItem& vmi = *getViewModelItem();
+ // getDisplayName() is expensive (due to internal getLabelSuffix() and name building)
+ // it also sets search strings so it requires a filter reset
+ mLabel = vmi.getDisplayName();
+ setToolTip(vmi.getName());
+
+ // Dirty the filter flag of the model from the view (CHUI-849)
+ vmi.dirtyFilter();
+
+ // Don't do full refresh on constructor if it is possible to avoid
+ // it significantly slows down bulk view creation.
+ // Todo: Ideally we need to move getDisplayName() out of constructor as well.
+ // Like: make a logic that will let filter update search string,
+ // while LLFolderViewItem::arrange() updates visual part
+ mSuffixNeedsRefresh = true;
+ mLabelWidthDirty = true;
return TRUE;
}
-
LLFolderView* LLFolderViewItem::getRoot()
{
return mRoot;
@@ -280,24 +295,51 @@ BOOL LLFolderViewItem::isPotentiallyVisible(S32 filter_generation)
void LLFolderViewItem::refresh()
{
- LLFolderViewModelItem& vmi = *getViewModelItem();
+ LLFolderViewModelItem& vmi = *getViewModelItem();
+
+ mLabel = vmi.getDisplayName();
+ setToolTip(vmi.getName());
+ // icons are slightly expensive to get, can be optimized
+ // see LLInventoryIcon::getIcon()
+ mIcon = vmi.getIcon();
+ mIconOpen = vmi.getIconOpen();
+ mIconOverlay = vmi.getIconOverlay();
- mLabel = vmi.getDisplayName();
+ if (mRoot->useLabelSuffix())
+ {
+ // Very Expensive!
+ // Can do a number of expensive checks, like checking active motions, wearables or friend list
+ mLabelStyle = vmi.getLabelStyle();
+ mLabelSuffix = vmi.getLabelSuffix();
+ }
- setToolTip(vmi.getName());
- mIcon = vmi.getIcon();
- mIconOpen = vmi.getIconOpen();
- mIconOverlay = vmi.getIconOverlay();
+ // Dirty the filter flag of the model from the view (CHUI-849)
+ vmi.dirtyFilter();
+
+ mLabelWidthDirty = true;
+ mSuffixNeedsRefresh = false;
+}
+
+void LLFolderViewItem::refreshSuffix()
+{
+ LLFolderViewModelItem const* vmi = getViewModelItem();
+
+ // icons are slightly expensive to get, can be optimized
+ // see LLInventoryIcon::getIcon()
+ mIcon = vmi->getIcon();
+ mIconOpen = vmi->getIconOpen();
+ mIconOverlay = vmi->getIconOverlay();
if (mRoot->useLabelSuffix())
{
- mLabelStyle = vmi.getLabelStyle();
- mLabelSuffix = vmi.getLabelSuffix();
+ // Very Expensive!
+ // Can do a number of expensive checks, like checking active motions, wearables or friend list
+ mLabelStyle = vmi->getLabelStyle();
+ mLabelSuffix = vmi->getLabelSuffix();
}
- mLabelWidthDirty = true;
- // Dirty the filter flag of the model from the view (CHUI-849)
- vmi.dirtyFilter();
+ mLabelWidthDirty = true;
+ mSuffixNeedsRefresh = false;
}
// Utility function for LLFolderView
@@ -348,6 +390,12 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
: 0;
if (mLabelWidthDirty)
{
+ if (mSuffixNeedsRefresh)
+ {
+ // Expensive. But despite refreshing label,
+ // it is purely visual, so it is fine to do at our laisure
+ refreshSuffix();
+ }
mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight;
mLabelWidthDirty = false;
}
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 61c39e0175..da09d139e9 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -95,6 +95,7 @@ protected:
LLPointer<LLFolderViewModelItem> mViewModelItem;
LLFontGL::StyleFlags mLabelStyle;
std::string mLabelSuffix;
+ bool mSuffixNeedsRefresh; //suffix and icons
LLUIImagePtr mIcon,
mIconOpen,
mIconOverlay;
@@ -266,8 +267,13 @@ public:
virtual BOOL passedFilter(S32 filter_generation = -1);
virtual BOOL isPotentiallyVisible(S32 filter_generation = -1);
- // refresh information from the object being viewed.
- virtual void refresh();
+ // refresh information from the object being viewed.
+ // refreshes label, suffixes and sets icons. Expensive!
+ // Causes filter update
+ virtual void refresh();
+ // refreshes suffixes and sets icons. Expensive!
+ // Does not need filter update
+ virtual void refreshSuffix();
// LLView functionality
virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index 3b45fb53a2..ea106b5fae 100644
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -48,7 +48,8 @@ std::string LLFolderViewModelCommon::getStatusText()
void LLFolderViewModelCommon::filter()
{
- getFilter().resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));
+ static LLCachedControl<S32> filter_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
+ getFilter().resetTime(llclamp(filter_visible(), 1, 100));
mFolderView->getViewModelItem()->filter(getFilter());
}
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index f71a88c56e..84a1539094 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -285,17 +285,7 @@ public:
typedef std::list<LLFolderViewModelItem*> child_list_t;
virtual void addChild(LLFolderViewModelItem* child)
- {
- // Avoid duplicates: bail out if that child is already present in the list
- // Note: this happens when models are created before views
- child_list_t::const_iterator iter;
- for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
- {
- if (child == *iter)
- {
- return;
- }
- }
+ {
mChildren.push_back(child);
child->setParent(this);
dirtyFilter();
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 70304cdfd2..1badd54fca 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2151,6 +2151,7 @@ void LLLineEditor::clear()
void LLLineEditor::onTabInto()
{
selectAll();
+ LLUICtrl::onTabInto();
}
//virtual
diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp
index 20e2b569f1..b3df7c154b 100644
--- a/indra/llui/llmultisliderctrl.cpp
+++ b/indra/llui/llmultisliderctrl.cpp
@@ -509,6 +509,7 @@ void LLMultiSliderCtrl::onTabInto()
{
mEditor->onTabInto();
}
+ LLF32UICtrl::onTabInto();
}
void LLMultiSliderCtrl::reportInvalidData()
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 6a7075301b..06ec648178 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -255,7 +255,7 @@ LLNotificationForm::LLNotificationForm(const LLSD& sd)
}
else
{
- LL_WARNS() << "Invalid form data " << sd << LL_ENDL;
+ LL_WARNS("Notifications") << "Invalid form data " << sd << LL_ENDL;
mFormData = LLSD::emptyArray();
}
}
@@ -448,11 +448,11 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
mUniqueContext.push_back(context.value);
}
- LL_DEBUGS() << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL;
+ LL_DEBUGS("Notifications") << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL;
BOOST_FOREACH(const LLNotificationTemplate::Tag& tag, p.tags)
{
- LL_DEBUGS() << " tag \"" << std::string(tag.value) << "\"" << LL_ENDL;
+ LL_DEBUGS("Notifications") << " tag \"" << std::string(tag.value) << "\"" << LL_ENDL;
mTags.push_back(tag.value);
}
@@ -1398,8 +1398,14 @@ void LLNotifications::initSingleton()
createDefaultChannels();
}
+void LLNotifications::cleanupSingleton()
+{
+ clear();
+}
+
void LLNotifications::createDefaultChannels()
{
+ 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
mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "",
@@ -1455,7 +1461,7 @@ void LLNotifications::forceResponse(const LLNotification::Params& params, S32 op
if (selected_item.isUndefined())
{
- LL_WARNS() << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL;
+ LL_WARNS("Notifications") << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL;
return;
}
response[selected_item["name"].asString()] = true;
@@ -1489,12 +1495,12 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
if (found != replacements.end())
{
replacement = found->second;
- LL_DEBUGS() << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL;
+ LL_DEBUGS("Notifications") << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL;
it->second->setValue(replacement);
}
else
{
- LL_WARNS() << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL;
+ LL_WARNS("Notifications") << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL;
}
}
}
@@ -1533,7 +1539,7 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path
bool LLNotifications::loadTemplates()
{
- LL_INFOS() << "Reading notifications template" << LL_ENDL;
+ 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
// specific skin.
@@ -1604,7 +1610,7 @@ bool LLNotifications::loadTemplates()
mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification));
}
- LL_INFOS() << "...done" << LL_ENDL;
+ LL_INFOS("Notifications") << "...done" << LL_ENDL;
return true;
}
@@ -1832,7 +1838,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
for(it = mVisibilityRules.begin(); it != mVisibilityRules.end(); it++)
{
// An empty type/tag/name string will match any notification, so only do the comparison when the string is non-empty in the rule.
- LL_DEBUGS()
+ LL_DEBUGS("Notifications")
<< "notification \"" << n->getName() << "\" "
<< "testing against " << ((*it)->mVisible?"show":"hide") << " rule, "
<< "name = \"" << (*it)->mName << "\" "
@@ -1877,7 +1883,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
if((*it)->mResponse.empty())
{
// Response property is empty. Cancel this notification.
- LL_DEBUGS() << "cancelling notification " << n->getName() << LL_ENDL;
+ LL_DEBUGS("Notifications") << "cancelling notification " << n->getName() << LL_ENDL;
cancel(n);
}
@@ -1888,7 +1894,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
// TODO: verify that the response template has an item with the correct name
response[(*it)->mResponse] = true;
- LL_DEBUGS() << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL;
+ LL_DEBUGS("Notifications") << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL;
n->respond(response);
}
@@ -1900,7 +1906,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
break;
}
- LL_DEBUGS() << "allowing notification " << n->getName() << LL_ENDL;
+ LL_DEBUGS("Notifications") << "allowing notification " << n->getName() << LL_ENDL;
return true;
}
@@ -1961,7 +1967,7 @@ void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
// from PE merge - we should figure out if this is the right thing to do
if (name.empty())
{
- LL_WARNS() << "Empty name received for Id: " << agent_id << LL_ENDL;
+ LL_WARNS("Notifications") << "Empty name received for Id: " << agent_id << LL_ENDL;
name = SYSTEM_FROM;
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index cac687f53d..2f4578da17 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -957,6 +957,7 @@ public:
private:
/*virtual*/ void initSingleton();
+ /*virtual*/ void cleanupSingleton();
void loadPersistentNotifications();
@@ -1069,6 +1070,7 @@ public:
LLPersistentNotificationChannel()
: LLNotificationChannel("Persistent", "Visible", &notificationFilter)
{}
+ virtual ~LLPersistentNotificationChannel() {}
typedef std::vector<LLNotificationPtr> history_list_t;
history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); }
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 763c3aeb81..367c6c3c5b 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -132,6 +132,7 @@ LLScrollListCtrl::Params::Params()
sort_ascending("sort_ascending", true),
mouse_wheel_opaque("mouse_wheel_opaque", false),
commit_on_keyboard_movement("commit_on_keyboard_movement", true),
+ commit_on_selection_change("commit_on_selection_change", false),
heading_height("heading_height"),
page_lines("page_lines", 0),
background_visible("background_visible"),
@@ -162,7 +163,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mMaxSelectable(0),
mAllowKeyboardMovement(true),
mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
- mCommitOnSelectionChange(false),
+ mCommitOnSelectionChange(p.commit_on_selection_change),
mSelectionChanged(false),
mNeedsScroll(false),
mCanSelect(true),
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 43e1c0d707..8d00296183 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -97,6 +97,7 @@ public:
// behavioral flags
Optional<bool> multi_select,
commit_on_keyboard_movement,
+ commit_on_selection_change,
mouse_wheel_opaque;
// display flags
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 3b89a8ca63..d80a434f22 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -479,6 +479,7 @@ void LLSliderCtrl::onTabInto()
{
mEditor->onTabInto();
}
+ LLF32UICtrl::onTabInto();
}
void LLSliderCtrl::reportInvalidData()
diff --git a/indra/llui/llspellcheck.cpp b/indra/llui/llspellcheck.cpp
index 296ea09079..ebd8ca0923 100644
--- a/indra/llui/llspellcheck.cpp
+++ b/indra/llui/llspellcheck.cpp
@@ -49,8 +49,6 @@ LLSpellChecker::settings_change_signal_t LLSpellChecker::sSettingsChangeSignal;
LLSpellChecker::LLSpellChecker()
: mHunspell(NULL)
{
- // Load initial dictionary information
- refreshDictionaryMap();
}
LLSpellChecker::~LLSpellChecker()
@@ -58,6 +56,12 @@ LLSpellChecker::~LLSpellChecker()
delete mHunspell;
}
+void LLSpellChecker::initSingleton()
+{
+ // Load initial dictionary information
+ refreshDictionaryMap();
+}
+
bool LLSpellChecker::checkSpelling(const std::string& word) const
{
if ( (!mHunspell) || (word.length() < 3) || (0 != mHunspell->spell(word.c_str())) )
diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h
index f1964cc091..3da5e30955 100644
--- a/indra/llui/llspellcheck.h
+++ b/indra/llui/llspellcheck.h
@@ -47,6 +47,7 @@ public:
protected:
void addToDictFile(const std::string& dict_path, const std::string& word);
void initHunspell(const std::string& dict_language);
+ void initSingleton();
public:
typedef std::list<std::string> dict_list_t;
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index ce3fc29d32..ee78b82429 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -442,7 +442,8 @@ void LLSpinCtrl::setAllowEdit(BOOL allow_edit)
void LLSpinCtrl::onTabInto()
{
- mEditor->onTabInto();
+ mEditor->onTabInto();
+ LLF32UICtrl::onTabInto();
}
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 6521b883f8..e6b43da8e5 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -220,6 +220,8 @@ LLTabContainer::Params::Params()
last_tab("last_tab"),
use_custom_icon_ctrl("use_custom_icon_ctrl", false),
open_tabs_on_drag_and_drop("open_tabs_on_drag_and_drop", false),
+ enable_tabs_flashing("enable_tabs_flashing", false),
+ tabs_flashing_color("tabs_flashing_color"),
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
use_ellipses("use_ellipses"),
font_halign("halign")
@@ -259,6 +261,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mCustomIconCtrlUsed(p.use_custom_icon_ctrl),
mOpenTabsOnDragAndDrop(p.open_tabs_on_drag_and_drop),
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
+ mEnableTabsFlashing(p.enable_tabs_flashing),
+ mTabsFlashingColor(p.tabs_flashing_color),
mUseTabEllipses(p.use_ellipses)
{
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
@@ -280,6 +284,11 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mMinTabWidth = tabcntr_vert_tab_min_width;
}
+ if (p.tabs_flashing_color.isProvided())
+ {
+ mEnableTabsFlashing = true;
+ }
+
initButtons( );
}
@@ -1102,6 +1111,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.pad_left( mLabelPadLeft );
p.pad_right(2);
}
+
+ // inits flash timer
+ p.button_flash_enable = mEnableTabsFlashing;
+ p.flash_color = mTabsFlashingColor;
// *TODO : It seems wrong not to use p in both cases considering the way p is initialized
if (mCustomIconCtrlUsed)
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 6bf963313c..8f8cedb1b9 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -109,6 +109,12 @@ public:
* Open tabs on hover in drag and drop situations
*/
Optional<bool> open_tabs_on_drag_and_drop;
+
+ /**
+ * Enable tab flashing
+ */
+ Optional<bool> enable_tabs_flashing;
+ Optional<LLUIColor> tabs_flashing_color;
/**
* Paddings for LLIconCtrl in case of LLCustomButtonIconCtrl usage(use_custom_icon_ctrl = true)
@@ -310,6 +316,8 @@ private:
bool mCustomIconCtrlUsed;
bool mOpenTabsOnDragAndDrop;
+ bool mEnableTabsFlashing;
+ LLUIColor mTabsFlashingColor;
S32 mTabIconCtrlPad;
bool mUseTabEllipses;
};
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 83b851eed2..ff72417867 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1017,7 +1017,38 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
// handle triple click
if (!mTripleClickTimer.hasExpired())
{
- selectAll();
+ S32 real_line = getLineNumFromDocIndex(mCursorPos, false);
+ S32 line_start = -1;
+ S32 line_end = -1;
+ for (line_list_t::const_iterator it = mLineInfoList.begin(), end_it = mLineInfoList.end();
+ it != end_it;
+ ++it)
+ {
+ if (it->mLineNum < real_line)
+ {
+ continue;
+ }
+ if (it->mLineNum > real_line)
+ {
+ break;
+ }
+ if (line_start == -1)
+ {
+ line_start = it->mDocIndexStart;
+ }
+ line_end = it->mDocIndexEnd;
+ line_end = llclamp(line_end, 0, getLength());
+ }
+
+ if (line_start == -1)
+ {
+ return TRUE;
+ }
+
+ mSelectionEnd = line_start;
+ mSelectionStart = line_end;
+ setCursorPos(line_start);
+
return TRUE;
}
@@ -2228,6 +2259,18 @@ void LLTextBase::needsReflow(S32 index)
mReflowIndex = llmin(mReflowIndex, index);
}
+S32 LLTextBase::removeFirstLine()
+{
+ if (!mLineInfoList.empty())
+ {
+ S32 length = getLineEnd(0);
+ deselect();
+ removeStringNoUndo(0, length);
+ return length;
+ }
+ return 0;
+}
+
void LLTextBase::appendLineBreakSegment(const LLStyle::Params& style_params)
{
segment_vec_t segments;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 8687e7aa2a..4e966b7cef 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -404,6 +404,7 @@ public:
virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style
virtual std::string getText() const;
void setMaxTextLength(S32 length) { mMaxTextByteLength = length; }
+ S32 getMaxTextLength() { return mMaxTextByteLength; }
// wide-char versions
void setWText(const LLWString& text);
@@ -432,6 +433,7 @@ public:
S32 getLength() const { return getWText().length(); }
S32 getLineCount() const { return mLineInfoList.size(); }
+ S32 removeFirstLine(); // returns removed length
void addDocumentChild(LLView* view);
void removeDocumentChild(LLView* view);
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index c98da0d410..544a76e8d5 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -721,8 +721,9 @@ void LLUICtrl::resetDirty()
}
// virtual
-void LLUICtrl::onTabInto()
+void LLUICtrl::onTabInto()
{
+ onUpdateScrollToChild(this);
}
// virtual
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 333d03f208..e6835f73fb 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -454,13 +454,17 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
}
//
-// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link
+// LLUrlEntrySeconlifeURL Describes *secondlife.com/ *lindenlab.com/ *secondlifegrid.net/ and *tilia-inc.com/ urls to substitute icon 'hand.png' before link
//
LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
{
mPattern = boost::regex("((http://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com)"
"|"
- "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?))"
+ "(http://([-\\w\\.]*\\.)?secondlifegrid\\.net)"
+ "|"
+ "(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)"
+ "|"
+ "(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))"
"\\/\\S*",
boost::regex::perl|boost::regex::icase);
@@ -495,12 +499,14 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const
}
//
-// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com and *tilia-inc.com urls to substitute icon 'hand.png' before link
+// LLUrlEntrySimpleSecondlifeURL Describes *secondlife.com *lindenlab.com *secondlifegrid.net and *tilia-inc.com urls to substitute icon 'hand.png' before link
//
LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()
{
- mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)",
- boost::regex::perl|boost::regex::icase);
+ mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(?!\\S)"
+ "|"
+ "https?://([-\\w\\.]*\\.)?secondlifegrid\\.net(?!\\S)",
+ boost::regex::perl|boost::regex::icase);
mIcon = "Hand";
mMenuName = "menu_url_http.xml";
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index bd213d594a..e3a6a98a9f 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -646,6 +646,16 @@ void LLView::onVisibilityChange ( BOOL new_visibility )
}
// virtual
+void LLView::onUpdateScrollToChild(const LLUICtrl * cntrl)
+{
+ LLView* parent_view = getParent();
+ if (parent_view)
+ {
+ parent_view->onUpdateScrollToChild(cntrl);
+ }
+}
+
+// virtual
void LLView::translate(S32 x, S32 y)
{
mRect.translate(x, y);
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index db81900aaf..5c91c37d3c 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -301,6 +301,7 @@ public:
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
virtual void onVisibilityChange ( BOOL new_visibility );
+ virtual void onUpdateScrollToChild(const LLUICtrl * cntrl);
void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); }
void popVisible() { setVisible(mLastVisible); }
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 5b9dce02c4..d2c5b11c3d 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -359,10 +359,10 @@ attributedStringInfo getSegments(NSAttributedString *str)
callRightMouseDown(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = true;
} else {
- if ([theEvent clickCount] >= 2)
+ if ([theEvent clickCount] == 2)
{
callDoubleClick(mMousePos, [theEvent modifierFlags]);
- } else if ([theEvent clickCount] == 1) {
+ } else if ([theEvent clickCount] >= 1) {
callLeftMouseDown(mMousePos, [theEvent modifierFlags]);
}
}
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 7783505c27..180954f715 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -784,9 +784,6 @@ void LLWindowWin32::close()
resetDisplayResolution();
}
- // Don't process events in our mainWindowProc any longer.
- SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, NULL);
-
// Make sure cursor is visible and we haven't mangled the clipping state.
showCursor();
setMouseClipping(FALSE);
@@ -1133,7 +1130,10 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
<< " Height: " << (window_rect.bottom - window_rect.top)
<< " Fullscreen: " << mFullscreen
<< LL_ENDL;
- DestroyWindow(mWindowHandle);
+ if (!destroy_window_handler(mWindowHandle))
+ {
+ LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL;
+ }
mWindowHandle = CreateWindowEx(dw_ex_style,
mWindowClassName,
mWindowTitle,
@@ -1453,8 +1453,12 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
ReleaseDC (mWindowHandle, mhDC); // Release The Device Context
mhDC = 0; // Zero The Device Context
}
- DestroyWindow (mWindowHandle); // Destroy The Window
-
+
+ // Destroy The Window
+ if (!destroy_window_handler(mWindowHandle))
+ {
+ LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL;
+ }
mWindowHandle = CreateWindowEx(dw_ex_style,
mWindowClassName,
@@ -3397,7 +3401,10 @@ void LLSplashScreenWin32::hideImpl()
{
if (mWindow)
{
- DestroyWindow(mWindow);
+ if (!destroy_window_handler(mWindow))
+ {
+ LL_WARNS("Window") << "Failed to properly close splash screen window!" << LL_ENDL;
+ }
mWindow = NULL;
}
}
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index bc967c9bca..0bb62d79ff 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -98,7 +98,9 @@ private:
bool mCanCut;
bool mCanCopy;
bool mCanPaste;
+ std::string mRootCachePath;
std::string mCachePath;
+ std::string mContextCachePath;
std::string mCefLogFile;
bool mCefLogVerbose;
std::vector<std::string> mPickedFiles;
@@ -458,7 +460,6 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
}
else if (message_name == "cleanup")
{
- mVolumeCatcher.setVolume(0); // Hack: masks CEF exit issues
mCEFLib->requestExit();
}
else if (message_name == "force_exit")
@@ -527,7 +528,9 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
settings.accept_language_list = mHostLanguage;
settings.background_color = 0xffffffff;
settings.cache_enabled = true;
+ settings.root_cache_path = mRootCachePath;
settings.cache_path = mCachePath;
+ settings.context_cache_path = mContextCachePath;
settings.cookies_enabled = mCookiesEnabled;
settings.disable_gpu = mDisableGPU;
#if LL_DARWIN
@@ -583,9 +586,25 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
else if (message_name == "set_user_data_path")
{
std::string user_data_path_cache = message_in.getValue("cache_path");
- std::string user_data_path_cookies = message_in.getValue("cookies_path");
+ std::string subfolder = message_in.getValue("username");
- mCachePath = user_data_path_cache + "cef_cache";
+ mRootCachePath = user_data_path_cache + "cef_cache";
+ if (!subfolder.empty())
+ {
+ std::string delim;
+#if LL_WINDOWS
+ // media plugin doesn't have access to gDirUtilp
+ delim = "\\";
+#else
+ delim = "/";
+#endif
+ mCachePath = mRootCachePath + delim + subfolder;
+ }
+ else
+ {
+ mCachePath = mRootCachePath;
+ }
+ mContextCachePath = ""; // disabled by ""
mCefLogFile = message_in.getValue("cef_log_file");
mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log");
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 88667bdc11..3439951e80 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -401,6 +401,7 @@ set(viewer_SOURCE_FILES
llmenuoptionpathfindingrebakenavmesh.cpp
llmeshrepository.cpp
llmimetypes.cpp
+ llmodelpreview.cpp
llmorphview.cpp
llmoveview.cpp
llmutelist.cpp
@@ -1032,6 +1033,7 @@ set(viewer_HEADER_FILES
llmenuoptionpathfindingrebakenavmesh.h
llmeshrepository.h
llmimetypes.h
+ llmodelpreview.h
llmorphview.h
llmoveview.h
llmutelist.h
@@ -1618,6 +1620,10 @@ if (WINDOWS)
# causes those systems to run in a Windows 8 compatibility mode, which works.
LIST(APPEND viewer_SOURCE_FILES windows.manifest)
endif (ADDRESS_SIZE EQUAL 64)
+
+ if (OPENAL)
+ LIST(APPEND viewer_LIBRARIES ${OPENAL_LIBRARIES})
+ endif (OPENAL)
endif (WINDOWS)
# Add the xui files. This is handy for searching for xui elements
@@ -1719,6 +1725,12 @@ if (FMODSTUDIO)
endif (FMODSTUDIO)
set_source_files_properties(llstartup.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
+
+if (HAVOK OR HAVOK_TPV)
+ set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_HAVOK")
+endif (HAVOK OR HAVOK_TPV)
+
+# progress view disables/enables icons based on available packages
set_source_files_properties(llprogressview.cpp PROPERTIES COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS}")
list(APPEND viewer_SOURCE_FILES ${viewer_HEADER_FILES})
@@ -1841,6 +1853,13 @@ if (WINDOWS)
)
endif (FMODSTUDIO)
+ if (OPENAL)
+ list(APPEND COPY_INPUT_DEPENDENCIES
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/OpenAL32.dll
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/alut.dll
+ )
+ endif (OPENAL)
+
add_custom_command(
OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat
COMMAND ${PYTHON_EXECUTABLE}
@@ -1851,6 +1870,7 @@ if (WINDOWS)
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--fmodstudio=${FMODSTUDIO}"
+ "--openal=${OPENAL}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
@@ -1913,6 +1933,7 @@ if (WINDOWS)
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--fmodstudio=${FMODSTUDIO}"
+ "--openal=${OPENAL}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
@@ -2060,6 +2081,7 @@ if (LINUX)
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--fmodstudio=${FMODSTUDIO}"
+ "--openal=${OPENAL}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
@@ -2087,6 +2109,7 @@ if (LINUX)
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--fmodstudio=${FMODSTUDIO}"
+ "--openal=${OPENAL}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
@@ -2124,7 +2147,7 @@ if (DARWIN)
set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}")
- set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2019")
+ set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2020")
set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib")
set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication")
@@ -2164,6 +2187,7 @@ if (DARWIN)
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--fmodstudio=${FMODSTUDIO}"
+ "--openal=${OPENAL}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
--bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER}
@@ -2199,6 +2223,7 @@ if (DARWIN)
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--fmodstudio=${FMODSTUDIO}"
+ "--openal=${OPENAL}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=${CMAKE_BUILD_TYPE}
"--channel=${VIEWER_CHANNEL}"
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 4b20d9700d..e5a66bad38 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.8
+6.4.11
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a00aa86d78..52dc4744f2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -812,17 +812,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>FramePerSecondLimit</key>
- <map>
- <key>Comment</key>
- <string>Controls upper limit of frames per second</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>U32</string>
- <key>Value</key>
- <integer>120</integer>
- </map>
<key>BackgroundYieldTime</key>
<map>
<key>Comment</key>
@@ -6719,7 +6708,7 @@
<integer>600</integer>
</map>
<key>MigrateCacheDirectory</key>
- <map>
+ <map>
<key>Comment</key>
<string>Check for old version of disk cache to migrate to current location</string>
<key>Persist</key>
@@ -7969,7 +7958,6 @@
<key>Value</key>
<integer>13</integer>
</map>
-
<key>PreviewAmbientColor</key>
<map>
<key>Comment</key>
@@ -7986,8 +7974,6 @@
<real>1.0</real>
</array>
</map>
-
-
<key>PreviewDiffuse0</key>
<map>
<key>Comment</key>
@@ -14420,7 +14406,7 @@
<key>VoiceCallsFriendsOnly</key>
<map>
<key>Comment</key>
- <string>Only accept voice calls from residents on your friends list</string>
+ <string>(Deprecated) Only accept voice calls from residents on your friends list</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -16618,3 +16604,4 @@
</map>
</llsd>
+
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 8f4ca6c633..537744b44c 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -220,6 +220,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>VoiceCallsFriendsOnly</key>
+ <map>
+ <key>Comment</key>
+ <string>Only accept voice calls and receive IMs from residents on your friends list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>VoiceEffectDefault</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index caa4fe1f65..b7036e02cf 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file WLCloudsV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
@@ -33,26 +33,26 @@ ATTRIBUTE vec2 texcoord0;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec4 vary_CloudColorSun;
+VARYING vec4 vary_CloudColorAmbient;
VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
VARYING float altitude_blend_factor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -60,7 +60,7 @@ uniform float cloud_shadow;
uniform float density_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec4 glow;
uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
@@ -70,133 +70,123 @@ uniform float cloud_scale;
// NOTE: Keep these in sync!
// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
// indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+// indra\newview\app-settings\shaders\class2\windlight\cloudsV.glsl
// indra\newview\lllegacyatmospherics.cpp
+// indra\newview\llsettingsvo.cpp
void main()
{
-
- // World / view / projection
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-
- // Texture coords
- vary_texcoord0 = texcoord0;
- vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= cloud_scale;
- vary_texcoord0.xy += 0.5;
-
- vary_texcoord1 = vary_texcoord0;
- vary_texcoord1.x += lightnorm.x * 0.0125;
- vary_texcoord1.y += lightnorm.z * 0.0125;
-
- vary_texcoord2 = vary_texcoord0 * 16.;
- vary_texcoord3 = vary_texcoord1 * 16.;
-
- // Get relative position
- vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
- altitude_blend_factor = clamp((P.y + 512.0) / max_y, 0.0, 1.0);
-
- // Set altitude
- if (P.y > 0.)
- {
- P *= (max_y / P.y);
- }
- else
- {
- altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
- P *= (-32000. / P.y);
- }
-
- // Can normalize then
- vec3 Pn = normalize(P);
- float Plen = length(P);
-
- // Initialize temp variables
- vec4 temp1 = vec4(0.);
- vec4 temp2 = vec4(0.);
- vec4 blue_weight;
- vec4 haze_weight;
- //vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 sunlight = sunlight_color;
- vec4 light_atten;
-
- float dens_mul = density_multiplier;
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
- // Calculate relative weights
- temp1 = abs(blue_density) + vec4(abs(haze_density));
- blue_weight = blue_density / temp1;
- haze_weight = haze_density / temp1;
-
- // Compute sunlight from P & lightnorm (for long rays like sky)
- temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
-
- // Distance
- temp2.z = Plen * dens_mul;
-
- // Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
- // compiler gets confused.
- temp1 = exp(-temp1 * temp2.z);
-
-
- // Compute haze glow
- temp2.x = dot(Pn, lightnorm.xyz);
- temp2.x = 1. - temp2.x;
- // temp2.x is 0 at the sun and increases away from sun
- temp2.x = max(temp2.x, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- temp2.x *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- temp2.x = pow(temp2.x, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- temp2.x *= sun_moon_glow_factor;
-
- // Add "minimum anti-solar illumination"
- temp2.x += .25;
-
- // Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
-
- // Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow);
-
- // Haze color below cloud
- vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
- );
-
- // CLOUDS
- temp2.y = max(0., lightnorm.y * 2.);
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
-
- // Cloud color out
- vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
- vary_CloudColorAmbient = tmpAmbient * cloud_color;
-
- // Attenuate cloud color by atmosphere
- temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
- vary_CloudColorSun *= temp1;
- vary_CloudColorAmbient *= temp1;
- vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
-
- // Make a nice cloud density based on the cloud_shadow value that was passed in.
- vary_CloudDensity = 2. * (cloud_shadow - 0.25);
-
-
- // Combine these to minimize register use
- vary_CloudColorAmbient += oHazeColorBelowCloud;
-
- // needs this to compile on mac
- //vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
-
- // END CLOUDS
+ // World / view / projection
+ gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+ // Texture coords
+ // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
+ vary_texcoord0 = vec2(-texcoord0.x, texcoord0.y); // See: LLSettingsVOSky::applySpecial
+
+ vary_texcoord0.xy -= 0.5;
+ vary_texcoord0.xy /= cloud_scale;
+ vary_texcoord0.xy += 0.5;
+
+ vary_texcoord1 = vary_texcoord0;
+ vary_texcoord1.x += lightnorm.x * 0.0125;
+ vary_texcoord1.y += lightnorm.z * 0.0125;
+
+ vary_texcoord2 = vary_texcoord0 * 16.;
+ vary_texcoord3 = vary_texcoord1 * 16.;
+
+ // Get relative position
+ vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+ altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
+
+ // Set altitude
+ if (rel_pos.y > 0)
+ {
+ rel_pos *= (max_y / rel_pos.y);
+ }
+ if (rel_pos.y < 0)
+ {
+ altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
+ rel_pos *= (-32000. / rel_pos.y);
+ }
+
+ // Can normalize then
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
+
+ // Initialize temp variables
+ vec4 sunlight = sunlight_color;
+ vec4 light_atten;
+
+ // Sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+
+ // Calculate relative weights
+ vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec4 blue_weight = blue_density / combined_haze;
+ vec4 haze_weight = haze_density / combined_haze;
+
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Distance
+ float density_dist = rel_pos_len * density_multiplier;
+
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist);
+
+ // Compute haze glow
+ float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ haze_glow *= sun_moon_glow_factor;
+
+ // Add "minimum anti-solar illumination"
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+ // Increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient_color;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= (1. - cloud_shadow);
+
+ // Haze color below cloud
+ vec4 additiveColorBelowCloud =
+ (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+
+ // CLOUDS
+ off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Cloud color out
+ vary_CloudColorSun = (sunlight * haze_glow) * cloud_color;
+ vary_CloudColorAmbient = tmpAmbient * cloud_color;
+
+ // Attenuate cloud color by atmosphere
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
+ vary_CloudColorSun *= combined_haze;
+ vary_CloudColorAmbient *= combined_haze;
+ vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+
+ // Make a nice cloud density based on the cloud_shadow value that was passed in.
+ vary_CloudDensity = 2. * (cloud_shadow - 0.25);
+
+ // Combine these to minimize register use
+ vary_CloudColorAmbient += oHazeColorBelowCloud;
+
+ // needs this to compile on mac
+ // vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+
+ // END CLOUDS
}
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index bd0ad3bce8..6b36d00f97 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -42,6 +42,9 @@ VARYING vec4 vary_position;
uniform samplerCube environmentMap;
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
vec3 fullbrightShinyAtmosTransport(vec3 light);
vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
vec3 fullbrightScaleSoftClip(vec3 light);
@@ -51,7 +54,9 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
-
+// See:
+// class1\deferred\fullbrightShinyF.glsl
+// class1\lighting\lightFullbrightShinyF.glsl
void main()
{
#ifdef HAS_DIFFUSE_LOOKUP
@@ -59,25 +64,39 @@ void main()
#else
vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
#endif
-
+
color.rgb *= vertex_color.rgb;
- vec3 pos = vary_position.xyz/vary_position.w;
- vec3 sunlit;
- vec3 amblit;
- vec3 additive;
- vec3 atten;
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+ vec3 pos = vary_position.xyz/vary_position.w;
+
+ calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
- calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
-
- vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
- float env_intensity = vertex_color.a;
- color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+ vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+ float env_intensity = vertex_color.a;
//color.rgb = srgb_to_linear(color.rgb);
-
- color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
- color.rgb = fullbrightScaleSoftClip(color.rgb);
+ color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+
+ color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+ }
+
+/*
+ // NOTE: HUD objects will be full bright. Uncomment if you want "some" environment lighting effecting these HUD objects.
+ else
+ {
+ vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+ float env_intensity = vertex_color.a;
+ color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+ }
+*/
color.a = 1.0;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 0afd1a9672..80d19102b6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -1,439 +1,443 @@
-/**
-* @file materialF.glsl
-*
-* $LicenseInfo:firstyear=2007&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2007, 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$
-*/
-
-/*[EXTRA_CODE_HERE]*/
-
-//class1/deferred/materialF.glsl
-
-// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
-
-#define DIFFUSE_ALPHA_MODE_NONE 0
-#define DIFFUSE_ALPHA_MODE_BLEND 1
-#define DIFFUSE_ALPHA_MODE_MASK 2
-#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-
-uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
-uniform int sun_up_factor;
-
-#ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
-#endif
-
-vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
-vec3 scaleSoftClipFrag(vec3 l);
-
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightScaleSoftClip(vec3 light);
-
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
-
-vec3 srgb_to_linear(vec3 cs);
-vec3 linear_to_srgb(vec3 cs);
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-#ifdef HAS_SUN_SHADOW
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-#endif
-
-uniform samplerCube environmentMap;
-uniform sampler2D lightFunc;
-
-// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-uniform mat3 env_mat;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-VARYING vec2 vary_fragcoord;
-
-VARYING vec3 vary_position;
-
-uniform mat4 proj_mat;
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec4 light_attenuation[8];
-uniform vec3 light_diffuse[8];
-
-float getAmbientClamp();
-
-vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
-{
- vec3 col = vec3(0);
-
- //get light vector
- vec3 lv = lp.xyz - v;
-
- //get distance
- float dist = length(lv);
- float da = 1.0;
-
- dist /= la;
-
- if (dist > 0.0 && la > 0.0)
- {
- //normalize light vector
- lv = normalize(lv);
-
- //distance attenuation
- float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0f;
-
- if (dist_atten <= 0.0)
- {
- return col;
- }
-
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
-
- //angular attenuation
- da *= dot(n, lv);
-
- float lit = 0.0f;
-
- float amb_da = ambiance;
- if (da >= 0)
- {
- lit = max(da * dist_atten, 0.0);
- col = lit * light_col * diffuse;
- amb_da += (da*0.5 + 0.5) * ambiance;
- }
- amb_da += (da*da*0.5 + 0.5) * ambiance;
- amb_da *= dist_atten;
- amb_da = min(amb_da, 1.0f - lit);
-
- // SL-10969 need to see why these are blown out
- //col.rgb += amb_da * light_col * diffuse;
-
- if (spec.a > 0.0)
- {
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(lv + npos);
- float nh = dot(n, h);
- float nv = dot(n, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
- vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
- speccol = clamp(speccol, vec3(0), vec3(1));
- col += speccol;
-
- float cur_glare = max(speccol.r, speccol.g);
- cur_glare = max(cur_glare, speccol.b);
- glare = max(glare, speccol.r);
- glare += max(cur_glare, 0.0);
- }
- }
- }
-
- return max(col, vec3(0.0, 0.0, 0.0));
-}
-
-#else
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-#endif
-
-uniform sampler2D diffuseMap; //always in sRGB space
-
-#ifdef HAS_NORMAL_MAP
-uniform sampler2D bumpMap;
-#endif
-
-#ifdef HAS_SPECULAR_MAP
-uniform sampler2D specularMap;
-
-VARYING vec2 vary_texcoord2;
-#endif
-
-uniform float env_intensity;
-uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-uniform float minimum_alpha;
-#endif
-
-#ifdef HAS_NORMAL_MAP
-VARYING vec3 vary_mat0;
-VARYING vec3 vary_mat1;
-VARYING vec3 vary_mat2;
-VARYING vec2 vary_texcoord1;
-#else
-VARYING vec3 vary_normal;
-#endif
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec2 encode_normal(vec3 n);
-
-void main()
-{
- vec2 pos_screen = vary_texcoord0.xy;
-
- vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
- diffcol.rgb *= vertex_color.rgb;
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-
- // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
- float bias = 0.001953125; // 1/512, or half an 8-bit quantization
- if (diffcol.a < minimum_alpha-bias)
- {
- discard;
- }
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
- vec3 gamma_diff = diffcol.rgb;
- diffcol.rgb = srgb_to_linear(diffcol.rgb);
-#endif
-
-#ifdef HAS_SPECULAR_MAP
- vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
- spec.rgb *= specular_color.rgb;
-#else
- vec4 spec = vec4(specular_color.rgb, 1.0);
-#endif
-
-#ifdef HAS_NORMAL_MAP
- vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
-
- norm.xyz = norm.xyz * 2 - 1;
-
- vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
- dot(norm.xyz,vary_mat1),
- dot(norm.xyz,vary_mat2));
-#else
- vec4 norm = vec4(0,0,0,1.0);
- vec3 tnorm = vary_normal;
-#endif
-
- norm.xyz = normalize(tnorm.xyz);
-
- vec2 abnormal = encode_normal(norm.xyz);
-
- vec4 final_color = diffcol;
-
-#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
- final_color.a = emissive_brightness;
-#else
- final_color.a = max(final_color.a, emissive_brightness);
-#endif
-
- vec4 final_specular = spec;
-
-#ifdef HAS_SPECULAR_MAP
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
- final_specular.a = specular_color.a * norm.a;
-#else
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
- final_specular.a = specular_color.a;
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
- //forward rendering, output just lit sRGBA
- vec3 pos = vary_position;
-
- float shadow = 1.0f;
-
-#ifdef HAS_SUN_SHADOW
- shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
-#endif
-
- spec = final_specular;
- vec4 diffuse = final_color;
- float envIntensity = final_normal.z;
-
- vec3 color = vec3(0,0,0);
-
- vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
-
- float bloom = 0.0;
- vec3 sunlit;
- vec3 amblit;
- vec3 additive;
- vec3 atten;
-
- calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
-
- // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
- // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
- // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
- //color = fullbrightScaleSoftClip(color);
-
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
- //we're in sRGB space, so gamma correct this dot product so
- // lighting from the sun stays sharp
- float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
- da = pow(da, 1.0 / 1.3);
-
- color = amblit;
-
- //darken ambient for normals perpendicular to light vector so surfaces in shadow
- // and facing away from light still have some definition to them.
- // do NOT gamma correct this dot product so ambient lighting stays soft
- float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
- ambient *= 0.5;
- ambient *= ambient;
- ambient = (1.0 - ambient);
-
- vec3 sun_contrib = min(da, shadow) * sunlit;
-
- color *= ambient;
-
- color += sun_contrib;
-
- color *= gamma_diff.rgb;
-
- float glare = 0.0;
-
- if (spec.a > 0.0) // specular reflection
- {
-#if 1 //EEP
-
- vec3 npos = -normalize(pos.xyz);
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(light_dir.xyz + npos);
- float nh = dot(norm.xyz, h);
- float nv = dot(norm.xyz, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
- vec3 sp = sun_contrib*scol / 6.0f;
- sp = clamp(sp, vec3(0), vec3(1));
- bloom = dot(sp, sp) / 4.0;
- color += sp * spec.rgb;
- }
-#else // PRODUCTION
- float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-
- // add the two types of shiny together
- vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib) / 6;
-
- glare = max(spec_contrib.r, spec_contrib.g);
- glare = max(glare, spec_contrib.b);
-
- color += spec_contrib;
-#endif
- }
-
- color = mix(color.rgb, diffcol.rgb, diffuse.a);
-
- if (envIntensity > 0.0)
- {
- //add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
-
- vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
-
- color = mix(color, reflected_color, envIntensity);
-
- float cur_glare = max(reflected_color.r, reflected_color.g);
- cur_glare = max(cur_glare, reflected_color.b);
- cur_glare *= envIntensity*4.0;
- glare += cur_glare;
- }
-
- color = atmosFragLighting(color, additive, atten);
- color = scaleSoftClipFrag(color);
-
- //convert to linear before adding local lights
- color = srgb_to_linear(color);
-
- vec3 npos = normalize(-pos.xyz);
-
- vec3 light = vec3(0, 0, 0);
-
-#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
-
- LIGHT_LOOP(1)
- LIGHT_LOOP(2)
- LIGHT_LOOP(3)
- LIGHT_LOOP(4)
- LIGHT_LOOP(5)
- LIGHT_LOOP(6)
- LIGHT_LOOP(7)
-
- color += light;
-
- glare = min(glare, 1.0);
- float al = max(diffcol.a, glare)*vertex_color.a;
-
- //convert to srgb as this color is being written post gamma correction
- color = linear_to_srgb(color);
-
-#ifdef WATER_FOG
- vec4 temp = applyWaterFogView(pos, vec4(color, al));
- color = temp.rgb;
- al = temp.a;
-#endif
-
- frag_color = vec4(color, al);
-
-#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
-
- // deferred path
- frag_data[0] = final_color; //gbuffer is sRGB
- frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
- frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity.
-#endif
-}
-
+/**
+* @file materialF.glsl
+*
+* $LicenseInfo:firstyear=2007&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2007, 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$
+*/
+
+/*[EXTRA_CODE_HERE]*/
+
+//class1/deferred/materialF.glsl
+
+// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
+
+#define DIFFUSE_ALPHA_MODE_NONE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
+uniform int sun_up_factor;
+
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
+#endif
+
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFrag(vec3 l);
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+vec3 srgb_to_linear(vec3 cs);
+vec3 linear_to_srgb(vec3 cs);
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+#ifdef HAS_SUN_SHADOW
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+#endif
+
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+uniform mat3 env_mat;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+VARYING vec2 vary_fragcoord;
+
+VARYING vec3 vary_position;
+
+uniform mat4 proj_mat;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8];
+uniform vec4 light_attenuation[8];
+uniform vec3 light_diffuse[8];
+
+float getAmbientClamp();
+
+vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
+{
+ vec3 col = vec3(0);
+
+ //get light vector
+ vec3 lv = lp.xyz - v;
+
+ //get distance
+ float dist = length(lv);
+ float da = 1.0;
+
+ dist /= la;
+
+ if (dist > 0.0 && la > 0.0)
+ {
+ //normalize light vector
+ lv = normalize(lv);
+
+ //distance attenuation
+ float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0f;
+
+ if (dist_atten <= 0.0)
+ {
+ return col;
+ }
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= dot(n, lv);
+
+ float lit = 0.0f;
+
+ float amb_da = ambiance;
+ if (da >= 0)
+ {
+ lit = max(da * dist_atten, 0.0);
+ col = lit * light_col * diffuse;
+ amb_da += (da*0.5 + 0.5) * ambiance;
+ }
+ amb_da += (da*da*0.5 + 0.5) * ambiance;
+ amb_da *= dist_atten;
+ amb_da = min(amb_da, 1.0f - lit);
+
+ // SL-10969 need to see why these are blown out
+ //col.rgb += amb_da * light_col * diffuse;
+
+ if (spec.a > 0.0)
+ {
+ //vec3 ref = dot(pos+lv, norm);
+ vec3 h = normalize(lv + npos);
+ float nh = dot(n, h);
+ float nv = dot(n, npos);
+ float vh = dot(npos, h);
+ float sa = nh;
+ float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
+ vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ col += speccol;
+
+ float cur_glare = max(speccol.r, speccol.g);
+ cur_glare = max(cur_glare, speccol.b);
+ glare = max(glare, speccol.r);
+ glare += max(cur_glare, 0.0);
+ }
+ }
+ }
+
+ return max(col, vec3(0.0, 0.0, 0.0));
+}
+
+#else
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+#endif
+
+uniform sampler2D diffuseMap; //always in sRGB space
+
+#ifdef HAS_NORMAL_MAP
+uniform sampler2D bumpMap;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+uniform sampler2D specularMap;
+
+VARYING vec2 vary_texcoord2;
+#endif
+
+uniform float env_intensity;
+uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+uniform float minimum_alpha;
+#endif
+
+#ifdef HAS_NORMAL_MAP
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
+#else
+VARYING vec3 vary_normal;
+#endif
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+vec2 encode_normal(vec3 n);
+
+void main()
+{
+ vec2 pos_screen = vary_texcoord0.xy;
+
+ vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
+ diffcol.rgb *= vertex_color.rgb;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+
+ // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
+ float bias = 0.001953125; // 1/512, or half an 8-bit quantization
+ if (diffcol.a < minimum_alpha-bias)
+ {
+ discard;
+ }
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ vec3 gamma_diff = diffcol.rgb;
+ diffcol.rgb = srgb_to_linear(diffcol.rgb);
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
+ spec.rgb *= specular_color.rgb;
+#else
+ vec4 spec = vec4(specular_color.rgb, 1.0);
+#endif
+
+#ifdef HAS_NORMAL_MAP
+ vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+
+ norm.xyz = norm.xyz * 2 - 1;
+
+ vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+ dot(norm.xyz,vary_mat1),
+ dot(norm.xyz,vary_mat2));
+#else
+ vec4 norm = vec4(0,0,0,1.0);
+ vec3 tnorm = vary_normal;
+#endif
+
+ norm.xyz = normalize(tnorm.xyz);
+
+ vec2 abnormal = encode_normal(norm.xyz);
+
+ vec4 final_color = diffcol;
+
+#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
+ final_color.a = emissive_brightness;
+#else
+ final_color.a = max(final_color.a, emissive_brightness);
+#endif
+
+ vec4 final_specular = spec;
+
+#ifdef HAS_SPECULAR_MAP
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
+ final_specular.a = specular_color.a * norm.a;
+#else
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
+ final_specular.a = specular_color.a;
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+ //forward rendering, output just lit sRGBA
+ vec3 pos = vary_position;
+
+ float shadow = 1.0f;
+
+#ifdef HAS_SUN_SHADOW
+ shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
+#endif
+
+ spec = final_specular;
+ vec4 diffuse = final_color;
+ float envIntensity = final_normal.z;
+
+ vec3 color = vec3(0,0,0);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+
+ float bloom = 0.0;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+
+ calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
+
+ // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
+ // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
+ // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
+ //color = fullbrightScaleSoftClip(color);
+
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+ //we're in sRGB space, so gamma correct this dot product so
+ // lighting from the sun stays sharp
+ float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
+ da = pow(da, 1.0 / 1.3);
+
+ color = amblit;
+
+ //darken ambient for normals perpendicular to light vector so surfaces in shadow
+ // and facing away from light still have some definition to them.
+ // do NOT gamma correct this dot product so ambient lighting stays soft
+ float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+ ambient *= 0.5;
+ ambient *= ambient;
+ ambient = (1.0 - ambient);
+
+ vec3 sun_contrib = min(da, shadow) * sunlit;
+
+ color *= ambient;
+
+ color += sun_contrib;
+
+ color *= gamma_diff.rgb;
+
+ float glare = 0.0;
+
+ if (spec.a > 0.0) // specular reflection
+ {
+ /* // Reverting this specular calculation to previous 'dumbshiny' version - DJH 6/17/2020
+ // Preserving the refactored version as a comment for potential reconsideration,
+ // overriding the general rule to avoid pollutiong the source with commented code.
+ //
+ // If you're reading this in 2021+, feel free to obliterate.
+
+ vec3 npos = -normalize(pos.xyz);
+
+ //vec3 ref = dot(pos+lv, norm);
+ vec3 h = normalize(light_dir.xyz + npos);
+ float nh = dot(norm.xyz, h);
+ float nv = dot(norm.xyz, npos);
+ float vh = dot(npos, h);
+ float sa = nh;
+ float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
+ vec3 sp = sun_contrib*scol / 6.0f;
+ sp = clamp(sp, vec3(0), vec3(1));
+ bloom = dot(sp, sp) / 4.0;
+ color += sp * spec.rgb;
+ }
+ */
+
+ float sa = dot(refnormpersp, sun_dir.xyz);
+ vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
+
+ glare = max(spec_contrib.r, spec_contrib.g);
+ glare = max(glare, spec_contrib.b);
+
+ color += spec_contrib;
+ }
+
+ color = mix(color.rgb, diffcol.rgb, diffuse.a);
+
+ if (envIntensity > 0.0)
+ {
+ //add environmentmap
+ vec3 env_vec = env_mat * refnormpersp;
+
+ vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
+
+ color = mix(color, reflected_color, envIntensity);
+
+ float cur_glare = max(reflected_color.r, reflected_color.g);
+ cur_glare = max(cur_glare, reflected_color.b);
+ cur_glare *= envIntensity*4.0;
+ glare += cur_glare;
+ }
+
+ color = atmosFragLighting(color, additive, atten);
+ color = scaleSoftClipFrag(color);
+
+ //convert to linear before adding local lights
+ color = srgb_to_linear(color);
+
+ vec3 npos = normalize(-pos.xyz);
+
+ vec3 light = vec3(0, 0, 0);
+
+#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ color += light;
+
+ glare = min(glare, 1.0);
+ float al = max(diffcol.a, glare)*vertex_color.a;
+
+ //convert to srgb as this color is being written post gamma correction
+ color = linear_to_srgb(color);
+
+#ifdef WATER_FOG
+ vec4 temp = applyWaterFogView(pos, vec4(color, al));
+ color = temp.rgb;
+ al = temp.a;
+#endif
+
+ frag_color = vec4(color, al);
+
+#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
+
+ // deferred path
+ frag_data[0] = final_color; //gbuffer is sRGB
+ frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
+ frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity.
+#endif
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
index 80f232948a..35068899ee 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
@@ -1,9 +1,9 @@
/**
- * @file moonF.glsl
+ * @file class1\deferred\moonF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2005, 2020 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
@@ -36,34 +36,33 @@ out vec4 frag_data[3];
uniform vec4 color;
uniform vec4 sunlight_color;
uniform vec4 moonlight_color;
-uniform vec3 lumWeights;
+uniform vec3 moon_dir;
uniform float moon_brightness;
-uniform float minLuminance;
uniform sampler2D diffuseMap;
-uniform sampler2D altDiffuseMap;
-uniform float blend_factor; // interp factor between moon A/B
+
VARYING vec2 vary_texcoord0;
vec3 srgb_to_linear(vec3 c);
-void main()
-{
- vec4 moonA = texture2D(diffuseMap, vary_texcoord0.xy);
- vec4 moonB = texture2D(altDiffuseMap, vary_texcoord0.xy);
- vec4 c = mix(moonA, moonB, blend_factor);
- c.rgb = srgb_to_linear(c.rgb);
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light);
- // mix factor which blends when sunlight is brighter
- // and shows true moon color at night
- vec3 luma_weights = vec3(0.3, 0.5, 0.3);
+void main()
+{
+ // Restore Pre-EEP alpha fade moon near horizon
+ float fade = 1.0;
+ if( moon_dir.z > 0 )
+ fade = clamp( moon_dir.z*moon_dir.z*4.0, 0.0, 1.0 );
- vec4 light_color = max(sunlight_color, moonlight_color);
- float mix = 1.0 - dot(normalize(light_color.rgb), luma_weights);
+ vec4 c = texture2D(diffuseMap, vary_texcoord0.xy);
+// c.rgb = srgb_to_linear(c.rgb);
+ c.rgb *= moonlight_color.rgb;
+ c.rgb *= moon_brightness;
- vec3 exp = vec3(1.0 - mix * moon_brightness) * 2.0 - 1.0;
- c.rgb = pow(c.rgb, exp);
+ c.rgb *= fade;
+ c.a *= fade;
- //c.rgb *= moonlight_color.rgb;
+ c.rgb = scaleSoftClip(c.rgb);
frag_data[0] = vec4(c.rgb, c.a);
frag_data[1] = vec4(0.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
index e1bac4f248..c4922afd7d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
@@ -1,9 +1,9 @@
/**
- * @file moonV.glsl
+ * @file class1\deferred\moonV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2007, 2020 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
@@ -32,18 +32,13 @@ ATTRIBUTE vec2 texcoord0;
VARYING vec2 vary_texcoord0;
-void calcAtmospherics(vec3 eye_pos);
-
void main()
{
//transform vertex
- vec3 offset = vec3(0, 0, 50);
- vec4 vert = vec4(position.xyz - offset, 1.0);
+ vec4 vert = vec4(position.xyz, 1.0);
vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vert;
- calcAtmospherics(pos.xyz);
-
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 0d1cc81786..8c402fcb54 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -1,24 +1,24 @@
-/**
- * @file multiPointLightF.glsl
+/**
+ * @file class1/deferred/multiPointLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
@@ -36,119 +36,112 @@ out vec4 frag_color;
uniform sampler2DRect depthMap;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
-uniform samplerCube environmentMap;
-uniform sampler2D noiseMap;
-uniform sampler2D lightFunc;
+uniform samplerCube environmentMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
-
-uniform vec3 env_mat[3];
+uniform vec3 env_mat[3];
uniform float sun_wash;
+uniform int light_count;
+uniform vec4 light[LIGHT_COUNT];
+uniform vec4 light_col[LIGHT_COUNT];
-uniform int light_count;
-
-uniform vec4 light[LIGHT_COUNT];
-uniform vec4 light_col[LIGHT_COUNT];
-
-VARYING vec4 vary_fragcoord;
-uniform vec2 screen_res;
-
+uniform vec2 screen_res;
uniform float far_z;
+uniform mat4 inv_proj;
-uniform mat4 inv_proj;
+VARYING vec4 vary_fragcoord;
vec4 getPosition(vec2 pos_screen);
vec3 getNorm(vec2 pos_screen);
vec3 srgb_to_linear(vec3 c);
-void main()
+void main()
{
- vec3 out_col = vec3(0,0,0);
-
#if defined(LOCAL_LIGHT_KILL)
- discard;
-#else
- vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
- vec3 pos = getPosition(frag.xy).xyz;
- if (pos.z < far_z)
- {
- discard;
- }
-
- vec3 norm = getNorm(frag.xy);
-
- vec4 spec = texture2DRect(specularRect, frag.xy);
- vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
- diff.rgb = srgb_to_linear(diff.rgb);
-
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
- vec3 npos = normalize(-pos);
-
- // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
- for (int i = 0; i < LIGHT_COUNT; ++i)
- {
- vec3 lv = light[i].xyz-pos;
- float dist = length(lv);
- dist /= light[i].w;
- if (dist <= 1.0)
- {
- float da = dot(norm, lv);
- if (da > 0.0)
- {
- lv = normalize(lv);
- da = dot(norm, lv);
-
- float fa = light_col[i].a+1.0;
- float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
- dist_atten *= dist_atten;
-
- // Tweak falloff slightly to match pre-EEP attenuation
- // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit
- dist_atten *= 2.0;
-
- dist_atten *= noise;
-
- float lit = da * dist_atten;
-
- vec3 col = light_col[i].rgb*lit*diff;
-
- //vec3 col = vec3(dist2, light_col[i].a, lit);
-
- if (spec.a > 0.0)
- {
- lit = min(da*6.0, 1.0) * dist_atten;
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(lv+npos);
- float nh = dot(norm, h);
- float nv = dot(norm, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- col += lit*scol*light_col[i].rgb*spec.rgb;
- //col += spec.rgb;
- }
- }
-
- out_col += col;
- }
- }
- }
+ discard; // Bail immediately
#endif
-
- frag_color.rgb = out_col;
- frag_color.a = 0.0;
+
+ vec3 out_col = vec3(0, 0, 0);
+ vec2 frag = (vary_fragcoord.xy * 0.5 + 0.5) * screen_res;
+ vec3 pos = getPosition(frag.xy).xyz;
+ if (pos.z < far_z)
+ {
+ discard;
+ }
+
+ vec3 norm = getNorm(frag.xy);
+
+ vec4 spec = texture2DRect(specularRect, frag.xy);
+ spec.rgb = srgb_to_linear(spec.rgb);
+ vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
+ diff.rgb = srgb_to_linear(diff.rgb);
+
+ float noise = texture2D(noiseMap, frag.xy / 128.0).b;
+ vec3 npos = normalize(-pos);
+
+ // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
+ for (int i = 0; i < LIGHT_COUNT; ++i)
+ {
+ vec3 lv = light[i].xyz - pos;
+ float dist = length(lv);
+ dist /= light[i].w;
+ if (dist <= 1.0)
+ {
+ float da = dot(norm, lv);
+ if (da > 0.0)
+ {
+ lv = normalize(lv);
+ da = dot(norm, lv);
+
+ float fa = light_col[i].a + 1.0;
+ float dist_atten = clamp(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+
+ // Tweak falloff slightly to match pre-EEP attenuation
+ // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit
+ dist_atten *= 2.0;
+
+ dist_atten *= noise;
+
+ float lit = da * dist_atten;
+
+ vec3 col = light_col[i].rgb * lit * diff;
+
+ if (spec.a > 0.0)
+ {
+ lit = min(da * 6.0, 1.0) * dist_atten;
+ vec3 h = normalize(lv + npos);
+ float nh = dot(norm, h);
+ float nv = dot(norm, npos);
+ float vh = dot(npos, h);
+ float sa = nh;
+ float fres = pow(1 - dot(h, npos), 5) * 0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres * texture2D(lightFunc, vec2(nh, spec.a)).r * gt / (nh * da);
+ col += lit * scol * light_col[i].rgb * spec.rgb;
+ }
+ }
+
+ out_col += col;
+ }
+ }
+ }
+
+ frag_color.rgb = out_col;
+ frag_color.a = 0.0;
#ifdef IS_AMD_CARD
- // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts.
- vec4 dummy1 = light[0];
- vec4 dummy2 = light_col[0];
- vec4 dummy3 = light[LIGHT_COUNT-1];
- vec4 dummy4 = light_col[LIGHT_COUNT-1];
+ // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage
+ // awawy which leads to unfun crashes and artifacts.
+ vec4 dummy1 = light[0];
+ vec4 dummy2 = light_col[0];
+ vec4 dummy3 = light[LIGHT_COUNT - 1];
+ vec4 dummy4 = light_col[LIGHT_COUNT - 1];
#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index ead754ec76..28a1faf24f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file WLSkyV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
@@ -37,13 +37,13 @@ VARYING vec4 vary_HazeColor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -52,7 +52,7 @@ uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec4 glow;
uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
@@ -63,103 +63,91 @@ uniform vec4 cloud_color;
// indra\newview\lllegacyatmospherics.cpp
void main()
{
-
- // World / view / projection
+ // World / view / projection
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
- gl_Position = pos;
-
- // Get relative position
- vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
- // Set altitude
- if (P.y > 0.)
- {
- P *= (max_y / P.y);
- }
- else
- {
- P *= (-32000. / P.y);
- }
-
- // Can normalize then
- vec3 Pn = normalize(P);
-
- float Plen = length(P);
-
- // Initialize temp variables
- vec4 temp1 = vec4(0.);
- vec4 temp2 = vec4(0.);
- vec4 blue_weight;
- vec4 haze_weight;
- vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 light_atten;
-
- float dens_mul = density_multiplier;
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
- // Calculate relative weights
- temp1 = abs(blue_density) + vec4(abs(haze_density));
- blue_weight = blue_density / temp1;
- haze_weight = haze_density / temp1;
-
- // Compute sunlight from P & lightnorm (for long rays like sky)
- temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
-
- // Distance
- temp2.z = Plen * dens_mul;
-
- // Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
- // compiler gets confused.
- temp1 = exp(-temp1 * temp2.z);
+ gl_Position = pos;
+
+ // Get relative position
+ vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+ // Adj position vector to clamp altitude
+ if (rel_pos.y > 0)
+ {
+ rel_pos *= (max_y / rel_pos.y);
+ }
+ if (rel_pos.y < 0)
+ {
+ rel_pos *= (-32000. / rel_pos.y);
+ }
+
+ // Can normalize then
+ vec3 rel_pos_norm = normalize(rel_pos);
- // Compute haze glow
- temp2.x = dot(Pn, lightnorm.xyz);
- temp2.x = 1. - temp2.x;
- // temp2.x is 0 at the sun and increases away from sun
- temp2.x = max(temp2.x, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- temp2.x *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- temp2.x = pow(temp2.x, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+ float rel_pos_len = length(rel_pos);
- // Add "minimum anti-solar illumination"
- temp2.x += .25;
+ // Initialize temp variables
+ vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
+ vec4 light_atten;
- vec4 color = ( blue_horizon * blue_weight * (sunlight + ambient_color)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
- );
+ // Sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+ // Calculate relative weights
+ vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec4 blue_weight = blue_density / combined_haze;
+ vec4 haze_weight = haze_density / combined_haze;
+
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Distance
+ float density_dist = rel_pos_len * density_multiplier;
+
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist);
+
+ // Compute haze glow
+ float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ // Add "minimum anti-solar illumination"
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+ vec4 color =
+ (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Final atmosphere additive
- color *= (1. - temp1);
+ color *= (1. - combined_haze);
- // Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
- tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+ // Increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient_color;
+ tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
- // Dim sunlight by cloud shadow percentage
- sunlight *= max(0.0, (1. - cloud_shadow));
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= max(0.0, (1. - cloud_shadow));
- // Haze color below cloud
- vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
- );
+ // Haze color below cloud
+ vec4 additiveColorBelowCloud =
+ (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
- // Attenuate cloud color by atmosphere
- temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
+ // Attenuate cloud color by atmosphere
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
- // At horizon, blend high altitude sky color towards the darker color below the clouds
- color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
+ // At horizon, blend high altitude sky color towards the darker color below the clouds
+ color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
// Haze color above cloud
- vary_HazeColor = color;
+ vary_HazeColor = color;
}
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index a5804220bc..f80f1a985a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -124,41 +124,15 @@ void main()
if (spec.a > 0.0) // specular reflection
{
+ float sa = dot(refnormpersp, light_dir.xyz);
+ vec3 dumbshiny = sunlit * (texture2D(lightFunc, vec2(sa, spec.a)).r);
-#if 1 //EEP
- vec3 npos = -normalize(pos.xyz);
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(light_dir.xyz+npos);
- float nh = dot(norm.xyz, h);
- float nv = dot(norm.xyz, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scontrib = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- vec3 sp = sun_contrib*scontrib / 6.0;
- sp = clamp(sp, vec3(0), vec3(1));
- bloom += dot(sp, sp) / 4.0;
- color += sp * spec.rgb;
- }
-#else //PRODUCTION
- float sa = dot(refnormpersp, light_dir.xyz);
- vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-
// add the two types of shiny together
vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib) / 6;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
color.rgb += spec_contrib;
-#endif
-
}
-
+
color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
if (envIntensity > 0.0)
diff --git a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
index 50e781fa78..6cd2445522 100644
--- a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
@@ -23,6 +23,9 @@
* $/LicenseInfo$
*/
+// Lambert Azimuthal Equal-Area projection
+// See: https://aras-p.info/texts/CompactNormalStorage.html
+// Also see: A_bit_more_deferred_-_CryEngine3.ppt
vec2 encode_normal(vec3 n)
{
float f = sqrt(8 * n.z + 8);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
index f665394b46..0bb48061e0 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
@@ -31,6 +31,9 @@ out vec4 frag_color;
uniform float minimum_alpha;
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO;
+uniform int no_atmo;
+
vec3 atmosLighting(vec3 light);
vec3 scaleSoftClip(vec3 light);
@@ -41,16 +44,19 @@ void default_lighting()
{
vec4 color = diffuseLookup(vary_texcoord0.xy);
- color *= vertex_color;
-
if (color.a < minimum_alpha)
{
discard;
}
+
+ color *= vertex_color;
- color.rgb = atmosLighting(color.rgb);
-
- color.rgb = scaleSoftClip(color.rgb);
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ color.rgb = atmosLighting(color.rgb);
+ color.rgb = scaleSoftClip(color.rgb);
+ }
frag_color = color;
}
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
index 46390e4a0e..1855cfceeb 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
@@ -30,7 +30,10 @@ out vec4 frag_color;
#endif
uniform float minimum_alpha;
-uniform float texture_gamma;
+uniform float texture_gamma; // either 1.0 or 2.2; see: "::TEXTURE_GAMMA"
+
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
vec3 fullbrightAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
@@ -50,9 +53,17 @@ void fullbright_lighting()
color.rgb *= vertex_color.rgb;
color.rgb = pow(color.rgb, vec3(texture_gamma));
- color.rgb = fullbrightAtmosTransport(color.rgb);
-
- color.rgb = fullbrightScaleSoftClip(color.rgb);
+
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ color.rgb = fullbrightAtmosTransport(color.rgb);
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+ }
+
+ //*TODO: Are we missing an inverse pow() here?
+ // class1\lighting\lightFullbrightF.glsl has:
+ // color.rgb = pow(color.rgb, vec3(1.0/texture_gamma));
frag_color = color;
}
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
index b967709c57..5fcdf3107c 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
@@ -34,6 +34,9 @@ VARYING vec2 vary_texcoord0;
uniform float texture_gamma;
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO;
+uniform int no_atmo;
+
vec3 fullbrightAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
@@ -43,9 +46,12 @@ void fullbright_lighting()
color.rgb = pow(color.rgb, vec3(texture_gamma));
- color.rgb = fullbrightAtmosTransport(color.rgb);
-
- color.rgb = fullbrightScaleSoftClip(color.rgb);
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ color.rgb = fullbrightAtmosTransport(color.rgb);
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+ }
color.rgb = pow(color.rgb, vec3(1.0/texture_gamma));
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
index 567811cd75..6f7e777d23 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
@@ -35,20 +35,37 @@ VARYING vec3 vary_texcoord1;
uniform samplerCube environmentMap;
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
vec3 fullbrightShinyAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
+// See:
+// class1\deferred\fullbrightShinyF.glsl
+// class1\lighting\lightFullbrightShinyF.glsl
void fullbright_shiny_lighting()
{
vec4 color = diffuseLookup(vary_texcoord0.xy);
color.rgb *= vertex_color.rgb;
-
- vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
- color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
- color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+ color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
- color.rgb = fullbrightScaleSoftClip(color.rgb);
+ color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+ }
+/*
+ // NOTE: HUD objects will be full bright. Uncomment if you want "some" environment lighting effecting these HUD objects.
+ else
+ {
+ vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+ color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
+ }
+*/
color.a = 1.0;
diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
index 88959266c8..4bb588335a 100644
--- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
@@ -93,6 +93,5 @@ void main()
col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz);
col.rgb += light_diffuse[2].rgb*calcLocalLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z);
col.rgb += light_diffuse[3].rgb*calcLocalLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z);
-
vertex_color = col*color;
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
index a59bd9c0a6..9ef7704b70 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
@@ -1,4 +1,4 @@
-/**
+/**
* @file simpleV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
@@ -28,6 +28,9 @@ uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
ATTRIBUTE vec3 position;
void passTextureIndex();
ATTRIBUTE vec2 texcoord0;
@@ -46,19 +49,23 @@ void main()
{
//transform vertex
vec4 vert = vec4(position.xyz,1.0);
- passTextureIndex();
- vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+
+ passTextureIndex();
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy;
-
-
-
- vec3 norm = normalize(normal_matrix * normal);
- calcAtmospherics(pos.xyz);
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 1)
+ {
+ vertex_color = diffuse_color;
+ }
+ else
+ {
+ vec4 pos = (modelview_matrix * vert);
+ vec3 norm = normalize(normal_matrix * normal);
- vec4 color = calcLighting(pos.xyz, norm, diffuse_color);
- vertex_color = color;
+ calcAtmospherics(pos.xyz);
-
+ vertex_color = calcLighting(pos.xyz, norm, diffuse_color);
+ }
}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
index dcb02bd1c1..ea2690ba09 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
@@ -1,154 +1,134 @@
-/**
+/**
* @file class1\windlight\atmosphericsFuncs.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, 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$
*/
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
uniform float cloud_shadow;
uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec4 glow;
uniform float scene_light_strength;
-uniform mat3 ssao_effect_mat;
-uniform int no_atmo;
+uniform mat3 ssao_effect_mat;
+uniform int no_atmo;
uniform float sun_moon_glow_factor;
-float getAmbientClamp()
+float getAmbientClamp() { return 1.0f; }
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive,
+ out vec3 atten, bool use_ao)
{
- return 1.0f;
-}
+ vec3 rel_pos = inPositionEye;
+ //(TERRAIN) limit altitude
+ if (abs(rel_pos.y) > max_y) rel_pos *= (max_y / rel_pos.y);
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao) {
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
+ vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec3 P = inPositionEye;
-
- //(TERRAIN) limit altitude
- if (P.y > max_y) P *= (max_y / P.y);
- if (P.y < -max_y) P *= (-max_y / P.y);
+ // sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+ // I had thought blue_density and haze_density should have equal weighting,
+ // but attenuation due to haze_density tends to seem too strong
- vec3 tmpLightnorm = lightnorm.xyz;
+ vec4 combined_haze = blue_density + vec4(haze_density);
+ vec4 blue_weight = blue_density / combined_haze;
+ vec4 haze_weight = vec4(haze_density) / combined_haze;
- vec3 Pn = normalize(P);
- float Plen = length(P);
+ //(TERRAIN) compute sunlight from lightnorm y component. Factor is roughly cosecant(sun elevation) (for short rays like terrain)
+ float above_horizon_factor = 1.0 / max(1e-6, lightnorm.y);
+ sunlight *= exp(-light_atten * above_horizon_factor); // for sun [horizon..overhead] this maps to an exp curve [0..1]
+
+ // main atmospheric scattering line integral
+ float density_dist = rel_pos_len * density_multiplier;
- vec4 temp1 = vec4(0);
- vec3 temp2 = vec3(0);
- vec4 blue_weight;
- vec4 haze_weight;
- vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 light_atten;
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist*distance_multiplier in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist * distance_multiplier);
- float dens_mul = density_multiplier;
- float dist_mul = distance_multiplier;
+ // final atmosphere attenuation factor
+ atten = combined_haze.rgb;
- //sunlight attenuation effect (hue and brightness) due to atmosphere
- //this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
- //I had thought blue_density and haze_density should have equal weighting,
- //but attenuation due to haze_density tends to seem too strong
+ // compute haze glow
+ float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
- temp1 = blue_density + vec4(haze_density);
- blue_weight = blue_density / temp1;
- haze_weight = vec4(haze_density) / temp1;
+ // dampen sun additive contrib when not facing it...
+ // SL-13539: This "if" clause causes an "additive" white artifact at roughly 77 degreees.
+ // if (length(light_dir) > 0.01)
+ haze_glow *= max(0.0f, dot(light_dir, rel_pos_norm));
- //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
- temp2.y = max(0.0, tmpLightnorm.y);
- if (abs(temp2.y) > 0.000001f)
- {
- temp2.y = 1. / abs(temp2.y);
- }
- temp2.y = max(0.0000001f, temp2.y);
- sunlight *= exp(-light_atten * temp2.y);
+ haze_glow = 1. - haze_glow;
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
- // main atmospheric scattering line integral
- temp2.z = Plen * dens_mul;
+ // add "minimum anti-solar illumination"
+ haze_glow += .25;
- // Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z*dist_mul in a variable because the ati
- // compiler gets confused.
- temp1 = exp(-temp1 * temp2.z * dist_mul);
+ haze_glow *= sun_moon_glow_factor;
- //final atmosphere attenuation factor
- atten = temp1.rgb;
-
- //compute haze glow
- //(can use temp2.x as temp because we haven't used it yet)
- temp2.x = dot(Pn, tmpLightnorm.xyz);
+ vec4 amb_color = ambient_color;
- // dampen sun additive contrib when not facing it...
- if (length(light_dir) > 0.01)
- {
- temp2.x *= max(0.0f, dot(light_dir, Pn));
- }
- temp2.x = 1. - temp2.x;
- //temp2.x is 0 at the sun and increases away from sun
- temp2.x = max(temp2.x, .001); //was glow.y
- //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- temp2.x *= glow.x;
- //higher glow.x gives dimmer glow (because next step is 1 / "angle")
- temp2.x = pow(temp2.x, glow.z);
- //glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- //add "minimum anti-solar illumination"
- temp2.x += .25;
-
- temp2.x *= sun_moon_glow_factor;
-
- vec4 amb_color = ambient_color;
-
- //increase ambient when there are more clouds
+ // increase ambient when there are more clouds
vec4 tmpAmbient = amb_color + (vec4(1.) - amb_color) * cloud_shadow * 0.5;
-
+
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
* // The following line of code performs the equivalent of:
* float ambAlpha = tmpAmbient.a;
* float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
* vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
- * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+ * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat,
+ * ambAlpha);
*/
if (use_ao)
{
tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
}
- //haze color
- additive =
- vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
- + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
- + tmpAmbient));
+ // Similar/Shared Algorithms:
+ // indra\llinventory\llsettingssky.cpp -- LLSettingsSky::calculateLightSettings()
+ // indra\newview\app_settings\shaders\class1\windlight\atmosphericsFuncs.glsl -- calcAtmosphericVars()
+ // haze color
+ vec3 cs = sunlight.rgb * (1. - cloud_shadow);
+ additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb);
- //brightness of surface both sunlight and ambient
+ // brightness of surface both sunlight and ambient
sunlit = sunlight.rgb * 0.5;
amblit = tmpAmbient.rgb * .25;
- additive *= vec3(1.0 - temp1);
+ additive *= vec3(1.0 - combined_haze);
}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
index 24f3992e32..2425a2ad04 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
@@ -3,7 +3,7 @@
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2005, 2020 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
@@ -36,28 +36,30 @@ out vec4 frag_color;
uniform vec4 color;
uniform vec4 sunlight_color;
uniform vec4 moonlight_color;
-uniform vec3 lumWeights;
+uniform vec3 moon_dir;
uniform float moon_brightness;
-uniform float minLuminance;
uniform sampler2D diffuseMap;
-uniform sampler2D altDiffuseMap;
-uniform float blend_factor; // interp factor between moon A/B
+
VARYING vec2 vary_texcoord0;
+vec3 scaleSoftClip(vec3 light);
+
void main()
{
- vec4 moonA = texture2D(diffuseMap, vary_texcoord0.xy);
- vec4 moonB = texture2D(altDiffuseMap, vary_texcoord0.xy);
- vec4 c = mix(moonA, moonB, blend_factor);
+ // Restore Pre-EEP alpha fade moon near horizon
+ float fade = 1.0;
+ if( moon_dir.z > 0 )
+ fade = clamp( moon_dir.z*moon_dir.z*4.0, 0.0, 1.0 );
+
+ vec4 c = texture2D(diffuseMap, vary_texcoord0.xy);
+// c.rgb = pow(c.rgb, vec3(0.7f)); // can't use "srgb_to_linear(color.rgb)" as that is a deferred only function
+ c.rgb *= moonlight_color.rgb;
+ c.rgb *= moon_brightness;
- // mix factor which blends when sunlight is brighter
- // and shows true moon color at night
- vec3 luma_weights = vec3(0.3, 0.5, 0.3);
- float mix = 1.0f - dot(normalize(sunlight_color.rgb), luma_weights);
+ c.rgb *= fade;
+ c.a *= fade;
- vec3 exp = vec3(1.0 - mix * moon_brightness) * 2.0 - 1.0;
- c.rgb = pow(c.rgb, exp);
- //c.rgb *= moonlight_color.rgb;
+ c.rgb = scaleSoftClip(c.rgb);
frag_color = vec4(c.rgb, c.a);
}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl b/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
index 8cd4b2ef47..2fceb5f743 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
@@ -3,7 +3,7 @@
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2007, 2020 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
@@ -30,20 +30,15 @@ uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
-void calcAtmospherics(vec3 inPositionEye);
-
VARYING vec2 vary_texcoord0;
void main()
{
//transform vertex
- vec3 offset = vec3(0, 0, 50);
- vec4 vert = vec4(position.xyz - offset, 1.0);
+ vec4 vert = vec4(position.xyz, 1.0);
vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vert;
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
- calcAtmospherics(pos.xyz);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
index 1dce85a83b..1485c515a4 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file class2/deferred/skyF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
@@ -32,13 +32,13 @@ uniform mat4 modelview_projection_matrix;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -47,7 +47,7 @@ uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec4 glow;
uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
@@ -73,16 +73,16 @@ uniform float ice_level;
vec3 rainbow(float d)
{
- d = clamp(d, -1.0, 0.0);
- float rad = (droplet_radius - 5.0f) / 1024.0f;
- return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
+ d = clamp(d, -1.0, 0.0);
+ float rad = (droplet_radius - 5.0f) / 1024.0f;
+ return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
}
vec3 halo22(float d)
{
- d = clamp(d, 0.1, 1.0);
- float v = sqrt(clamp(1 - (d * d), 0, 1));
- return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
+ d = clamp(d, 0.1, 1.0);
+ float v = sqrt(clamp(1 - (d * d), 0, 1));
+ return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
}
/// Soft clips the light with a gamma correction
@@ -90,115 +90,96 @@ vec3 scaleSoftClip(vec3 light);
void main()
{
-
// World / view / projection
- // Get relative position
- vec3 P = pos.xyz - camPosLocal.xyz + vec3(0,50,0);
+ // Get relative position (offset why?)
+ vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
- // Set altitude
- if (P.y > 0.)
+ // Adj position vector to clamp altitude
+ if (rel_pos.y > 0.)
{
- P *= (max_y / P.y);
+ rel_pos *= (max_y / rel_pos.y);
}
- else
+ if (rel_pos.y < 0.)
{
- P *= (-32000. / P.y);
+ rel_pos *= (-32000. / rel_pos.y);
}
- // Can normalize then
- vec3 Pn = normalize(P);
- float Plen = length(P);
+ // Normalized
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
// Initialize temp variables
- vec4 temp1 = vec4(0.);
- vec4 temp2 = vec4(0.);
- vec4 blue_weight;
- vec4 haze_weight;
vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 light_atten;
-
- float dens_mul = density_multiplier;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
+ vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- temp1 = abs(blue_density) + vec4(abs(haze_density));
- blue_weight = blue_density / temp1;
- haze_weight = haze_density / temp1;
+ vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec4 blue_weight = blue_density / combined_haze;
+ vec4 haze_weight = haze_density / combined_haze;
- // Compute sunlight from P & lightnorm (for long rays like sky)
- temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
// Distance
- temp2.z = Plen * dens_mul;
+ float density_dist = rel_pos_len * density_multiplier;
- // Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
// compiler gets confused.
- temp1 = exp(-temp1 * temp2.z);
+ combined_haze = exp(-combined_haze * density_dist);
// Compute haze glow
- temp2.x = dot(Pn, lightnorm.xyz);
- temp2.x = 1. - temp2.x;
- // temp2.x is 0 at the sun and increases away from sun
- temp2.x = max(temp2.x, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- temp2.x *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- temp2.x = pow(temp2.x, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+ float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
+ haze_glow = 1. - haze_glow;
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
// Add "minimum anti-solar illumination"
- temp2.x += .25;
-
- temp2.x *= sun_moon_glow_factor;
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
// Haze color above cloud
- vec4 color = ( blue_horizon * blue_weight * (sunlight + ambient_color)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
- );
+ vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color)
+ + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color);
// Final atmosphere additive
- color *= (1. - temp1);
+ color *= (1. - combined_haze);
// Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
- tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+ // TODO 9/20: DJH what does this do? max(0,(1-ambient)) will change the color
+ vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= max(0.0, (1. - cloud_shadow));
// Haze color below cloud
- vec4 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
- );
+ vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient)
+ + haze_horizon * haze_weight * (sunlight * haze_glow + ambient);
-
-
// Attenuate cloud color by atmosphere
- temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
// At horizon, blend high altitude sky color towards the darker color below the clouds
- color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
-
- float optic_d = dot(Pn, lightnorm.xyz);
-
- vec3 halo_22 = halo22(optic_d);
+ color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
+ float optic_d = dot(rel_pos_norm, lightnorm.xyz);
+ vec3 halo_22 = halo22(optic_d);
color.rgb += rainbow(optic_d);
-
color.rgb += halo_22;
-
color.rgb *= 2.;
color.rgb = scaleSoftClip(color.rgb);
- /// Gamma correct for WL (soft clip effect).
+ // Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 1.0);
- frag_data[1] = vec4(0.0,0.0,0.0,0.0);
- frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog
+ frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0);
+ frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0); // 1.0 in norm.w masks off fog
}
-
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index b0dff0c628..f4db53e0b7 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file class2/deferred/softenLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
@@ -39,7 +39,7 @@ uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
uniform sampler2DRect depthMap;
-uniform samplerCube environmentMap;
+uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
uniform float blur_size;
@@ -50,7 +50,7 @@ uniform mat3 env_mat;
uniform vec3 sun_dir;
uniform vec3 moon_dir;
-uniform int sun_up_factor;
+uniform int sun_up_factor;
VARYING vec2 vary_fragcoord;
uniform mat4 inv_proj;
@@ -61,10 +61,10 @@ vec4 getPositionWithDepth(vec2 pos_screen, float depth);
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
float getAmbientClamp();
-vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
-vec3 scaleSoftClipFrag(vec3 l);
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightScaleSoftClip(vec3 light);
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFrag(vec3 l);
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c);
@@ -73,128 +73,85 @@ vec3 srgb_to_linear(vec3 c);
vec4 applyWaterFogView(vec3 pos, vec4 color);
#endif
-void main()
+void main()
{
- vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).r;
- vec4 pos = getPositionWithDepth(tc, depth);
- vec4 norm = texture2DRect(normalMap, tc);
+ vec2 tc = vary_fragcoord.xy;
+ float depth = texture2DRect(depthMap, tc.xy).r;
+ vec4 pos = getPositionWithDepth(tc, depth);
+ vec4 norm = texture2DRect(normalMap, tc);
float envIntensity = norm.z;
- norm.xyz = getNorm(tc);
-
- vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
- float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
- float light_gamma = 1.0/1.3;
- da = pow(da, light_gamma);
-
+ norm.xyz = getNorm(tc);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+ float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
+ float light_gamma = 1.0 / 1.3;
+ da = pow(da, light_gamma);
+
vec4 diffuse = texture2DRect(diffuseRect, tc);
-
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
- scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
+ scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
- float scol = max(scol_ambocc.r, diffuse.a);
+ vec3 color = vec3(0);
+ float bloom = 0.0;
- float ambocc = scol_ambocc.g;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+ calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
- vec3 color = vec3(0);
- float bloom = 0.0;
+ color.rgb = amblit;
+
+ float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+ ambient *= 0.5;
+ ambient *= ambient;
+ ambient = (1.0 - ambient);
+ color.rgb *= ambient;
+
+ vec3 sun_contrib = min(da, scol) * sunlit;
+ color.rgb += sun_contrib;
+ color.rgb *= diffuse.rgb;
+
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+ if (spec.a > 0.0) // specular reflection
{
- vec3 sunlit;
- vec3 amblit;
- vec3 additive;
- vec3 atten;
-
- calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
-
- color.rgb = amblit;
-
- float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
- ambient *= 0.5;
- ambient *= ambient;
- ambient = (1.0 - ambient);
-
- color.rgb *= ambient;
-
- vec3 sun_contrib = min(da, scol) * sunlit;
-
- color.rgb += sun_contrib;
-
- color.rgb *= diffuse.rgb;
-
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
- if (spec.a > 0.0) // specular reflection
- {
-
-#if 1 //EEP
- vec3 npos = -normalize(pos.xyz);
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(light_dir.xyz+npos);
- float nh = dot(norm.xyz, h);
- float nv = dot(norm.xyz, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scontrib = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- vec3 sp = sun_contrib*scontrib / 6.0;
- sp = clamp(sp, vec3(0), vec3(1));
- bloom += dot(sp, sp) / 4.0;
- color += sp * spec.rgb;
- }
-#else //PRODUCTION
- float sa = dot(refnormpersp, light_dir.xyz);
- vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-
- // add the two types of shiny together
- vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib) / 6;
- color.rgb += spec_contrib;
-#endif
+ float sa = dot(refnormpersp, light_dir.xyz);
+ vec3 dumbshiny = sunlit * scol * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
+ color.rgb += spec_contrib;
+ }
+
+ color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
- }
-
- color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
-
- if (envIntensity > 0.0)
- { //add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
- vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
- color = mix(color.rgb, reflected_color, envIntensity);
- }
-
- if (norm.w < 0.5)
- {
- color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
- color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
- }
-
- #ifdef WATER_FOG
- vec4 fogged = applyWaterFogView(pos.xyz,vec4(color, bloom));
- color = fogged.rgb;
- bloom = fogged.a;
- #endif
+ if (envIntensity > 0.0)
+ { // add environmentmap
+ vec3 env_vec = env_mat * refnormpersp;
+ vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
+ color = mix(color.rgb, reflected_color, envIntensity);
+ }
+ if (norm.w < 0.5)
+ {
+ color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
+ color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
}
-// linear debuggables
-//color.rgb = vec3(final_da);
-//color.rgb = vec3(ambient);
-//color.rgb = vec3(scol);
-//color.rgb = diffuse_srgb.rgb;
+#ifdef WATER_FOG
+ vec4 fogged = applyWaterFogView(pos.xyz, vec4(color, bloom));
+ color = fogged.rgb;
+ bloom = fogged.a;
+#endif
// convert to linear as fullscreen lights need to sum in linear colorspace
// and will be gamma (re)corrected downstream...
-
frag_color.rgb = srgb_to_linear(color.rgb);
- frag_color.a = bloom;
+ frag_color.a = bloom;
}
-
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index 2c1475d547..1f881eb44b 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -1,24 +1,24 @@
-/**
+/**
* @file class2\wl\cloudsV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
@@ -33,25 +33,26 @@ ATTRIBUTE vec2 texcoord0;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec4 vary_CloudColorSun;
+VARYING vec4 vary_CloudColorAmbient;
VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
+
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
VARYING float altitude_blend_factor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -59,141 +60,133 @@ uniform float cloud_shadow;
uniform float density_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec4 glow;
uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
uniform float cloud_scale;
+// NOTE: Keep these in sync!
+// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
+// indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+// indra\newview\app-settings\shaders\class2\windlight\cloudsV.glsl
+// indra\newview\lllegacyatmospherics.cpp
+// indra\newview\llsettingsvo.cpp
void main()
{
+ // World / view / projection
+ gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+ // Texture coords
+ // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
+ vary_texcoord0 = vec2(-texcoord0.x, texcoord0.y); // See: LLSettingsVOSky::applySpecial
- // World / view / projection
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vary_texcoord0.xy -= 0.5;
+ vary_texcoord0.xy /= cloud_scale;
+ vary_texcoord0.xy += 0.5;
- vary_texcoord0 = texcoord0;
+ vary_texcoord1 = vary_texcoord0;
+ vary_texcoord1.x += lightnorm.x * 0.0125;
+ vary_texcoord1.y += lightnorm.z * 0.0125;
- // Get relative position
- vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
+ vary_texcoord2 = vary_texcoord0 * 16.;
+ vary_texcoord3 = vary_texcoord1 * 16.;
+
+ // Get relative position
+ vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
// fade clouds beyond a certain point so the bottom of the sky dome doesn't look silly at high altitude
- altitude_blend_factor = clamp((P.y + 512.0) / max_y, 0.0, 1.0);
-
- // Set altitude
- if (P.y > 0.)
- {
- P *= (max_y / P.y);
- }
- else
- {
- P *= (-32000. / P.y);
- }
-
- // Can normalize then
- vec3 Pn = normalize(P);
- float Plen = length(P);
-
- // Initialize temp variables
- vec4 temp1 = vec4(0.);
- vec4 temp2 = vec4(0.);
- vec4 blue_weight;
- vec4 haze_weight;
- //vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 sunlight = sunlight_color;
- vec4 light_atten;
-
- float dens_mul = density_multiplier;
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
- // Calculate relative weights
- temp1 = abs(blue_density) + vec4(abs(haze_density));
- blue_weight = blue_density / temp1;
- haze_weight = haze_density / temp1;
-
- // Compute sunlight from P & lightnorm (for long rays like sky)
- temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
-
- // Distance
- temp2.z = Plen * dens_mul;
-
- // Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
- // compiler gets confused.
- temp1 = exp(-temp1 * temp2.z);
-
-
- // Compute haze glow
- temp2.x = dot(Pn, lightnorm.xyz);
- temp2.x = 1. - temp2.x;
- // temp2.x is 0 at the sun and increases away from sun
- temp2.x = max(temp2.x, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- temp2.x *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- temp2.x = pow(temp2.x, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- temp2.x *= sun_moon_glow_factor;
-
- // Add "minimum anti-solar illumination"
- temp2.x += .25;
-
- // Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
-
- // Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow);
-
- // Haze color below cloud
- vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
- );
-
- // CLOUDS
- temp2.y = max(0., lightnorm.y * 2.);
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
-
- // Cloud color out
- vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
- vary_CloudColorAmbient = tmpAmbient * cloud_color;
-
- // Attenuate cloud color by atmosphere
- temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
- vary_CloudColorSun *= temp1;
- vary_CloudColorAmbient *= temp1;
- vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
-
- // Make a nice cloud density based on the cloud_shadow value that was passed in.
- vary_CloudDensity = 2. * (cloud_shadow - 0.25);
-
-
- // Texture coords
- vary_texcoord0 = texcoord0;
- vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= cloud_scale;
- vary_texcoord0.xy += 0.5;
-
- vary_texcoord1 = vary_texcoord0;
- vary_texcoord1.x += lightnorm.x * 0.0125;
- vary_texcoord1.y += lightnorm.z * 0.0125;
-
- vary_texcoord2 = vary_texcoord0 * 16.;
- vary_texcoord3 = vary_texcoord1 * 16.;
-
- // Combine these to minimize register use
- vary_CloudColorAmbient += oHazeColorBelowCloud;
-
- // needs this to compile on mac
- //vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
-
- // END CLOUDS
+ altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
+
+ // Adj position vector to clamp altitude
+ if (rel_pos.y > 0.)
+ {
+ rel_pos *= (max_y / rel_pos.y);
+ }
+ if (rel_pos.y < 0.)
+ {
+ rel_pos *= (-32000. / rel_pos.y);
+ }
+
+ // Can normalize then
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
+
+ // Initialize temp variables
+ vec4 sunlight = sunlight_color;
+ vec4 light_atten;
+
+ // Sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+
+ // Calculate relative weights
+ vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec4 blue_weight = blue_density / combined_haze;
+ vec4 haze_weight = haze_density / combined_haze;
+
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Distance
+ float density_dist = rel_pos_len * density_multiplier;
+
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist);
+
+ // Compute haze glow
+ float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ haze_glow *= sun_moon_glow_factor;
+
+ // Add "minimum anti-solar illumination"
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+ // Increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient_color;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= (1. - cloud_shadow);
+
+ // Haze color below cloud
+ vec4 additiveColorBelowCloud =
+ (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+
+ // CLOUDS
+ off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Cloud color out
+ vary_CloudColorSun = (sunlight * haze_glow) * cloud_color;
+ vary_CloudColorAmbient = tmpAmbient * cloud_color;
+
+ // Attenuate cloud color by atmosphere
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
+ vary_CloudColorSun *= combined_haze;
+ vary_CloudColorAmbient *= combined_haze;
+ vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+
+ // Make a nice cloud density based on the cloud_shadow value that was passed in.
+ vary_CloudDensity = 2. * (cloud_shadow - 0.25);
+
+ // Combine these to minimize register use
+ vary_CloudColorAmbient += oHazeColorBelowCloud;
+
+ // needs this to compile on mac
+ // vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+
+ // END CLOUDS
}
-
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index 0d141342ce..a0a33b8642 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -1,28 +1,28 @@
-/**
+/**
* @file class2\wl\skyV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2005, 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$
*/
-
+
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
@@ -37,13 +37,13 @@ VARYING vec4 vary_HazeColor;
// Inputs
uniform vec3 camPosLocal;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
uniform float haze_horizon;
uniform float haze_density;
@@ -52,110 +52,98 @@ uniform float density_multiplier;
uniform float distance_multiplier;
uniform float max_y;
-uniform vec4 glow;
+uniform vec4 glow;
uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
void main()
{
-
- // World / view / projection
+ // World / view / projection
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
- gl_Position = pos;
-
- // Get relative position
- vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
- // Set altitude
- if (P.y > 0.)
- {
- P *= (max_y / P.y);
- }
- else
- {
- P *= (-32000. / P.y);
- }
-
- // Can normalize then
- vec3 Pn = normalize(P);
-
- float Plen = length(P);
-
- // Initialize temp variables
- vec4 temp1 = vec4(0.);
- vec4 temp2 = vec4(0.);
- vec4 blue_weight;
- vec4 haze_weight;
- vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec4 light_atten;
-
- float dens_mul = density_multiplier;
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
- // Calculate relative weights
- temp1 = abs(blue_density) + vec4(abs(haze_density));
- blue_weight = blue_density / temp1;
- haze_weight = haze_density / temp1;
-
- // Compute sunlight from P & lightnorm (for long rays like sky)
- temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
- temp2.y = 1. / temp2.y;
- sunlight *= exp( - light_atten * temp2.y);
-
- // Distance
- temp2.z = Plen * dens_mul;
-
- // Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
- // compiler gets confused.
- temp1 = exp(-temp1 * temp2.z);
+ gl_Position = pos;
+
+ // Get relative position
+ vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+ // Adj position vector to clamp altitude
+ if (rel_pos.y > 0.)
+ {
+ rel_pos *= (max_y / rel_pos.y);
+ }
+ if (rel_pos.y < 0.)
+ {
+ rel_pos *= (-32000. / rel_pos.y);
+ }
- // Compute haze glow
- temp2.x = dot(Pn, lightnorm.xyz);
- temp2.x = 1. - temp2.x;
- // temp2.x is 0 at the sun and increases away from sun
- temp2.x = max(temp2.x, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- temp2.x *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- temp2.x = pow(temp2.x, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+ // Can normalize then
+ vec3 rel_pos_norm = normalize(rel_pos);
- // Add "minimum anti-solar illumination"
- temp2.x += .25;
+ float rel_pos_len = length(rel_pos);
- vec4 color = ( blue_horizon * blue_weight * (sunlight + ambient_color)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
- );
+ // Initialize temp variables
+ vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
+ vec4 light_atten;
+ // Sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+
+ // Calculate relative weights
+ vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec4 blue_weight = blue_density / combined_haze;
+ vec4 haze_weight = haze_density / combined_haze;
+
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Distance
+ float density_dist = rel_pos_len * density_multiplier;
+
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist);
+
+ // Compute haze glow
+ float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ // Add "minimum anti-solar illumination"
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+ vec4 color =
+ (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Final atmosphere additive
- color *= (1. - temp1);
+ color *= (1. - combined_haze);
- // Increase ambient when there are more clouds
- vec4 tmpAmbient = ambient_color;
- tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+ // Increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient_color;
+ tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
- // Dim sunlight by cloud shadow percentage
- sunlight *= max(0.0, (1. - cloud_shadow));
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= max(0.0, (1. - cloud_shadow));
- // Haze color below cloud
- vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
- );
+ // Haze color below cloud
+ vec4 additiveColorBelowCloud =
+ (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
- // Attenuate cloud color by atmosphere
- temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
+ // Attenuate cloud color by atmosphere
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
- // At horizon, blend high altitude sky color towards the darker color below the clouds
- color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
+ // At horizon, blend high altitude sky color towards the darker color below the clouds
+ color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
// Haze color above cloud
- vary_HazeColor = color;
+ vary_HazeColor = color;
}
-
diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h
index 55e1d19f05..d133c6437b 100644
--- a/indra/newview/llaccountingcostmanager.h
+++ b/indra/newview/llaccountingcostmanager.h
@@ -30,12 +30,6 @@
#include "llhandle.h"
#include "llaccountingcost.h"
-#include "httpcommon.h"
-#include "llcoros.h"
-#include "lleventcoro.h"
-#include "httprequest.h"
-#include "httpheaders.h"
-#include "httpoptions.h"
//===============================================================================
// An interface class for panels which display the parcel accounting information.
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f3df79fb6b..166c2d67c8 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -867,9 +867,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
if (mRegionp != regionp)
{
- std::string ip = regionp->getHost().getString();
- LL_INFOS("AgentLocation") << "Moving agent into region: " << regionp->getName()
- << " located at " << ip << LL_ENDL;
+ LL_INFOS("AgentLocation") << "Moving agent into region: " << regionp->getName() << LL_ENDL;
if (mRegionp)
{
// We've changed regions, we're now going to change our agent coordinate frame.
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 88cce0b911..eb8be2d601 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -47,20 +47,15 @@ extern const BOOL ANIMATE;
extern const U8 AGENT_STATE_TYPING; // Typing indication
extern const U8 AGENT_STATE_EDITING; // Set when agent has objects selected
-class LLChat;
class LLViewerRegion;
class LLMotion;
-class LLToolset;
class LLMessageSystem;
class LLPermissions;
class LLHost;
class LLFriendObserver;
-class LLPickInfo;
-class LLViewerObject;
class LLAgentDropGroupViewerNode;
class LLAgentAccess;
class LLSLURL;
-class LLPauseRequestHandle;
class LLUIColor;
class LLTeleportRequest;
@@ -91,8 +86,6 @@ struct LLGroupData
class LLAgentListener;
-class LLAgentImpl;
-
//------------------------------------------------------------------------
// LLAgent
//------------------------------------------------------------------------
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 9e65409256..672104dd70 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -354,6 +354,18 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
resetPanDiff();
resetOrbitDiff();
mHUDTargetZoom = 1.f;
+
+ if (LLSelectMgr::getInstance()->mAllowSelectAvatar)
+ {
+ // resetting camera also resets position overrides in debug mode 'AllowSelectAvatar'
+ LLObjectSelectionHandle selected_handle = LLSelectMgr::getInstance()->getSelection();
+ if (selected_handle->getObjectCount() == 1
+ && selected_handle->getFirstObject() != NULL
+ && selected_handle->getFirstObject()->isAvatar())
+ {
+ LLSelectMgr::getInstance()->resetObjectOverrides(selected_handle);
+ }
+ }
}
// Allow camera to be moved somewhere other than behind avatar.
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 2411f0f86d..7f18ea6fe2 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -881,13 +881,6 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback
void LLAgentWearables::removeWearable(const LLWearableType::EType type, bool do_remove_all, U32 index)
{
- if (gAgent.isTeen() &&
- (type == LLWearableType::WT_UNDERSHIRT || type == LLWearableType::WT_UNDERPANTS))
- {
- // Can't take off underclothing in simple UI mode or on PG accounts
- // TODO: enable the removing of a single undershirt/underpants if multiple are worn. - Nyx
- return;
- }
if (getWearableCount(type) == 0)
{
// no wearables to remove
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index ee49125711..005259bcb8 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -44,6 +44,10 @@
const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3");
const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3");
+std::list<AISAPI::ais_query_item_t> AISAPI::sPostponedQuery;
+
+const S32 MAX_SIMULTANEOUS_COROUTINES = 2048;
+
//-------------------------------------------------------------------------
/*static*/
bool AISAPI::isAvailable()
@@ -366,9 +370,51 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t
/*static*/
void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc)
{
+ LLCoprocedureManager &inst = LLCoprocedureManager::instance();
+ S32 pending_in_pool = inst.countPending("AIS");
std::string procFullName = "AIS(" + procName + ")";
- LLCoprocedureManager::instance().enqueueCoprocedure("AIS", procFullName, proc);
+ if (pending_in_pool < MAX_SIMULTANEOUS_COROUTINES)
+ {
+ inst.enqueueCoprocedure("AIS", procFullName, proc);
+ }
+ else
+ {
+ // As I understand it, coroutines have built-in 'pending' pool
+ // but unfortunately it has limited size which inventory often goes over
+ // so this is a workaround to not overfill it.
+ if (sPostponedQuery.empty())
+ {
+ sPostponedQuery.push_back(ais_query_item_t(procFullName, proc));
+ gIdleCallbacks.addFunction(onIdle, NULL);
+ }
+ else
+ {
+ sPostponedQuery.push_back(ais_query_item_t(procFullName, proc));
+ }
+ }
+}
+/*static*/
+void AISAPI::onIdle(void *userdata)
+{
+ if (!sPostponedQuery.empty())
+ {
+ LLCoprocedureManager &inst = LLCoprocedureManager::instance();
+ S32 pending_in_pool = inst.countPending("AIS");
+ while (pending_in_pool < MAX_SIMULTANEOUS_COROUTINES && !sPostponedQuery.empty())
+ {
+ ais_query_item_t &item = sPostponedQuery.front();
+ inst.enqueueCoprocedure("AIS", item.first, item.second);
+ sPostponedQuery.pop_front();
+ pending_in_pool++;
+ }
+ }
+
+ if (sPostponedQuery.empty())
+ {
+ // Nothing to do anymore
+ gIdleCallbacks.deleteFunction(onIdle, NULL);
+ }
}
/*static*/
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index e97059014b..856f3fc180 100644
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -31,7 +31,6 @@
#include <map>
#include <set>
#include <string>
-#include "llhttpretrypolicy.h"
#include "llviewerinventory.h"
#include "llcorehttputil.h"
#include "llcoproceduremanager.h"
@@ -72,6 +71,7 @@ private:
const std::string, LLSD, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t) > invokationFn_t;
static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc);
+ static void onIdle(void *userdata); // launches postponed AIS commands
static std::string getInvCap();
static std::string getLibCap();
@@ -80,6 +80,8 @@ private:
invokationFn_t invoke, std::string url, LLUUID targetId, LLSD body,
completion_t callback, COMMAND_TYPE type);
+ typedef std::pair<std::string, LLCoprocedureManager::CoProcedure_t> ais_query_item_t;
+ static std::list<ais_query_item_t> sPostponedQuery;
};
class AISUpdate
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index afa4414968..134a34137b 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -522,20 +522,20 @@ void LLAppCoreHttp::refreshSettings(bool initial)
LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
const LLCore::HttpHandler::ptr_t &handler, void *appdata)
{
- X509_STORE_CTX *ctx = static_cast<X509_STORE_CTX *>(appdata);
- LLCore::HttpStatus result;
- LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
- LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
- LLSD validation_params = LLSD::emptyMap();
- LLURI uri(url);
+ LLCore::HttpStatus result;
+ try
+ {
+ X509_STORE_CTX *ctx = static_cast<X509_STORE_CTX *>(appdata);
+ LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
+ LLPointer<LLCertificateChain> chain = gSecAPIHandler->getCertificateChain(ctx);
+ LLSD validation_params = LLSD::emptyMap();
+ LLURI uri(url);
- validation_params[CERT_HOSTNAME] = uri.hostName();
+ validation_params[CERT_HOSTNAME] = uri.hostName();
- // *TODO: In the case of an exception while validating the cert, we need a way
- // to pass the offending(?) cert back out. *Rider*
+ // *TODO: In the case of an exception while validating the cert, we need a way
+ // to pass the offending(?) cert back out. *Rider*
- try
- {
// don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects
store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params);
}
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 47fde299c7..a2b7362608 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -294,6 +294,7 @@ struct AttachmentInfo
std::vector<AttachmentInfo> info{
AttachmentInfo(metadata.logFilePathname, "text/plain"),
AttachmentInfo(metadata.userSettingsPathname, "text/xml"),
+ AttachmentInfo(metadata.accountSettingsPathname, "text/xml"),
AttachmentInfo(metadata.staticDebugPathname, "text/xml")
};
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 1a33059188..e5c505501e 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3278,6 +3278,50 @@ void update_base_outfit_after_ordering()
bool copy_folder_links = false;
app_mgr.slamCategoryLinks(app_mgr.getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater);
+ if (base_outfit_id.notNull())
+ {
+ LLIsValidItemLink collector;
+
+ LLInventoryModel::cat_array_t cof_cats;
+ LLInventoryModel::item_array_t cof_item_array;
+ gInventory.collectDescendentsIf(app_mgr.getCOF(), cof_cats, cof_item_array,
+ LLInventoryModel::EXCLUDE_TRASH, collector);
+
+ for (U32 i = 0; i < outfit_item_array.size(); ++i)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item_array.at(i)->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ outfit_item_array.erase(outfit_item_array.begin() + i);
+ break;
+ }
+ }
+
+ if (outfit_item_array.size() != cof_item_array.size())
+ {
+ return;
+ }
+
+ std::sort(cof_item_array.begin(), cof_item_array.end(), sort_by_linked_uuid);
+ std::sort(outfit_item_array.begin(), outfit_item_array.end(), sort_by_linked_uuid);
+
+ for (U32 i = 0; i < cof_item_array.size(); ++i)
+ {
+ LLViewerInventoryItem *cof_it = cof_item_array.at(i);
+ LLViewerInventoryItem *base_it = outfit_item_array.at(i);
+
+ if (cof_it->getActualDescription() != base_it->getActualDescription())
+ {
+ if (cof_it->getLinkedUUID() == base_it->getLinkedUUID())
+ {
+ base_it->setDescription(cof_it->getActualDescription());
+ gInventory.updateItem(base_it);
+ }
+ }
+ }
+ LLAppearanceMgr::getInstance()->updateIsDirty();
+ }
+
}
// Save COF changes - update the contents of the current base outfit
@@ -3582,6 +3626,10 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
}
llcoro::suspend();
+ if (LLApp::isQuitting())
+ {
+ return;
+ }
S32 retryCount(0);
bool bRetry;
do
@@ -3645,6 +3693,11 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
+ if (LLApp::isQuitting())
+ {
+ return;
+ }
+
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -3680,6 +3733,10 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
LL_WARNS("Avatar") << "Bake retry #" << retryCount << " in " << timeout << " seconds." << LL_ENDL;
llcoro::suspendUntilTimeout(timeout);
+ if (LLApp::isQuitting())
+ {
+ return;
+ }
bRetry = true;
continue;
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 75574df00e..515d6ffc14 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -73,6 +73,7 @@
#include "llviewermedia.h"
#include "llviewerparcelaskplay.h"
#include "llviewerparcelmedia.h"
+#include "llviewershadermgr.h"
#include "llviewermediafocus.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
@@ -526,7 +527,8 @@ bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
LLIconCtrl* icon;
- if(gAgent.isInGroup(match_id, TRUE))
+ if( match->getMenuName() == "menu_url_group.xml" // See LLUrlEntryGroup constructor
+ || gAgent.isInGroup(match_id, TRUE)) //This check seems unfiting, urls are either /agent or /group
{
LLGroupIconCtrl::Params icon_params;
icon_params.group_id = match_id;
@@ -604,8 +606,9 @@ static void settings_to_globals()
static void settings_modify()
{
LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred");
+ LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater");
LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
- LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
+ LLPipeline::sRenderDeferred = LLPipeline::sRenderTransparentWater && LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
@@ -688,8 +691,7 @@ LLAppViewer::LLAppViewer()
mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
mFastTimerLogThread(NULL),
mSettingsLocationList(NULL),
- mIsFirstRun(false),
- mMinMicroSecPerFrame(0.f)
+ mIsFirstRun(false)
{
if(NULL != sInstance)
{
@@ -781,7 +783,7 @@ bool LLAppViewer::init()
// initialize the LLSettingsType translation bridge.
LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>();
- LLSettingsType::initClass(trans);
+ LLSettingsType::initParamSingleton(trans);
// initialize SSE options
LLVector4a::initClass();
@@ -1024,13 +1026,27 @@ bool LLAppViewer::init()
{
// can't use an alert here since we're exiting and
// all hell breaks lose.
+ LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedGLRequirements");
OSMessageBox(
- LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
+ details.getString(),
LLStringUtil::null,
OSMB_OK);
return 0;
}
+ // If we don't have the right shader requirements.
+ if (!gGLManager.mHasShaderObjects
+ || !gGLManager.mHasVertexShader
+ || !gGLManager.mHasFragmentShader)
+ {
+ LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedShaderRequirements");
+ OSMessageBox(
+ details.getString(),
+ LLStringUtil::null,
+ OSMB_OK);
+ return 0;
+ }
+
// Without SSE2 support we will crash almost immediately, warn here.
if (!gSysCPU.hasSSE2())
{
@@ -1258,10 +1274,6 @@ bool LLAppViewer::init()
joystick = LLViewerJoystick::getInstance();
joystick->setNeedsReset(true);
- /*----------------------------------------------------------------------*/
-
- gSavedSettings.getControl("FramePerSecondLimit")->getSignal()->connect(boost::bind(&LLAppViewer::onChangeFrameLimit, this, _2));
- onChangeFrameLimit(gSavedSettings.getLLSD("FramePerSecondLimit"));
return true;
}
@@ -1481,21 +1493,6 @@ bool LLAppViewer::doFrame()
display();
- static U64 last_call = 0;
- if (!gTeleportDisplay || gGLManager.mIsIntel) // SL-10625...throttle early, throttle often with Intel
- {
- // Frame/draw throttling
- U64 elapsed_time = LLTimer::getTotalTime() - last_call;
- if (elapsed_time < mMinMicroSecPerFrame)
- {
- LL_RECORD_BLOCK_TIME(FTM_SLEEP);
- // llclamp for when time function gets funky
- U64 sleep_time = llclamp(mMinMicroSecPerFrame - elapsed_time, (U64)1, (U64)1e6);
- micro_sleep(sleep_time, 0);
- }
- }
- last_call = LLTimer::getTotalTime();
-
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
LLFloaterOutfitSnapshot::update();
@@ -1520,8 +1517,10 @@ bool LLAppViewer::doFrame()
}
// yield cooperatively when not running as foreground window
- if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible())
- || !gFocusMgr.getAppHasFocus())
+ // and when not quiting (causes trouble at mac's cleanup stage)
+ if (!LLApp::isExiting()
+ && ((gViewerWindow && !gViewerWindow->getWindow()->getVisible())
+ || !gFocusMgr.getAppHasFocus()))
{
// Sleep if we're not rendering, or the window is minimized.
static LLCachedControl<S32> s_bacground_yeild_time(gSavedSettings, "BackgroundYieldTime", 40);
@@ -2119,8 +2118,6 @@ bool LLAppViewer::cleanup()
LLError::LLCallStacks::cleanup();
- removeMarkerFiles();
-
// It's not at first obvious where, in this long sequence, a generic cleanup
// call OUGHT to go. So let's say this: as we migrate cleanup from
// explicit hand-placed calls into the generic mechanism, eventually
@@ -2128,14 +2125,12 @@ bool LLAppViewer::cleanup()
// still see above are calls that MUST happen before the generic cleanup
// kicks in.
- // The logging subsystem depends on an LLSingleton. Any logging after
- // LLSingletonBase::deleteAll() won't be recorded.
- LL_INFOS() << "Goodbye!" << LL_ENDL;
-
// This calls every remaining LLSingleton's cleanupSingleton() and
// deleteSingleton() methods.
LLSingletonBase::deleteAll();
+ LL_INFOS() << "Goodbye!" << LL_ENDL;
+
removeDumpDir();
// return 0;
@@ -3122,8 +3117,9 @@ LLSD LLAppViewer::getViewerInfo() const
info["POSITION"] = ll_sd_from_vector3d(pos);
info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));
info["REGION"] = gAgent.getRegion()->getName();
- info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
- info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
+
+ boost::regex regex("\\.(secondlife|lindenlab)\\..*");
+ info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getHost().getHostName(), regex, "");
info["SERVER_VERSION"] = gLastVersionChannel;
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
@@ -3991,6 +3987,7 @@ static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_q
void LLAppViewer::userQuit()
{
+ LL_INFOS() << "User requested quit" << LL_ENDL;
if (gDisconnected
|| !gViewerWindow
|| !gViewerWindow->getProgressView()
@@ -4851,13 +4848,14 @@ void LLAppViewer::idle()
{
return;
}
+
+ gViewerWindow->updateUI();
+
if (gTeleportDisplay)
{
return;
}
- gViewerWindow->updateUI();
-
///////////////////////////////////////
// Agent and camera movement
//
@@ -5433,19 +5431,6 @@ void LLAppViewer::disconnectViewer()
LLUrlEntryParcel::setDisconnected(gDisconnected);
}
-bool LLAppViewer::onChangeFrameLimit(LLSD const & evt)
-{
- if (evt.asInteger() > 0)
- {
- mMinMicroSecPerFrame = (U64)(1000000.0f / F32(evt.asInteger()));
- }
- else
- {
- mMinMicroSecPerFrame = 0;
- }
- return false;
-}
-
void LLAppViewer::forceErrorLLError()
{
LL_ERRS() << "This is a deliberate llerror" << LL_ENDL;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index e8b3464c6e..8f0f54de3b 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -255,8 +255,6 @@ private:
void sendLogoutRequest();
void disconnectViewer();
- bool onChangeFrameLimit(LLSD const & evt);
-
// *FIX: the app viewer class should be some sort of singleton, no?
// Perhaps its child class is the singleton and this should be an abstract base.
static LLAppViewer* sInstance;
@@ -313,10 +311,7 @@ private:
// llcorehttp library init/shutdown helper
LLAppCoreHttp mAppCoreHttp;
- bool mIsFirstRun;
- U64 mMinMicroSecPerFrame; // frame throttling
-
-
+ bool mIsFirstRun;
};
// consts from viewer.h
diff --git a/indra/newview/llappviewerlistener.cpp b/indra/newview/llappviewerlistener.cpp
index 94250f1fc2..2380a8ebf0 100644
--- a/indra/newview/llappviewerlistener.cpp
+++ b/indra/newview/llappviewerlistener.cpp
@@ -52,10 +52,12 @@ LLAppViewerListener::LLAppViewerListener(const LLAppViewerGetter& getter):
void LLAppViewerListener::requestQuit(const LLSD& event)
{
+ LL_INFOS() << "Listener requested quit" << LL_ENDL;
mAppViewerGetter()->requestQuit();
}
void LLAppViewerListener::forceQuit(const LLSD& event)
{
+ LL_INFOS() << "Listener requested force quit" << LL_ENDL;
mAppViewerGetter()->forceQuit();
}
diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h
index 37e8a3917a..79c3efff91 100644
--- a/indra/newview/llappviewermacosx-for-objc.h
+++ b/indra/newview/llappviewermacosx-for-objc.h
@@ -41,6 +41,7 @@ struct CrashMetadata
{
std::string logFilePathname;
std::string userSettingsPathname;
+ std::string accountSettingsPathname;
std::string staticDebugPathname;
std::string OSInfo;
std::string agentFullname;
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 3111540a13..662164af2d 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -199,10 +199,11 @@ CrashMetadataSingleton::CrashMetadataSingleton()
else
{
LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL;
- logFilePathname = get_metadata(info, "SLLog");
- userSettingsPathname = get_metadata(info, "SettingsFilename");
- OSInfo = get_metadata(info, "OSInfo");
- agentFullname = get_metadata(info, "LoginName");
+ logFilePathname = get_metadata(info, "SLLog");
+ userSettingsPathname = get_metadata(info, "SettingsFilename");
+ accountSettingsPathname = get_metadata(info, "PerAccountSettingsFilename");
+ OSInfo = get_metadata(info, "OSInfo");
+ agentFullname = get_metadata(info, "LoginName");
// Translate underscores back to spaces
LLStringUtil::replaceChar(agentFullname, '_', ' ');
regionName = get_metadata(info, "CurrentRegion");
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 156a1c5893..9b1c0d1f8b 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -139,6 +139,9 @@ namespace
{
// user name, when we have it
sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname()));
+
+ sBugSplatSender->sendAdditionalFile(
+ WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "settings_per_account.xml")));
}
// LL_ERRS message, when there is one
diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h
index a4ef762e8b..90aeff3032 100644
--- a/indra/newview/llattachmentsmgr.h
+++ b/indra/newview/llattachmentsmgr.h
@@ -30,8 +30,6 @@
#include "llsingleton.h"
-class LLViewerInventoryItem;
-
//--------------------------------------------------------------------------------
// LLAttachmentsMgr
//
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index a1dacd1a27..c510e86958 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -31,7 +31,6 @@
#include "lliconctrl.h"
#include "llavatarpropertiesprocessor.h"
-#include "llviewermenu.h"
class LLAvatarName;
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index 36d18114aa..b95cd68526 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -30,7 +30,6 @@
#include <boost/signals2.hpp>
#include "llpanel.h"
-#include "lloutputmonitorctrl.h"
#include "llbutton.h"
#include "lltextbox.h"
#include "llstyle.h"
@@ -38,6 +37,7 @@
#include "llcallingcard.h" // for LLFriendObserver
class LLAvatarIconCtrl;
+class LLOutputMonitorCtrl;
class LLAvatarName;
class LLIconCtrl;
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 54c6c985d6..3ab5c669c4 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -57,7 +57,6 @@
#include "llinventorymodel.h"
#include "llmultigesture.h"
#include "llui.h"
-#include "llviewermenu.h"
#include "lluictrlfactory.h"
//
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 431a8c60be..2ba2c6d8b5 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -64,6 +64,7 @@
#include "llstring.h"
#include "llurlaction.h"
#include "llviewercontrol.h"
+#include "llviewermenu.h"
#include "llviewerobjectlist.h"
static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index 4f42868f1a..1c22e055bb 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "llchatitemscontainerctrl.h"
+#include "llchatmsgbox.h"
#include "lltextbox.h"
#include "llavataractions.h"
diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h
index f66670ec8c..ebff9ca298 100644
--- a/indra/newview/llchatitemscontainerctrl.h
+++ b/indra/newview/llchatitemscontainerctrl.h
@@ -28,12 +28,13 @@
#define LL_LLCHATITEMSCONTAINERCTRL_H_
#include "llchat.h"
-#include "llchatmsgbox.h"
#include "llpanel.h"
#include "llscrollbar.h"
#include "llviewerchat.h"
#include "lltoastpanel.h"
+class LLChatMsgBox;
+
typedef enum e_show_item_header
{
CHATITEMHEADER_SHOW_ONLY_NAME = 0,
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index dedb06c945..0f187b0ecf 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -36,6 +36,7 @@
#include "llsingleton.h"
#include "llsyswellwindow.h"
#include "llfloaternotificationstabbed.h"
+#include "llviewermenu.h"
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
@@ -1092,6 +1093,10 @@ void LLScriptChiclet::onMenuItemClicked(const LLSD& user_data)
{
LLScriptFloaterManager::instance().removeNotification(getSessionId());
}
+ else if ("close all" == action)
+ {
+ LLIMWellWindow::getInstance()->closeAll();
+ }
}
void LLScriptChiclet::createPopupMenu()
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 1caefd58ab..b31981b235 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -140,10 +140,31 @@ protected:
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("Attachment.Touch", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs));
+ registrar.add("Attachment.Edit", boost::bind(handleMultiple, handle_item_edit, mUUIDs));
registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("Attachment.OnEnable", boost::bind(&CofAttachmentContextMenu::onEnable, this, _2));
+
return createFromFile("menu_cof_attachment.xml");
}
+
+ bool onEnable(const LLSD& userdata)
+ {
+ const std::string event_name = userdata.asString();
+
+ if ("touch" == event_name)
+ {
+ return (1 == mUUIDs.size()) && (enable_attachment_touch(mUUIDs.front()));
+ }
+ else if ("edit" == event_name)
+ {
+ return (1 == mUUIDs.size()) && (get_is_item_editable(mUUIDs.front()));
+ }
+
+ return true;
+ }
};
//////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h
index 380fdccfa3..a17cab486a 100644
--- a/indra/newview/llcolorswatch.h
+++ b/indra/newview/llcolorswatch.h
@@ -36,7 +36,6 @@
// Classes
//
class LLColor4;
-class LLFloaterColorPicker;
class LLColorSwatchCtrl
: public LLUICtrl
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index fe14bc081f..06d959ba3c 100644
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -402,23 +402,30 @@ bool LLCommandLineParser::parseCommandLineString(const std::string& str)
}
}
- // Split the string content into tokens
- const char* escape_chars = "\\";
- const char* separator_chars = "\r\n ";
- const char* quote_chars = "\"'";
- boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars);
- boost::tokenizer< boost::escaped_list_separator<char> > tok(cmd_line_string, sep);
std::vector<std::string> tokens;
- // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens));
- for(boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin();
- i != tok.end();
- ++i)
+ try
{
- if(0 != i->size())
+ // Split the string content into tokens
+ const char* escape_chars = "\\";
+ const char* separator_chars = "\r\n ";
+ const char* quote_chars = "\"'";
+ boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars);
+ boost::tokenizer< boost::escaped_list_separator<char> > tok(cmd_line_string, sep);
+ // std::copy(tok.begin(), tok.end(), std::back_inserter(tokens));
+ for (boost::tokenizer< boost::escaped_list_separator<char> >::iterator i = tok.begin();
+ i != tok.end();
+ ++i)
{
- tokens.push_back(*i);
+ if (0 != i->size())
+ {
+ tokens.push_back(*i);
+ }
}
}
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("Unexpected crash while parsing: " << str));
+ }
po::command_line_parser clp(tokens);
return parseAndStoreResults(clp);
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 76e16f5a1f..3aaaaf52f5 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -347,6 +347,13 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren
bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,
const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
+ if (LLApp::isQuitting())
+ {
+ // Reply from coroutine came on shutdown
+ // We are quiting, don't start any more coroutines!
+ return true;
+ }
+
LLSD result;
LLCheckedHandle<LLFloaterCompileQueue> floater(hfloater);
// Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle.
@@ -381,6 +388,8 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout,
LLSDMap("timeout", LLSD::Boolean(true)));
+ floater.check();
+
if (result.has("timeout"))
{ // A timeout filed in the result will always be true if present.
LLStringUtil::format_map_t args;
@@ -404,6 +413,12 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
}
+ if (!gAssetStorage)
+ {
+ // viewer likely is shutting down
+ return true;
+ }
+
{
HandleScriptUserData userData(pump.getName());
@@ -468,6 +483,8 @@ bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloat
result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSDMap("timeout", LLSD::Boolean(true)));
+ floater.check();
+
if (result.has("timeout"))
{ // A timeout filed in the result will always be true if present.
LLStringUtil::format_map_t args;
@@ -797,6 +814,7 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L
// but offers no guarantee of doing so.
llcoro::suspend();
}
+ floater.check();
}
floater->addStringMessage("Done");
diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h
index 1b3d8f83a0..adb854875a 100644
--- a/indra/newview/llcompilequeue.h
+++ b/indra/newview/llcompilequeue.h
@@ -29,14 +29,11 @@
#include "llinventory.h"
#include "llviewerobject.h"
-#include "llvoinventorylistener.h"
#include "lluuid.h"
#include "llfloater.h"
#include "llscrolllistctrl.h"
-#include "llviewerinventory.h"
-
#include "llevents.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 5539fa75dd..9430bb3ca3 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -482,6 +482,10 @@ bool LLConversationLog::saveToFile(const std::string& filename)
conv_it->getSessionID().toString(conversation_id);
conv_it->getParticipantID().toString(participant_id);
+ bool is_adhoc = (conv_it->getConversationType() == LLIMModel::LLIMSession::ADHOC_SESSION);
+ std::string conv_name = is_adhoc ? conv_it->getConversationName() : LLURI::escape(conv_it->getConversationName());
+ std::string file_name = is_adhoc ? conv_it->getHistoryFileName() : LLURI::escape(conv_it->getHistoryFileName());
+
// examples of two file entries
// [1343221177] 0 1 0 John Doe| 7e4ec5be-783f-49f5-71dz-16c58c64c145 4ec62a74-c246-0d25-2af6-846beac2aa55 john.doe|
// [1343222639] 2 0 0 Ad-hoc Conference| c3g67c89-c479-4c97-b21d-32869bcfe8rc 68f1c33e-4135-3e3e-a897-8c9b23115c09 Ad-hoc Conference hash597394a0-9982-766d-27b8-c75560213b9a|
@@ -490,10 +494,10 @@ bool LLConversationLog::saveToFile(const std::string& filename)
(S32)conv_it->getConversationType(),
(S32)0,
(S32)conv_it->hasOfflineMessages(),
- LLURI::escape(conv_it->getConversationName()).c_str(),
+ conv_name.c_str(),
participant_id.c_str(),
conversation_id.c_str(),
- LLURI::escape(conv_it->getHistoryFileName()).c_str());
+ file_name.c_str());
}
fclose(fp);
return true;
@@ -541,14 +545,18 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
conv_id_buffer,
history_file_name);
+ bool is_adhoc = ((SessionType)stype == LLIMModel::LLIMSession::ADHOC_SESSION);
+ std::string conv_name = is_adhoc ? conv_name_buffer : LLURI::unescape(conv_name_buffer);
+ std::string file_name = is_adhoc ? history_file_name : LLURI::unescape(history_file_name);
+
ConversationParams params;
params.time(LLUnits::Seconds::fromValue(time))
.conversation_type((SessionType)stype)
.has_offline_ims(has_offline_ims)
- .conversation_name(LLURI::unescape(conv_name_buffer))
+ .conversation_name(conv_name)
.participant_id(LLUUID(part_id_buffer))
.session_id(LLUUID(conv_id_buffer))
- .history_filename(LLURI::unescape(history_file_name));
+ .history_filename(file_name);
LLConversation conversation(params);
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index c258136889..4aa74a550c 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -92,6 +92,23 @@ LLConversationItem::~LLConversationItem()
}
}
+//virtual
+void LLConversationItem::addChild(LLFolderViewModelItem* child)
+{
+ // Avoid duplicates: bail out if that child is already present in the list
+ // Note: this happens when models are created and 'parented' before views
+ // This is performance unfriendly, but conversation can addToFolder multiple times
+ child_list_t::const_iterator iter;
+ for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
+ {
+ if (child == *iter)
+ {
+ return;
+ }
+ }
+ LLFolderViewModelItemCommon::addChild(child);
+}
+
void LLConversationItem::postEvent(const std::string& event_type, LLConversationItemSession* session, LLConversationItemParticipant* participant)
{
LLUUID session_id = (session ? session->getUUID() : LLUUID());
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 80385fad5f..30c7481864 100644
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -96,6 +96,7 @@ public:
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) { }
virtual BOOL isUpToDate() const { return TRUE; }
virtual bool hasChildren() const { return FALSE; }
+ virtual void addChild(LLFolderViewModelItem* child);
virtual bool potentiallyVisible() { return true; }
virtual bool filter( LLFolderViewFilter& filter) { return false; }
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 60a5204547..093e772abe 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -430,7 +430,7 @@ void LLConversationViewSession::refresh()
// Refresh the session view from its model data
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem());
vmi->resetRefresh();
-
+
if (mSessionTitle)
{
mSessionTitle->setText(vmi->getDisplayName());
@@ -545,7 +545,9 @@ BOOL LLConversationViewParticipant::postBuild()
}
updateChildren();
- return LLFolderViewItem::postBuild();
+ LLFolderViewItem::postBuild();
+ refresh();
+ return TRUE;
}
void LLConversationViewParticipant::draw()
@@ -619,7 +621,7 @@ void LLConversationViewParticipant::refresh()
// *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
-
+
// Do the regular upstream refresh
LLFolderViewItem::refresh();
}
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index 420c250dfe..c5930c8a29 100644
--- a/indra/newview/llconversationview.h
+++ b/indra/newview/llconversationview.h
@@ -34,6 +34,7 @@
#include "lloutputmonitorctrl.h"
class LLTextBox;
+class LLFloater;
class LLFloaterIMContainer;
class LLConversationViewSession;
class LLConversationViewParticipant;
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 8c6cbc020b..2219f20272 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1178,11 +1178,33 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
}
else if (isRoot())
{
- if (mSpatialBridge && (mSpatialBridge->asPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) != mVObjp->isHUDAttachment())
+ if (mSpatialBridge)
{
- // remove obsolete bridge
- mSpatialBridge->markDead();
- setSpatialBridge(NULL);
+ U32 partition_type = mSpatialBridge->asPartition()->mPartitionType;
+ bool is_hud = mVObjp->isHUDAttachment();
+ bool is_animesh = mVObjp->isAnimatedObject() && mVObjp->getControlAvatar() != NULL;
+ bool is_attachment = mVObjp->isAttachment() && !is_hud && !is_animesh;
+ if ((partition_type == LLViewerRegion::PARTITION_HUD) != is_hud)
+ {
+ // Was/became HUD
+ // remove obsolete bridge
+ mSpatialBridge->markDead();
+ setSpatialBridge(NULL);
+ }
+ else if ((partition_type == LLViewerRegion::PARTITION_CONTROL_AV) != is_animesh)
+ {
+ // Was/became part of animesh
+ // remove obsolete bridge
+ mSpatialBridge->markDead();
+ setSpatialBridge(NULL);
+ }
+ else if ((partition_type == LLViewerRegion::PARTITION_AVATAR) != is_attachment)
+ {
+ // Was/became part of avatar
+ // remove obsolete bridge
+ mSpatialBridge->markDead();
+ setSpatialBridge(NULL);
+ }
}
//must be an active volume
if (!mSpatialBridge)
@@ -1191,6 +1213,15 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
{
setSpatialBridge(new LLHUDBridge(this, getRegion()));
}
+ else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
+ {
+ setSpatialBridge(new LLControlAVBridge(this, getRegion()));
+ }
+ // check HUD first, because HUD is also attachment
+ else if (mVObjp->isAttachment())
+ {
+ setSpatialBridge(new LLAvatarBridge(this, getRegion()));
+ }
else
{
setSpatialBridge(new LLVolumeBridge(this, getRegion()));
@@ -1698,12 +1729,26 @@ void LLDrawable::updateFaceSize(S32 idx)
LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp)
: LLSpatialPartition(0, FALSE, 0, regionp)
{
- mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
+ mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
mLODPeriod = 16;
mSlopRatio = 0.25f;
}
+LLAvatarPartition::LLAvatarPartition(LLViewerRegion* regionp)
+ : LLBridgePartition(regionp)
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
+ mPartitionType = LLViewerRegion::PARTITION_AVATAR;
+}
+
+LLControlAVPartition::LLControlAVPartition(LLViewerRegion* regionp)
+ : LLBridgePartition(regionp)
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_CONTROL_AV;
+ mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV;
+}
+
LLHUDBridge::LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
: LLVolumeBridge(drawablep, regionp)
{
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 2aee7b450a..d583a692f9 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -86,7 +86,8 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
poolp = new LLDrawPoolAlpha();
break;
case POOL_AVATAR:
- poolp = new LLDrawPoolAvatar();
+ case POOL_CONTROL_AV:
+ poolp = new LLDrawPoolAvatar(type);
break;
case POOL_TREE:
poolp = new LLDrawPoolTree(tex0);
@@ -383,16 +384,6 @@ LLRenderPass::~LLRenderPass()
}
-LLDrawPool* LLRenderPass::instancePool()
-{
-#if LL_RELEASE_FOR_DOWNLOAD
- LL_WARNS() << "Attempting to instance a render pass. Invalid operation." << LL_ENDL;
-#else
- LL_ERRS() << "Attempting to instance a render pass. Invalid operation." << LL_ENDL;
-#endif
- return NULL;
-}
-
void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
{
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
@@ -449,7 +440,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
if (params.mModelMatrix != gGLLastMatrix)
{
gGLLastMatrix = params.mModelMatrix;
- gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.loadMatrix(gGLModelView);
if (params.mModelMatrix)
{
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 4eb9a4151d..ecd9bd034f 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -60,6 +60,7 @@ public:
POOL_GRASS,
POOL_INVISIBLE, // see below *
POOL_AVATAR,
+ POOL_CONTROL_AV, // Animesh
POOL_VOIDWATER,
POOL_WATER,
POOL_GLOW,
@@ -110,7 +111,6 @@ public:
virtual S32 getShaderLevel() const { return mShaderLevel; }
static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
- virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool.
virtual LLViewerTexture* getTexture() = 0;
virtual BOOL isFacePool() { return FALSE; }
virtual void resetDrawOrders() = 0;
@@ -138,31 +138,30 @@ public:
PASS_POST_BUMP,
PASS_MATERIAL,
PASS_MATERIAL_ALPHA,
- PASS_MATERIAL_ALPHA_MASK,
+ PASS_MATERIAL_ALPHA_MASK, // Diffuse texture used as alpha mask
PASS_MATERIAL_ALPHA_EMISSIVE,
PASS_SPECMAP,
PASS_SPECMAP_BLEND,
- PASS_SPECMAP_MASK,
+ PASS_SPECMAP_MASK, // Diffuse texture used as alpha mask and specular texture(map)
PASS_SPECMAP_EMISSIVE,
PASS_NORMMAP,
PASS_NORMMAP_BLEND,
- PASS_NORMMAP_MASK,
+ PASS_NORMMAP_MASK, // Diffuse texture used as alpha mask and normal map
PASS_NORMMAP_EMISSIVE,
PASS_NORMSPEC,
PASS_NORMSPEC_BLEND,
- PASS_NORMSPEC_MASK,
+ PASS_NORMSPEC_MASK, // Diffuse texture used as alpha mask with normal and specular map
PASS_NORMSPEC_EMISSIVE,
PASS_GLOW,
PASS_ALPHA,
PASS_ALPHA_MASK,
- PASS_FULLBRIGHT_ALPHA_MASK,
+ PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright
PASS_ALPHA_INVISIBLE,
NUM_RENDER_TYPES,
};
LLRenderPass(const U32 type);
virtual ~LLRenderPass();
- /*virtual*/ LLDrawPool* instancePool();
/*virtual*/ LLViewerTexture* getDebugTexture() { return NULL; }
LLViewerTexture* getTexture() { return NULL; }
BOOL isDead() { return FALSE; }
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index da0467315f..4ee08e869a 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -314,11 +314,15 @@ void LLDrawPoolAlpha::render(S32 pass)
LLVertexBuffer::MAP_TEXCOORD0);
pushBatches(LLRenderPass::PASS_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
pushBatches(LLRenderPass::PASS_ALPHA_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ // Material alpha mask
gGL.diffuseColor4f(0, 0, 1, 1);
pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_NORMMAP_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_SPECMAP_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_NORMSPEC_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
gGL.diffuseColor4f(0, 1, 0, 1);
pushBatches(LLRenderPass::PASS_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 789a254389..87772d9eb6 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -38,7 +38,6 @@
#include "lldrawable.h"
#include "lldrawpoolbump.h"
#include "llface.h"
-#include "llvolume.h"
#include "llmeshrepository.h"
#include "llsky.h"
#include "llviewercamera.h"
@@ -106,8 +105,8 @@ S32 cube_channel = -1;
static LLTrace::BlockTimerStatHandle FTM_SHADOW_AVATAR("Avatar Shadow");
-LLDrawPoolAvatar::LLDrawPoolAvatar() :
- LLFacePool(POOL_AVATAR)
+LLDrawPoolAvatar::LLDrawPoolAvatar(U32 type) :
+ LLFacePool(type)
{
}
@@ -136,15 +135,6 @@ BOOL LLDrawPoolAvatar::isDead()
}
return TRUE;
}
-
-//-----------------------------------------------------------------------------
-// instancePool()
-//-----------------------------------------------------------------------------
-LLDrawPool *LLDrawPoolAvatar::instancePool()
-{
- return new LLDrawPoolAvatar();
-}
-
S32 LLDrawPoolAvatar::getShaderLevel() const
{
@@ -1741,11 +1731,16 @@ void LLDrawPoolAvatar::getRiggedGeometry(
LLVolume* volume,
const LLVolumeFace& vol_face)
{
- face->setGeomIndex(0);
- face->setIndicesIndex(0);
-
- //rigged faces do not batch textures
- face->setTextureIndex(255);
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+
+ if (face->getTextureIndex() != FACE_DO_NOT_BATCH_TEXTURES)
+ {
+ face->setDrawInfo(NULL);
+ }
+
+ //rigged faces do not batch textures
+ face->setTextureIndex(FACE_DO_NOT_BATCH_TEXTURES);
if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
{
@@ -1810,7 +1805,7 @@ void LLDrawPoolAvatar::getRiggedGeometry(
}
else
{
- face->setPoolType(LLDrawPool::POOL_AVATAR);
+ face->setPoolType(mType); // either POOL_AVATAR or POOL_CONTROL_AV
}
//LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL;
@@ -2494,7 +2489,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
{
llassert (facep->isState(LLFace::RIGGED));
- llassert(getType() == LLDrawPool::POOL_AVATAR);
+ llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV);
if (facep->getPool() && facep->getPool() != this)
{
LL_ERRS() << "adding rigged face that's already in another pool" << LL_ENDL;
@@ -2516,7 +2511,7 @@ void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)
{
llassert (facep->isState(LLFace::RIGGED));
- llassert(getType() == LLDrawPool::POOL_AVATAR);
+ llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV);
if (facep->getPool() != this)
{
LL_ERRS() << "Tried to remove a rigged face from the wrong pool" << LL_ENDL;
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index cb09eb18e2..92a8538958 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -178,12 +178,10 @@ typedef enum
virtual S32 getShaderLevel() const;
- LLDrawPoolAvatar();
+ LLDrawPoolAvatar(U32 type);
static LLMatrix4& getModelView();
- /*virtual*/ LLDrawPool *instancePool();
-
/*virtual*/ S32 getNumPasses();
/*virtual*/ void beginRenderPass(S32 pass);
/*virtual*/ void endRenderPass(S32 pass);
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index 6bd2631d3b..5b74264dab 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -46,11 +46,6 @@ LLDrawPoolGround::LLDrawPoolGround() :
{
}
-LLDrawPool *LLDrawPoolGround::instancePool()
-{
- return new LLDrawPoolGround();
-}
-
void LLDrawPoolGround::prerender()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h
index a4f8a3fcf5..15b1dc60a2 100644
--- a/indra/newview/lldrawpoolground.h
+++ b/indra/newview/lldrawpoolground.h
@@ -43,8 +43,6 @@ public:
LLDrawPoolGround();
- /*virtual*/ LLDrawPool *instancePool();
-
/*virtual*/ void prerender();
/*virtual*/ void render(S32 pass = 0);
};
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index dbe8724088..b6f55e800a 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -48,11 +48,6 @@ LLDrawPoolSky::LLDrawPoolSky()
{
}
-LLDrawPool *LLDrawPoolSky::instancePool()
-{
- return new LLDrawPoolSky();
-}
-
void LLDrawPoolSky::prerender()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
@@ -128,23 +123,12 @@ void LLDrawPoolSky::renderSkyFace(U8 index)
return;
}
- F32 interp_val = gSky.mVOSkyp ? gSky.mVOSkyp->getInterpVal() : 0.0f;
-
if (index < 6) // sky tex...interp
{
llassert(mSkyTex);
mSkyTex[index].bindTexture(true); // bind the current tex
face->renderIndexed();
-
- if (interp_val > 0.01f) // iff, we've got enough info to lerp (a to and a from)
- {
- LLGLEnable blend(GL_BLEND);
- llassert(mSkyTex);
- mSkyTex[index].bindTexture(false); // bind the "other" texture
- gGL.diffuseColor4f(1, 1, 1, interp_val); // lighting is disabled
- face->renderIndexed();
- }
}
else // heavenly body faces, no interp...
{
diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h
index 916d8c1cbe..d1dcd6b22e 100644
--- a/indra/newview/lldrawpoolsky.h
+++ b/indra/newview/lldrawpoolsky.h
@@ -49,8 +49,6 @@ public:
LLDrawPoolSky();
- /*virtual*/ LLDrawPool *instancePool();
-
/*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); }
/*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
/*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 33a11631fe..37dc80e2b7 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -87,13 +87,6 @@ LLDrawPoolTerrain::~LLDrawPoolTerrain()
llassert( gPipeline.findPool( getType(), getTexture() ) == NULL );
}
-
-LLDrawPool *LLDrawPoolTerrain::instancePool()
-{
- return new LLDrawPoolTerrain(mTexturep);
-}
-
-
U32 LLDrawPoolTerrain::getVertexDataMask()
{
if (LLPipeline::sShadowRender)
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 04e27d9370..5b4558020d 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -49,8 +49,6 @@ public:
LLDrawPoolTerrain(LLViewerTexture *texturep);
virtual ~LLDrawPoolTerrain();
- /*virtual*/ LLDrawPool *instancePool();
-
/*virtual*/ S32 getNumDeferredPasses() { return 1; }
/*virtual*/ void beginDeferredPass(S32 pass);
/*virtual*/ void endDeferredPass(S32 pass);
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index b885008cae..0d5195bdbf 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -51,11 +51,6 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) :
mTexturep->setAddressMode(LLTexUnit::TAM_WRAP);
}
-LLDrawPool *LLDrawPoolTree::instancePool()
-{
- return new LLDrawPoolTree(mTexturep);
-}
-
void LLDrawPoolTree::prerender()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h
index 9c1e60f5eb..13f9ec8dce 100644
--- a/indra/newview/lldrawpooltree.h
+++ b/indra/newview/lldrawpooltree.h
@@ -45,8 +45,6 @@ public:
LLDrawPoolTree(LLViewerTexture *texturep);
- /*virtual*/ LLDrawPool *instancePool();
-
/*virtual*/ void prerender();
/*virtual*/ S32 getNumDeferredPasses() { return 1; }
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 073adfb627..aa426cd785 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -104,13 +104,6 @@ void LLDrawPoolWater::restoreGL()
}*/
}
-LLDrawPool *LLDrawPoolWater::instancePool()
-{
- LL_ERRS() << "Should never be calling instancePool on a water pool!" << LL_ENDL;
- return NULL;
-}
-
-
void LLDrawPoolWater::prerender()
{
mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
@@ -170,7 +163,7 @@ void LLDrawPoolWater::render(S32 pass)
std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
// See if we are rendering water as opaque or not
- if (!gSavedSettings.getBOOL("RenderTransparentWater"))
+ if (!LLPipeline::sRenderTransparentWater)
{
// render water for low end hardware
renderOpaqueLegacyWater();
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index d436557e1c..a5d163e0d7 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -61,7 +61,6 @@ public:
LLDrawPoolWater();
/*virtual*/ ~LLDrawPoolWater();
- /*virtual*/ LLDrawPool *instancePool();
static void restoreGL();
/*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); }
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 961d72c62e..d4e7f1600e 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -216,10 +216,11 @@ void LLDrawPoolWLSky::renderSkyHaze(const LLVector3& camPosLocal, F32 camHeightL
if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
{
+ LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
LLGLSPipelineDepthTestSkyBox sky(true, false);
sky_shader->bind();
sky_shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, 1);
- sky_shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, 1.0f);
+ sky_shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor());
renderDome(origin, camHeightLocal, sky_shader);
sky_shader->unbind();
}
@@ -531,8 +532,6 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
}
}
- blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor();
-
face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON];
if (gSky.mVOSkyp->getMoon().getDraw() && face && face->getTexture(LLRender::DIFFUSE_MAP) && face->getGeomCount() && moon_shader)
@@ -550,17 +549,17 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
{
// Bind current and next sun textures
moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
- blend_factor = 0;
+ //blend_factor = 0;
}
else if (tex_b && !tex_a)
{
moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
- blend_factor = 0;
+ //blend_factor = 0;
}
else if (tex_b != tex_a)
{
moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
- moon_shader->bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
+ //moon_shader->bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
}
LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
@@ -570,7 +569,8 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
moon_shader->uniform1f(LLShaderMgr::MOON_BRIGHTNESS, moon_brightness);
moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV);
moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV);
- moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+ //moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+ moon_shader->uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, psky->getMoonDirection().mV); // shader: moon_dir
face->renderIndexed();
@@ -632,11 +632,6 @@ void LLDrawPoolWLSky::prerender()
//LL_INFOS() << "wlsky prerendering pass." << LL_ENDL;
}
-LLDrawPoolWLSky *LLDrawPoolWLSky::instancePool()
-{
- return new LLDrawPoolWLSky();
-}
-
LLViewerTexture* LLDrawPoolWLSky::getTexture()
{
return NULL;
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index 3acfda4eee..a4f176d6db 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -62,8 +62,6 @@ public:
//static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
- // Create an empty new instance of the pool.
- /*virtual*/ LLDrawPoolWLSky *instancePool(); ///< covariant override
/*virtual*/ LLViewerTexture* getTexture();
/*virtual*/ BOOL isFacePool() { return FALSE; }
/*virtual*/ void resetDrawOrders();
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 1e8c57ac6a..89c20904c1 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -125,11 +125,11 @@ BOOL LLViewerDynamicTexture::render()
//-----------------------------------------------------------------------------
void LLViewerDynamicTexture::preRender(BOOL clear_depth)
{
- //only images up to 1024*1024 are supported
- llassert(mFullHeight <= 512);
- llassert(mFullWidth <= 512);
+ gPipeline.allocatePhysicsBuffer();
+ llassert(mFullWidth <= static_cast<S32>(gPipeline.mPhysicsDisplay.getWidth()));
+ llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight()));
- if (gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete())
+ if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsATI)
{ //using offscreen render target, just use the bottom left corner
mOrigin.set(0, 0);
}
@@ -216,7 +216,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
return TRUE;
}
- bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete();
+ bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsATI;
if (use_fbo)
{
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 342ee3ccf5..e56ed92d9e 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -806,6 +806,25 @@ const F32 LLEnvironment::SUN_DELTA_YAW(F_PI); // 180deg
const U32 LLEnvironment::DayInstance::NO_ANIMATE_SKY(0x01);
const U32 LLEnvironment::DayInstance::NO_ANIMATE_WATER(0x02);
+std::string env_selection_to_string(LLEnvironment::EnvSelection_t sel)
+{
+#define RTNENUM(E) case LLEnvironment::E: return #E
+ switch (sel){
+ RTNENUM(ENV_EDIT);
+ RTNENUM(ENV_LOCAL);
+ RTNENUM(ENV_PUSH);
+ RTNENUM(ENV_PARCEL);
+ RTNENUM(ENV_REGION);
+ RTNENUM(ENV_DEFAULT);
+ RTNENUM(ENV_END);
+ RTNENUM(ENV_CURRENT);
+ RTNENUM(ENV_NONE);
+ default:
+ return llformat("Unknown(%d)", sel);
+ }
+#undef RTNENUM
+}
+
//-------------------------------------------------------------------------
LLEnvironment::LLEnvironment():
@@ -981,7 +1000,7 @@ bool LLEnvironment::canAgentUpdateRegionEnvironment() const
if (gAgent.isGodlike())
return true;
- return gAgent.getRegion()->canManageEstate();
+ return gAgent.canManageEstate();
}
bool LLEnvironment::isExtendedEnvironmentEnabled() const
@@ -1037,7 +1056,8 @@ F32 LLEnvironment::getCamHeight() const
F32 LLEnvironment::getWaterHeight() const
{
- return gAgent.getRegion()->getWaterHeight();
+ LLViewerRegion* cur_region = gAgent.getRegion();
+ return cur_region ? cur_region->getWaterHeight() : DEFAULT_WATER_HEIGHT;
}
bool LLEnvironment::getIsSunUp() const
@@ -1059,6 +1079,7 @@ void LLEnvironment::setSelectedEnvironment(LLEnvironment::EnvSelection_t env, LL
{
mSelectedEnvironment = env;
updateEnvironment(transition, forced);
+ LL_DEBUGS("ENVIRONMENT") << "Setting environment " << env_selection_to_string(env) << " with transition: " << transition << LL_ENDL;
}
bool LLEnvironment::hasEnvironment(LLEnvironment::EnvSelection_t env)
@@ -1095,11 +1116,13 @@ LLEnvironment::DayInstance::ptr_t LLEnvironment::getEnvironmentInstance(LLEnviro
void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version)
{
if ((env < ENV_EDIT) || (env >= ENV_DEFAULT))
- {
- LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL;
+ {
+ LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL;
return;
}
+ logEnvironment(env, pday, env_version);
+
DayInstance::ptr_t environment = getEnvironmentInstance(env, true);
environment->clear();
@@ -1116,7 +1139,7 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm
{
if ((env < ENV_EDIT) || (env >= ENV_DEFAULT))
{
- LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL;
+ LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL;
return;
}
@@ -1125,30 +1148,32 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm
if (fixed.first)
{
+ logEnvironment(env, fixed.first, env_version);
environment->setSky(fixed.first);
environment->setFlags(DayInstance::NO_ANIMATE_SKY);
}
else if (!environment->getSky())
{
+ LL_DEBUGS("ENVIRONMENT") << "Blank sky for " << env_selection_to_string(env) << ". Reusing environment for sky." << LL_ENDL;
environment->setSky(mCurrentEnvironment->getSky());
environment->setFlags(DayInstance::NO_ANIMATE_SKY);
}
if (fixed.second)
{
+ logEnvironment(env, fixed.second, env_version);
environment->setWater(fixed.second);
environment->setFlags(DayInstance::NO_ANIMATE_WATER);
}
else if (!environment->getWater())
{
+ LL_DEBUGS("ENVIRONMENT") << "Blank water for " << env_selection_to_string(env) << ". Reusing environment for water." << LL_ENDL;
environment->setWater(mCurrentEnvironment->getWater());
environment->setFlags(DayInstance::NO_ANIMATE_WATER);
}
if (!mSignalEnvChanged.empty())
mSignalEnvChanged(env, env_version);
-
- /*TODO: readjust environment*/
}
void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version)
@@ -1221,10 +1246,12 @@ void LLEnvironment::onSetEnvAssetLoaded(EnvSelection_t env,
if (!settings || status)
{
LLSD args;
- args["DESC"] = asset_id.asString();
+ args["NAME"] = asset_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
+ LL_DEBUGS("ENVIRONMENT") << "Failed to find settings for " << env_selection_to_string(env) << ", asset_id: " << asset_id << LL_ENDL;
return;
}
+ LL_DEBUGS("ENVIRONMENT") << "Loaded asset: " << asset_id << LL_ENDL;
setEnvironment(env, settings);
updateEnvironment(transition);
@@ -1238,19 +1265,48 @@ void LLEnvironment::clearEnvironment(LLEnvironment::EnvSelection_t env)
return;
}
+ LL_DEBUGS("ENVIRONMENT") << "Cleaning environment " << env_selection_to_string(env) << LL_ENDL;
+
mEnvironments[env].reset();
if (!mSignalEnvChanged.empty())
mSignalEnvChanged(env, VERSION_CLEANUP);
+}
- /*TODO: readjust environment*/
+void LLEnvironment::logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version)
+{
+ LL_DEBUGS("ENVIRONMENT") << "Setting Day environment " << env_selection_to_string(env) << " with version(update type): " << env_version << LL_NEWLINE;
+ // code between LL_DEBUGS and LL_ENDL won't execute unless log is enabled
+ if (settings)
+ {
+ LLUUID asset_id = settings->getAssetId();
+ if (asset_id.notNull())
+ {
+ LL_CONT << "Asset id: " << asset_id << LL_NEWLINE;
+ }
+
+ LLUUID id = settings->getId(); // Not in use?
+ if (id.notNull())
+ {
+ LL_CONT << "Settings id: " << id << LL_NEWLINE;
+ }
+
+ LL_CONT << "Name: " << settings->getName() << LL_NEWLINE
+ << "Type: " << settings->getSettingsType() << LL_NEWLINE
+ << "Flags: " << settings->getFlags(); // Not in use?
+ }
+ else
+ {
+ LL_CONT << "Empty settings!";
+ }
+ LL_CONT << LL_ENDL;
}
LLSettingsDay::ptr_t LLEnvironment::getEnvironmentDay(LLEnvironment::EnvSelection_t env)
{
if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
{
- LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+ LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL;
return LLSettingsDay::ptr_t();
}
@@ -1266,7 +1322,7 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayLength(EnvSelection_t env
{
if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
{
- LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+ LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL;
return LLSettingsDay::Seconds(0);
}
@@ -1282,7 +1338,7 @@ LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayOffset(EnvSelection_t env
{
if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
{
- LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+ LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL;
return LLSettingsDay::Seconds(0);
}
@@ -1325,7 +1381,7 @@ LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironme
if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
{
- LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+ LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection (" << env_selection_to_string(env) << ")." << LL_ENDL;
return fixedEnvironment_t();
}
@@ -2361,7 +2417,7 @@ void LLEnvironment::onSetExperienceEnvAssetLoaded(LLUUID experience_id, LLSettin
if (!settings || status)
{
LLSD args;
- args["DESC"] = experience_id.asString();
+ args["NAME"] = experience_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
return;
}
@@ -3332,7 +3388,7 @@ namespace
return;
}
- LL_WARNS("PUSHENV") << "Underlying environment has changed (" << env << ")! Base env is type " << base_env << LL_ENDL;
+ LL_WARNS("PUSHENV", "ENVIRONMENT") << "Underlying environment has changed (" << env << ")! Base env is type " << base_env << LL_ENDL;
LLEnvironment::DayInstance::ptr_t trans = std::make_shared<InjectedTransition>(std::static_pointer_cast<DayInjection>(shared_from_this()),
mBaseDayInstance->getSky(), mBaseDayInstance->getWater(), nextbase, LLEnvironment::TRANSITION_DEFAULT);
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 91c4b85135..6ab0db7501 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -148,8 +148,11 @@ public:
void setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version = NO_VERSION);
void setSharedEnvironment();
-
void clearEnvironment(EnvSelection_t env);
+
+ static void logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version = NO_VERSION);
+
+
LLSettingsDay::ptr_t getEnvironmentDay(EnvSelection_t env);
LLSettingsDay::Seconds getEnvironmentDayLength(EnvSelection_t env);
LLSettingsDay::Seconds getEnvironmentDayOffset(EnvSelection_t env);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 18ea184da6..4a802ad9aa 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -153,7 +153,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
}
mTEOffset = -1;
- mTextureIndex = 255;
+ mTextureIndex = FACE_DO_NOT_BATCH_TEXTURES;
setDrawable(drawablep);
mVObjp = objp;
@@ -184,6 +184,7 @@ void LLFace::destroy()
if(mTexture[i].notNull())
{
mTexture[i]->removeFace(i, this) ;
+ mTexture[i] = NULL;
}
}
@@ -195,7 +196,7 @@ void LLFace::destroy()
if (mDrawPoolp)
{
- if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR)
+ if (this->isState(LLFace::RIGGED) && (mDrawPoolp->getType() == LLDrawPool::POOL_CONTROL_AV || mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR))
{
((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this);
}
@@ -203,7 +204,6 @@ void LLFace::destroy()
{
mDrawPoolp->removeFace(this);
}
-
mDrawPoolp = NULL;
}
@@ -212,7 +212,7 @@ void LLFace::destroy()
delete mTextureMatrix;
mTextureMatrix = NULL;
- if (mDrawablep.notNull())
+ if (mDrawablep)
{
LLSpatialGroup* group = mDrawablep->getSpatialGroup();
if (group)
@@ -224,7 +224,7 @@ void LLFace::destroy()
}
setDrawInfo(NULL);
-
+
mDrawablep = NULL;
mVObjp = NULL;
}
@@ -456,13 +456,13 @@ void LLFace::setTextureIndex(U8 index)
{
mTextureIndex = index;
- if (mTextureIndex != 255)
+ if (mTextureIndex != FACE_DO_NOT_BATCH_TEXTURES)
{
mDrawablep->setState(LLDrawable::REBUILD_POSITION);
}
else
{
- if (mDrawInfo && mDrawInfo->mTextureList.size() <= 1)
+ if (mDrawInfo && !mDrawInfo->mTextureList.empty())
{
LL_ERRS() << "Face with no texture index references indexed texture draw info." << LL_ENDL;
}
@@ -535,7 +535,7 @@ void LLFace::updateCenterAgent()
void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
{
- if (mDrawablep->getSpatialGroup() == NULL)
+ if (mDrawablep == NULL || mDrawablep->getSpatialGroup() == NULL)
{
return;
}
@@ -543,7 +543,7 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
mDrawablep->getSpatialGroup()->rebuildGeom();
mDrawablep->getSpatialGroup()->rebuildMesh();
- if(mDrawablep.isNull() || mVertexBuffer.isNull())
+ if(mVertexBuffer.isNull())
{
return;
}
@@ -1539,7 +1539,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount);
- U8 index = mTextureIndex < 255 ? mTextureIndex : 0;
+ U8 index = mTextureIndex < FACE_DO_NOT_BATCH_TEXTURES ? mTextureIndex : 0;
S32 val = 0;
U8* vp = (U8*) &val;
@@ -2072,7 +2072,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLVector4a texIdx;
- S32 index = mTextureIndex < 255 ? mTextureIndex : 0;
+ S32 index = mTextureIndex < FACE_DO_NOT_BATCH_TEXTURES ? mTextureIndex : 0;
F32 val = 0.f;
S32* vp = (S32*) &val;
@@ -2673,7 +2673,7 @@ S32 LLFace::renderElements(const U16 *index_array) const
S32 LLFace::renderIndexed()
{
- if(mDrawablep.isNull() || mDrawPoolp == NULL)
+ if(mDrawablep == NULL || mDrawPoolp == NULL)
{
return 0;
}
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index c74d4e3fa8..3611539ff8 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -52,6 +52,7 @@ class LLDrawInfo;
const F32 MIN_ALPHA_SIZE = 1024.f;
const F32 MIN_TEX_ANIM_SIZE = 512.f;
+const U8 FACE_DO_NOT_BATCH_TEXTURES = 255;
class LLFace : public LLTrace::MemTrackableNonVirtual<LLFace, 16>
{
@@ -279,8 +280,13 @@ private:
LLXformMatrix* mXform;
LLPointer<LLViewerTexture> mTexture[LLRender::NUM_TEXTURE_CHANNELS];
-
- LLPointer<LLDrawable> mDrawablep;
+
+ // mDrawablep is not supposed to be null, don't use LLPointer because
+ // mDrawablep owns LLFace and LLPointer is a good way to either cause a
+ // memory leak or a 'delete each other' situation if something deletes
+ // drawable wrongly.
+ LLDrawable* mDrawablep;
+ // LLViewerObject technically owns drawable, but also it should be strictly managed
LLPointer<LLViewerObject> mVObjp;
S32 mTEOffset;
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 91436e52fe..25348474a1 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -74,7 +74,6 @@ public:
void onClickBuy();
void onClickCancel();
- void onClickErrorWeb();
};
LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
@@ -132,7 +131,6 @@ BOOL LLFloaterBuyCurrencyUI::postBuild()
getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this));
getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this));
- getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickErrorWeb, this));
center();
@@ -173,7 +171,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
// hide most widgets - we'll turn them on as needed next
getChildView("info_buying")->setVisible(FALSE);
- getChildView("info_cannot_buy")->setVisible(FALSE);
getChildView("info_need_more")->setVisible(FALSE);
getChildView("purchase_warning_repurchase")->setVisible(FALSE);
getChildView("purchase_warning_notenough")->setVisible(FALSE);
@@ -183,32 +180,16 @@ void LLFloaterBuyCurrencyUI::updateUI()
if (hasError)
{
// display an error from the server
- getChildView("normal_background")->setVisible(FALSE);
- getChildView("error_background")->setVisible(TRUE);
- getChildView("info_cannot_buy")->setVisible(TRUE);
- getChildView("cannot_buy_message")->setVisible(TRUE);
- getChildView("balance_label")->setVisible(FALSE);
- getChildView("balance_amount")->setVisible(FALSE);
- getChildView("buying_label")->setVisible(FALSE);
- getChildView("buying_amount")->setVisible(FALSE);
- getChildView("total_label")->setVisible(FALSE);
- getChildView("total_amount")->setVisible(FALSE);
-
- LLTextBox* message = getChild<LLTextBox>("cannot_buy_message");
- if (message)
- {
- message->setText(mManager.errorMessage());
- }
-
- getChildView("error_web")->setVisible( !mManager.errorURI().empty());
+ LLSD args;
+ args["TITLE"] = getString("info_cannot_buy");
+ args["MESSAGE"] = mManager.errorMessage();
+ LLNotificationsUtil::add("CouldNotBuyCurrency", args);
+ closeFloater();
}
else
{
// display the main Buy L$ interface
getChildView("normal_background")->setVisible(TRUE);
- getChildView("error_background")->setVisible(FALSE);
- getChildView("cannot_buy_message")->setVisible(FALSE);
- getChildView("error_web")->setVisible(FALSE);
if (mHasTarget)
{
@@ -278,14 +259,6 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
LLStatusBar::sendMoneyBalanceRequest();
}
-void LLFloaterBuyCurrencyUI::onClickErrorWeb()
-{
- LLWeb::loadURL(mManager.errorURI());
- closeFloater();
- // Update L$ balance
- LLStatusBar::sendMoneyBalanceRequest();
-}
-
// static
void LLFloaterBuyCurrency::buyCurrency()
{
diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp
index 44725cab70..580a3f2610 100644
--- a/indra/newview/llfloaterconversationpreview.cpp
+++ b/indra/newview/llfloaterconversationpreview.cpp
@@ -84,7 +84,7 @@ BOOL LLFloaterConversationPreview::postBuild()
file = "chat";
}
mChatHistoryFileName = file;
- if (mIsGroup)
+ if (mIsGroup && !LLStringUtil::endsWith(mChatHistoryFileName, GROUP_CHAT_SUFFIX))
{
mChatHistoryFileName += GROUP_CHAT_SUFFIX;
}
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index ea22043de8..a7c2cbbeaa 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -1498,7 +1498,7 @@ void LLFloaterEditExtDayCycle::onAssetLoaded(LLUUID asset_id, LLSettingsBase::pt
if (!settings || status)
{
LLSD args;
- args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : "Unknown";
+ args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
closeFloater();
return;
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 37e162b249..cd8e0a48e7 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -346,7 +346,7 @@ void LLFloaterFixedEnvironment::onAssetLoaded(LLUUID asset_id, LLSettingsBase::p
if (!settings || status)
{
LLSD args;
- args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : "Unknown";
+ args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : asset_id.asString();
LLNotificationsUtil::add("FailedToFindSettings", args);
closeFloater();
return;
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index 696f748613..028c922a4d 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -35,6 +35,7 @@
#include "llagent.h"
#include "llbutton.h"
+#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldrawable.h"
#include "lldrawpoolavatar.h"
@@ -115,8 +116,14 @@ BOOL LLFloaterImagePreview::postBuild()
mSculptedPreview = new LLImagePreviewSculpted(256, 256);
mSculptedPreview->setPreviewTarget(mRawImagep, 2.0f);
- if (mRawImagep->getWidth() * mRawImagep->getHeight () <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)
- getChildView("lossless_check")->setEnabled(TRUE);
+ if (mRawImagep->getWidth() * mRawImagep->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)
+ {
+ // We want "lossless_check" to be unchecked when it is disabled, regardless of
+ // LosslessJ2CUpload state, so only assign control when enabling checkbox
+ LLCheckBoxCtrl* check_box = getChild<LLCheckBoxCtrl>("lossless_check");
+ check_box->setEnabled(TRUE);
+ check_box->setControlVariable(gSavedSettings.getControl("LosslessJ2CUpload"));
+ }
}
else
{
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 21420b122b..2a05f82f94 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -54,9 +54,13 @@
#include "llcallbacklist.h"
#include "llworld.h"
#include "llsdserialize.h"
+#include "llviewermenu.h" // is_agent_mappable
#include "llviewerobjectlist.h"
#include "boost/foreach.hpp"
+
+const S32 EVENTS_PER_IDLE_LOOP = 100;
+
//
// LLFloaterIMContainer
//
@@ -66,7 +70,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
mInitialized(false),
- mIsFirstLaunch(true)
+ mIsFirstLaunch(true),
+ mConversationEventQueue()
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@@ -424,7 +429,9 @@ void LLFloaterIMContainer::idle(void* user_data)
{
LLFloaterIMContainer* self = static_cast<LLFloaterIMContainer*>(user_data);
- if (!self->getVisible() || self->isMinimized())
+ self->idleProcessEvents();
+
+ if (!self->getVisible() || self->isMinimized())
{
return;
}
@@ -455,7 +462,7 @@ void LLFloaterIMContainer::idleUpdate()
while (current_participant_model != end_participant_model)
{
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
- participant_model->setModeratorOptionsVisible(is_moderator && participant_model->getUUID() != gAgentID);
+ participant_model->setModeratorOptionsVisible(is_moderator);
participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
current_participant_model++;
@@ -485,13 +492,28 @@ void LLFloaterIMContainer::idleUpdate()
}
}
+void LLFloaterIMContainer::idleProcessEvents()
+{
+ if (!mConversationEventQueue.empty())
+ {
+ S32 events_to_handle = llmin((S32)mConversationEventQueue.size(), EVENTS_PER_IDLE_LOOP);
+ for (S32 i = 0; i < events_to_handle; i++)
+ {
+ handleConversationModelEvent(mConversationEventQueue.back());
+ mConversationEventQueue.pop_back();
+ }
+ }
+}
+
bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
{
- // For debug only
- //std::ostringstream llsd_value;
- //llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl;
- //LL_INFOS() << "LLFloaterIMContainer::onConversationModelEvent, event = " << llsd_value.str() << LL_ENDL;
- // end debug
+ mConversationEventQueue.push_front(event);
+ return true;
+}
+
+
+void LLFloaterIMContainer::handleConversationModelEvent(const LLSD& event)
+{
// Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that
// the model could change substantially and the view could echo only a portion of this model (though currently the
@@ -508,7 +530,7 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
if (!session_view)
{
// We skip events that are not associated with a session
- return false;
+ return;
}
LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id);
LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ?
@@ -535,9 +557,9 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
{
LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]);
LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL);
+ LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
if (!participant_view && session_model && participant_model)
- {
- LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
+ {
if (session_id.isNull() || (im_sessionp && !im_sessionp->isP2PSessionType()))
{
participant_view = createConversationViewParticipant(participant_model);
@@ -548,7 +570,8 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
// Add a participant view to the conversation floater
if (conversation_floater && participant_model)
{
- conversation_floater->addConversationViewParticipant(participant_model);
+ bool skip_updating = im_sessionp && im_sessionp->isGroupChat();
+ conversation_floater->addConversationViewParticipant(participant_model, !skip_updating);
}
}
else if (type == "update_participant")
@@ -571,12 +594,6 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
mConversationViewModel.requestSortAll();
mConversationsRoot->arrangeAll();
- if (conversation_floater)
- {
- conversation_floater->refreshConversation();
- }
-
- return false;
}
void LLFloaterIMContainer::draw()
@@ -1409,12 +1426,21 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return is_single_select;
}
-
- // Beyond that point, if only the user agent is selected, everything is disabled
- if (is_single_select && (single_id == gAgentID))
- {
- return false;
- }
+
+ bool is_moderator_option = ("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item);
+
+ // Beyond that point, if only the user agent is selected, everything is disabled
+ if (is_single_select && (single_id == gAgentID))
+ {
+ if (is_moderator_option)
+ {
+ return enableModerateContextMenuItem(item, true);
+ }
+ else
+ {
+ return false;
+ }
+ }
// If the user agent is selected with others, everything is disabled
for (uuid_vec_t::const_iterator id = uuids.begin(); id != uuids.end(); ++id)
@@ -1480,11 +1506,11 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return canBanSelectedMember(single_id);
}
- else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item))
- {
- // *TODO : get that out of here...
- return enableModerateContextMenuItem(item);
- }
+ else if (is_moderator_option)
+ {
+ // *TODO : get that out of here...
+ return enableModerateContextMenuItem(item);
+ }
// By default, options that not explicitely disabled are enabled
return true;
@@ -1854,7 +1880,7 @@ LLConversationViewParticipant* LLFloaterIMContainer::createConversationViewParti
return LLUICtrlFactory::create<LLConversationViewParticipant>(params);
}
-bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata)
+bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& userdata, bool is_self)
{
// only group moderators can perform actions related to this "enable callback"
if (!isGroupModerator())
@@ -1874,7 +1900,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user
{
return voice_channel;
}
- else if ("can_mute" == userdata)
+ else if (("can_mute" == userdata) && !is_self)
{
return voice_channel && !isMuted(getCurSelectedViewModelItem()->getUUID());
}
@@ -1884,7 +1910,7 @@ bool LLFloaterIMContainer::enableModerateContextMenuItem(const std::string& user
}
// The last invoke is used to check whether the "can_allow_text_chat" will enabled
- return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID());
+ return LLVoiceClient::getInstance()->isParticipantAvatar(getCurSelectedViewModelItem()->getUUID()) && !is_self;
}
bool LLFloaterIMContainer::isGroupModerator()
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 78b3572111..468b47f1f1 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -164,7 +164,7 @@ private:
void doToSelectedGroup(const LLSD& userdata);
static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response);
- bool enableModerateContextMenuItem(const std::string& userdata);
+ bool enableModerateContextMenuItem(const std::string& userdata, bool is_self = false);
LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp);
LLSpeakerMgr * getSpeakerMgrForSelectedParticipant();
bool isGroupModerator();
@@ -181,6 +181,7 @@ private:
bool isParticipantListExpanded();
void idleUpdate(); // for convenience (self) from static idle
+ void idleProcessEvents();
LLButton* mExpandCollapseBtn;
LLButton* mStubCollapseBtn;
@@ -220,6 +221,7 @@ private:
LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
bool onConversationModelEvent(const LLSD& event);
+ void handleConversationModelEvent(const LLSD& event);
// Conversation list data
LLPanel* mConversationsListPanel; // This is the main widget we add conversation widget to
@@ -229,6 +231,8 @@ private:
LLFolderView* mConversationsRoot;
LLEventStream mConversationsEventStream;
+ std::deque<LLSD> mConversationEventQueue;
+
LLTimer mParticipantRefreshTimer;
};
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 3aee08482b..d604d0a789 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -465,9 +465,10 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args)
}
}
-
+static LLTrace::BlockTimerStatHandle FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT("Build Conversation View");
void LLFloaterIMSessionTab::buildConversationViewParticipant()
{
+ LL_RECORD_BLOCK_TIME(FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT);
// Clear the widget list since we are rebuilding afresh from the model
conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
while (widget_it != mConversationsWidgets.end())
@@ -496,14 +497,20 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
}
}
-void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model)
+void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model, bool update_view)
{
+ if (!participant_model)
+ {
+ // Nothing to do if the model is inexistent
+ return;
+ }
+
// Check if the model already has an associated view
LLUUID uuid = participant_model->getUUID();
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
// If not already present, create the participant view and attach it to the root, otherwise, just refresh it
- if (widget)
+ if (widget && update_view)
{
updateConversationViewParticipant(uuid); // overkill?
}
@@ -524,8 +531,8 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
{
mConversationsRoot->extractItem(widget);
delete widget;
- mConversationsWidgets.erase(participant_id);
}
+ mConversationsWidgets.erase(participant_id);
}
void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& participant_id)
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 1b4922fd73..5357a14ab9 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -84,7 +84,7 @@ public:
/*virtual*/ void setFocus(BOOL focus);
// Handle the left hand participant list widgets
- void addConversationViewParticipant(LLConversationItem* item);
+ void addConversationViewParticipant(LLConversationItem* item, bool update_view = true);
void removeConversationViewParticipant(const LLUUID& participant_id);
void updateConversationViewParticipant(const LLUUID& participant_id);
void refreshConversation();
diff --git a/indra/newview/llfloaterloadprefpreset.cpp b/indra/newview/llfloaterloadprefpreset.cpp
index fa17a9d40e..f89daf3e04 100644
--- a/indra/newview/llfloaterloadprefpreset.cpp
+++ b/indra/newview/llfloaterloadprefpreset.cpp
@@ -66,6 +66,11 @@ void LLFloaterLoadPrefPreset::onOpen(const LLSD& key)
EDefaultOptions option = DEFAULT_TOP;
LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, combo, option);
+ std::string preset_graphic_active = gSavedSettings.getString("PresetGraphicActive");
+ if (!preset_graphic_active.empty())
+ {
+ combo->setSimple(preset_graphic_active);
+ }
}
void LLFloaterLoadPrefPreset::onPresetsListChange()
@@ -74,6 +79,11 @@ void LLFloaterLoadPrefPreset::onPresetsListChange()
EDefaultOptions option = DEFAULT_TOP;
LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, combo, option);
+ std::string preset_graphic_active = gSavedSettings.getString("PresetGraphicActive");
+ if (!preset_graphic_active.empty())
+ {
+ combo->setSimple(preset_graphic_active);
+ }
}
void LLFloaterLoadPrefPreset::onBtnCancel()
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index bc44e37c5a..b9c03f66a3 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -27,7 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "llmodelloader.h"
-#include "lldaeloader.h"
+#include "llmodelpreview.h"
#include "llfloatermodelpreview.h"
@@ -40,15 +40,7 @@
#include "llagent.h"
#include "llbutton.h"
#include "llcombobox.h"
-#include "lldatapacker.h"
-#include "lldrawable.h"
-#include "llrender.h"
-#include "llface.h"
#include "llfocusmgr.h"
-#include "llfloaterperms.h"
-#include "lliconctrl.h"
-#include "llmatrix4a.h"
-#include "llmenubutton.h"
#include "llmeshrepository.h"
#include "llnotificationsutil.h"
#include "llsdutil_math.h"
@@ -56,44 +48,26 @@
#include "lltextbox.h"
#include "lltoolmgr.h"
#include "llui.h"
-#include "llvector4a.h"
-#include "llviewercamera.h"
#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llvoavatarself.h"
#include "pipeline.h"
-#include "lluictrlfactory.h"
#include "llviewercontrol.h"
-#include "llviewermenu.h"
-#include "llviewermenufile.h"
-#include "llviewerregion.h"
-#include "llviewertexturelist.h"
+#include "llviewermenufile.h" //LLFilePickerThread
#include "llstring.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
-#include "llradiogroup.h"
-#include "llsdserialize.h"
#include "llsliderctrl.h"
#include "llspinctrl.h"
-#include "lltoggleablemenu.h"
+#include "lltabcontainer.h"
#include "lltrans.h"
-#include "llvfile.h"
-#include "llvfs.h"
#include "llcallbacklist.h"
-#include "llviewerobjectlist.h"
-#include "llanimationstates.h"
+#include "llviewertexteditor.h"
#include "llviewernetwork.h"
-#include "llviewershadermgr.h"
-#include "glod/glod.h"
-#include <boost/algorithm/string.hpp>
//static
S32 LLFloaterModelPreview::sUploadAmount = 10;
LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL;
-bool LLModelPreview::sIgnoreLoadedCallback = false;
-
// "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01
// But according to the UI spec for upload model floater, this parameter
// should be represented by Retain spinner with values from 1 to 100 by 1.
@@ -106,114 +80,20 @@ const double RETAIN_COEFFICIENT = 100;
// should be represented by Smooth combobox with only 10 values.
// So this const is used as a size of Smooth combobox list.
const S32 SMOOTH_VALUES_NUMBER = 10;
+const S32 PREVIEW_RENDER_SIZE = 1024;
+const F32 PREVIEW_CAMERA_DISTANCE = 16.f;
-// mCameraDistance
-// Also see: mCameraZoom
-const F32 MODEL_PREVIEW_CAMERA_DISTANCE = 16.f;
-
-void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
-
-
-std::string lod_name[NUM_LOD+1] =
-{
- "lowest",
- "low",
- "medium",
- "high",
- "I went off the end of the lod_name array. Me so smart."
-};
-
-std::string lod_triangles_name[NUM_LOD+1] =
-{
- "lowest_triangles",
- "low_triangles",
- "medium_triangles",
- "high_triangles",
- "I went off the end of the lod_triangles_name array. Me so smart."
-};
-
-std::string lod_vertices_name[NUM_LOD+1] =
+class LLMeshFilePicker : public LLFilePickerThread
{
- "lowest_vertices",
- "low_vertices",
- "medium_vertices",
- "high_vertices",
- "I went off the end of the lod_vertices_name array. Me so smart."
-};
+public:
+ LLMeshFilePicker(LLModelPreview* mp, S32 lod);
+ virtual void notify(const std::vector<std::string>& filenames);
-std::string lod_status_name[NUM_LOD+1] =
-{
- "lowest_status",
- "low_status",
- "medium_status",
- "high_status",
- "I went off the end of the lod_status_name array. Me so smart."
+private:
+ LLModelPreview* mMP;
+ S32 mLOD;
};
-std::string lod_icon_name[NUM_LOD+1] =
-{
- "status_icon_lowest",
- "status_icon_low",
- "status_icon_medium",
- "status_icon_high",
- "I went off the end of the lod_status_name array. Me so smart."
-};
-
-std::string lod_status_image[NUM_LOD+1] =
-{
- "ModelImport_Status_Good",
- "ModelImport_Status_Warning",
- "ModelImport_Status_Error",
- "I went off the end of the lod_status_image array. Me so smart."
-};
-
-std::string lod_label_name[NUM_LOD+1] =
-{
- "lowest_label",
- "low_label",
- "medium_label",
- "high_label",
- "I went off the end of the lod_label_name array. Me so smart."
-};
-
-BOOL stop_gloderror()
-{
- GLuint error = glodGetError();
-
- if (error != GLOD_NO_ERROR)
- {
- LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL;
- return TRUE;
- }
-
- return FALSE;
-}
-
-LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)
-{
- LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW);
-
- if (texture)
- {
- if (texture->getDiscardLevel() > -1)
- {
- gGL.getTexUnit(0)->bind(texture, true);
- return texture;
- }
- }
-
- return NULL;
-}
-
-std::string stripSuffix(std::string name)
-{
- if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1))
- {
- return name.substr(0, name.rfind('_'));
- }
- return name;
-}
-
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
{
@@ -234,37 +114,16 @@ void LLMeshFilePicker::notify(const std::vector<std::string>& filenames)
}
}
-void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
-{
- LLModelLoader::scene::iterator base_iter = scene.begin();
- bool found = false;
- while (!found && (base_iter != scene.end()))
- {
- matOut = base_iter->first;
-
- LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin();
- while (!found && (base_instance_iter != base_iter->second.end()))
- {
- LLModelInstance& base_instance = *base_instance_iter++;
- LLModel* base_model = base_instance.mModel;
-
- if (base_model && (base_model->mLabel == name_to_match))
- {
- baseModelOut = base_model;
- return;
- }
- }
- base_iter++;
- }
-}
-
//-----------------------------------------------------------------------------
// LLFloaterModelPreview()
//-----------------------------------------------------------------------------
LLFloaterModelPreview::LLFloaterModelPreview(const LLSD& key) :
LLFloaterModelUploadBase(key),
mUploadBtn(NULL),
-mCalculateBtn(NULL)
+mCalculateBtn(NULL),
+mUploadLogText(NULL),
+mTabContainer(NULL),
+mAvatarTabIndex(0)
{
sInstance = this;
mLastMouseX = 0;
@@ -307,10 +166,11 @@ BOOL LLFloaterModelPreview::postBuild()
getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLODParamCommit, this, lod, true));
}
- childSetCommitCallback("upload_skin", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
- childSetCommitCallback("upload_joints", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
- childSetCommitCallback("lock_scale_if_joint_position", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
- childSetCommitCallback("upload_textures", boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this), NULL);
+ // Upload/avatar options, they need to refresh errors/notifications
+ childSetCommitCallback("upload_skin", boost::bind(&LLFloaterModelPreview::onUploadOptionChecked, this, _1), NULL);
+ childSetCommitCallback("upload_joints", boost::bind(&LLFloaterModelPreview::onUploadOptionChecked, this, _1), NULL);
+ childSetCommitCallback("lock_scale_if_joint_position", boost::bind(&LLFloaterModelPreview::onUploadOptionChecked, this, _1), NULL);
+ childSetCommitCallback("upload_textures", boost::bind(&LLFloaterModelPreview::onUploadOptionChecked, this, _1), NULL);
childSetTextArg("status", "[STATUS]", getString("status_idle"));
@@ -321,10 +181,6 @@ BOOL LLFloaterModelPreview::postBuild()
childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this);
- childSetCommitCallback("upload_skin", onUploadSkinCommit, this);
- childSetCommitCallback("upload_joints", onUploadJointsCommit, this);
- childSetCommitCallback("lock_scale_if_joint_position", onUploadJointsCommit, this);
-
childSetCommitCallback("import_scale", onImportScaleCommit, this);
childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this);
@@ -333,13 +189,20 @@ BOOL LLFloaterModelPreview::postBuild()
getChild<LLCheckBoxCtrl>("show_edges")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
getChild<LLCheckBoxCtrl>("show_physics")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
getChild<LLCheckBoxCtrl>("show_textures")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
- getChild<LLCheckBoxCtrl>("show_skin_weight")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
+ getChild<LLCheckBoxCtrl>("show_skin_weight")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onShowSkinWeightChecked, this, _1));
+ getChild<LLCheckBoxCtrl>("show_joint_overrides")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
getChild<LLCheckBoxCtrl>("show_joint_positions")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _1));
childDisable("upload_skin");
childDisable("upload_joints");
childDisable("lock_scale_if_joint_position");
+ childSetVisible("skin_too_many_joints", false);
+ childSetVisible("skin_unknown_joint", false);
+
+ childSetVisible("warning_title", false);
+ childSetVisible("warning_message", false);
+
initDecompControls();
LLView* preview_panel = getChild<LLView>("preview_panel");
@@ -395,6 +258,12 @@ BOOL LLFloaterModelPreview::postBuild()
mUploadBtn = getChild<LLButton>("ok_btn");
mCalculateBtn = getChild<LLButton>("calculate_btn");
+ mUploadLogText = getChild<LLViewerTextEditor>("log_text");
+ mTabContainer = getChild<LLTabContainer>("import_tab");
+
+ LLPanel *panel = mTabContainer->getPanelByName("rigging_panel");
+ mAvatarTabIndex = mTabContainer->getIndexForPanel(panel);
+ panel->getChild<LLScrollListCtrl>("joints_list")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onJointListSelection, this));
if (LLConvexDecomposition::getInstance() != NULL)
{
@@ -411,6 +280,24 @@ BOOL LLFloaterModelPreview::postBuild()
}
//-----------------------------------------------------------------------------
+// reshape()
+//-----------------------------------------------------------------------------
+
+void LLFloaterModelPreview::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLFloaterModelUploadBase::reshape(width, height, called_from_parent);
+
+ LLView* preview_panel = getChild<LLView>("preview_panel");
+ LLRect rect = preview_panel->getRect();
+
+ if (rect != mPreviewRect)
+ {
+ mModelPreview->refresh();
+ mPreviewRect = preview_panel->getRect();
+ }
+}
+
+//-----------------------------------------------------------------------------
// LLFloaterModelPreview()
//-----------------------------------------------------------------------------
LLFloaterModelPreview::~LLFloaterModelPreview()
@@ -433,18 +320,95 @@ void LLFloaterModelPreview::initModelPreview()
delete mModelPreview;
}
- mModelPreview = new LLModelPreview(512, 512, this );
- mModelPreview->setPreviewTarget(MODEL_PREVIEW_CAMERA_DISTANCE);
+ S32 tex_width = 512;
+ S32 tex_height = 512;
+
+ S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenWidth);
+ S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenHeight);
+
+ while ((tex_width << 1) < max_width)
+ {
+ tex_width <<= 1;
+ }
+ while ((tex_height << 1) < max_height)
+ {
+ tex_height <<= 1;
+ }
+
+ mModelPreview = new LLModelPreview(tex_width, tex_height, this);
+ mModelPreview->setPreviewTarget(PREVIEW_CAMERA_DISTANCE);
mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::modelUpdated, this, _1));
}
+void LLFloaterModelPreview::onUploadOptionChecked(LLUICtrl* ctrl)
+{
+ if (mModelPreview)
+ {
+ auto name = ctrl->getName();
+ bool value = ctrl->getValue().asBoolean();
+ // update the option and notifications
+ // (this is a bit convoluted, because of the current structure of mModelPreview)
+ if (name == "upload_skin")
+ {
+ childSetValue("show_skin_weight", value);
+ mModelPreview->mViewOption["show_skin_weight"] = value;
+ if (!value)
+ {
+ mModelPreview->mViewOption["show_joint_overrides"] = false;
+ mModelPreview->mViewOption["show_joint_positions"] = false;
+ childSetValue("show_joint_overrides", false);
+ childSetValue("show_joint_positions", false);
+ }
+ }
+ else if (name == "upload_joints")
+ {
+ if (mModelPreview->mViewOption["show_skin_weight"])
+ {
+ childSetValue("show_joint_overrides", value);
+ mModelPreview->mViewOption["show_joint_overrides"] = value;
+ }
+ }
+ else if (name == "upload_textures")
+ {
+ childSetValue("show_textures", value);
+ mModelPreview->mViewOption["show_textures"] = value;
+ }
+ else if (name == "lock_scale_if_joint_position")
+ {
+ mModelPreview->mViewOption["lock_scale_if_joint_position"] = value;
+ }
+
+ mModelPreview->refresh(); // a 'dirty' flag for render
+ mModelPreview->resetPreviewTarget();
+ mModelPreview->clearBuffers();
+ mModelPreview->mDirty = true;
+ }
+ // set the button visible, it will be refreshed later
+ toggleCalculateButton(true);
+}
+
+void LLFloaterModelPreview::onShowSkinWeightChecked(LLUICtrl* ctrl)
+{
+ if (mModelPreview)
+ {
+ mModelPreview->mCameraOffset.clearVec();
+ onViewOptionChecked(ctrl);
+ }
+}
+
void LLFloaterModelPreview::onViewOptionChecked(LLUICtrl* ctrl)
{
if (mModelPreview)
{
- mModelPreview->mViewOption[ctrl->getName()] = !mModelPreview->mViewOption[ctrl->getName()];
-
+ auto name = ctrl->getName();
+ mModelPreview->mViewOption[name] = !mModelPreview->mViewOption[name];
+ if (name == "show_physics")
+ {
+ auto enabled = mModelPreview->mViewOption[name];
+ childSetEnabled("physics_explode", enabled);
+ childSetVisible("physics_explode", enabled);
+ }
mModelPreview->refresh();
}
}
@@ -479,6 +443,12 @@ void LLFloaterModelPreview::disableViewOption(const std::string& option)
setViewOptionEnabled(option, false);
}
+void LLFloaterModelPreview::loadHighLodModel()
+{
+ mModelPreview->mLookUpLodFiles = true;
+ loadModel(3);
+}
+
void LLFloaterModelPreview::loadModel(S32 lod)
{
mModelPreview->mLoading = true;
@@ -500,19 +470,14 @@ void LLFloaterModelPreview::loadModel(S32 lod, const std::string& file_name, boo
void LLFloaterModelPreview::onClickCalculateBtn()
{
+ clearLogTab();
+ addStringToLog("Calculating model data.", false);
mModelPreview->rebuildUploadData();
bool upload_skinweights = childGetValue("upload_skin").asBoolean();
bool upload_joint_positions = childGetValue("upload_joints").asBoolean();
bool lock_scale_if_joint_position = childGetValue("lock_scale_if_joint_position").asBoolean();
- if (upload_joint_positions)
- {
- // Diagnostic message showing list of joints for which joint offsets are defined.
- // FIXME - given time, would be much better to put this in the UI, in updateStatusMessages().
- mModelPreview->getPreviewAvatar()->showAttachmentOverrides();
- }
-
mUploadModelUrl.clear();
mModelPhysicsFee.clear();
@@ -526,6 +491,132 @@ void LLFloaterModelPreview::onClickCalculateBtn()
mUploadBtn->setEnabled(false);
}
+// Modified cell_params, make sure to clear values if you have to reuse cell_params outside of this function
+void add_row_to_list(LLScrollListCtrl *listp,
+ LLScrollListCell::Params &cell_params,
+ const LLSD &item_value,
+ const std::string &name,
+ const LLSD &vx,
+ const LLSD &vy,
+ const LLSD &vz)
+{
+ LLScrollListItem::Params item_params;
+ item_params.value = item_value;
+
+ cell_params.column = "model_name";
+ cell_params.value = name;
+
+ item_params.columns.add(cell_params);
+
+ cell_params.column = "axis_x";
+ cell_params.value = vx;
+ item_params.columns.add(cell_params);
+
+ cell_params.column = "axis_y";
+ cell_params.value = vy;
+ item_params.columns.add(cell_params);
+
+ cell_params.column = "axis_z";
+ cell_params.value = vz;
+
+ item_params.columns.add(cell_params);
+
+ listp->addRow(item_params);
+}
+
+void populate_list_with_overrides(LLScrollListCtrl *listp, const LLJointOverrideData &data, bool include_overrides)
+{
+ if (data.mModelsNoOverrides.empty() && data.mPosOverrides.empty())
+ {
+ return;
+ }
+
+ static const std::string no_override_placeholder = "-";
+
+ S32 count = 0;
+ LLScrollListCell::Params cell_params;
+ cell_params.font = LLFontGL::getFontSansSerif();
+ // Start out right justifying numeric displays
+ cell_params.font_halign = LLFontGL::HCENTER;
+
+ std::map<std::string, LLVector3>::const_iterator map_iter = data.mPosOverrides.begin();
+ std::map<std::string, LLVector3>::const_iterator map_end = data.mPosOverrides.end();
+ while (map_iter != map_end)
+ {
+ if (include_overrides)
+ {
+ add_row_to_list(listp,
+ cell_params,
+ LLSD::Integer(count),
+ map_iter->first,
+ LLSD::Real(map_iter->second.mV[VX]),
+ LLSD::Real(map_iter->second.mV[VY]),
+ LLSD::Real(map_iter->second.mV[VZ]));
+ }
+ else
+ {
+ add_row_to_list(listp,
+ cell_params,
+ LLSD::Integer(count),
+ map_iter->first,
+ no_override_placeholder,
+ no_override_placeholder,
+ no_override_placeholder);
+ }
+ count++;
+ map_iter++;
+ }
+
+ std::set<std::string>::const_iterator set_iter = data.mModelsNoOverrides.begin();
+ std::set<std::string>::const_iterator set_end = data.mModelsNoOverrides.end();
+ while (set_iter != set_end)
+ {
+ add_row_to_list(listp,
+ cell_params,
+ LLSD::Integer(count),
+ *set_iter,
+ no_override_placeholder,
+ no_override_placeholder,
+ no_override_placeholder);
+ count++;
+ set_iter++;
+ }
+}
+
+void LLFloaterModelPreview::onJointListSelection()
+{
+ S32 display_lod = mModelPreview->mPreviewLOD;
+ LLPanel *panel = mTabContainer->getPanelByName("rigging_panel");
+ LLScrollListCtrl *joints_list = panel->getChild<LLScrollListCtrl>("joints_list");
+ LLScrollListCtrl *joints_pos = panel->getChild<LLScrollListCtrl>("pos_overrides_list");
+ LLScrollListCtrl *joints_scale = panel->getChild<LLScrollListCtrl>("scale_overrides_list");
+ LLTextBox *joint_pos_descr = panel->getChild<LLTextBox>("pos_overrides_descr");
+
+ joints_pos->deleteAllItems();
+ joints_scale->deleteAllItems();
+
+ LLScrollListItem *selected = joints_list->getFirstSelected();
+ if (selected)
+ {
+ std::string label = selected->getValue().asString();
+ LLJointOverrideData &data = mJointOverrides[display_lod][label];
+ bool upload_joint_positions = childGetValue("upload_joints").asBoolean();
+ populate_list_with_overrides(joints_pos, data, upload_joint_positions);
+
+ joint_pos_descr->setTextArg("[JOINT]", label);
+ mSelectedJointName = label;
+ }
+ else
+ {
+ // temporary value (shouldn't happen)
+ std::string label = "mPelvis";
+ joint_pos_descr->setTextArg("[JOINT]", label);
+ mSelectedJointName.clear();
+ }
+
+ // Note: We can make a version of renderBones() to highlight selected joint
+}
+
void LLFloaterModelPreview::onDescriptionKeystroke(LLUICtrl* ctrl)
{
// Workaround for SL-4186, server doesn't allow name changes after 'calculate' stage
@@ -570,33 +661,6 @@ void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata )
}
//static
-void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*,void* userdata)
-{
- LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
-
- if (!fp->mModelPreview)
- {
- return;
- }
-
- fp->mModelPreview->refresh();
-}
-
-//static
-void LLFloaterModelPreview::onUploadSkinCommit(LLUICtrl*,void* userdata)
-{
- LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
-
- if (!fp->mModelPreview)
- {
- return;
- }
- fp->mModelPreview->refresh();
- fp->mModelPreview->resetPreviewTarget();
- fp->mModelPreview->clearBuffers();
-}
-
-//static
void LLFloaterModelPreview::onPreviewLODCommit(LLUICtrl* ctrl, void* userdata)
{
LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
@@ -626,6 +690,7 @@ void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl* ctrl, void* userda
void LLFloaterModelPreview::toggleGenarateNormals()
{
bool enabled = childGetValue("gen_normals").asBoolean();
+ mModelPreview->mViewOption["gen_normals"] = enabled;
childSetEnabled("crease_angle", enabled);
if(enabled) {
mModelPreview->generateNormals();
@@ -669,6 +734,27 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
}
}
+void LLFloaterModelPreview::draw3dPreview()
+{
+ gGL.color3f(1.f, 1.f, 1.f);
+
+ gGL.getTexUnit(0)->bind(mModelPreview);
+
+ gGL.begin( LLRender::QUADS );
+ {
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex2i(mPreviewRect.mLeft+1, mPreviewRect.mTop-1);
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex2i(mPreviewRect.mLeft+1, mPreviewRect.mBottom+1);
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex2i(mPreviewRect.mRight-1, mPreviewRect.mBottom+1);
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex2i(mPreviewRect.mRight-1, mPreviewRect.mTop-1);
+ }
+ gGL.end();
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+}
//-----------------------------------------------------------------------------
// draw()
@@ -715,36 +801,9 @@ void LLFloaterModelPreview::draw()
childSetTextArg("prim_cost", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost));
childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size()));
- if (mModelPreview->lodsReady())
+ if (!isMinimized() && mModelPreview->lodsReady())
{
- gGL.color3f(1.f, 1.f, 1.f);
-
- gGL.getTexUnit(0)->bind(mModelPreview);
-
-
- LLView* preview_panel = getChild<LLView>("preview_panel");
-
- LLRect rect = preview_panel->getRect();
- if (rect != mPreviewRect)
- {
- mModelPreview->refresh();
- mPreviewRect = preview_panel->getRect();
- }
-
- gGL.begin( LLRender::QUADS );
- {
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop-1);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2i(mPreviewRect.mRight-1, mPreviewRect.mBottom);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2i(mPreviewRect.mRight-1, mPreviewRect.mTop-1);
- }
- gGL.end();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ draw3dPreview();
}
}
@@ -843,8 +902,11 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
mModelPreview->zoom((F32)clicks * -0.2f);
mModelPreview->refresh();
}
-
- return TRUE;
+ else
+ {
+ LLFloaterModelUploadBase::handleScrollWheel(x, y, clicks);
+ }
+ return TRUE;
}
/*virtual*/
@@ -1104,7 +1166,8 @@ void LLFloaterModelPreview::initDecompControls()
float max = param[i].mDetails.mRange.mHigh.mFloat;
float delta = param[i].mDetails.mRange.mDelta.mFloat;
- if ("Cosine%" == name)
+ bool is_smooth_cb = ("Cosine%" == name);
+ if (is_smooth_cb)
{
createSmoothComboBox(combo_box, min, max);
}
@@ -1115,10 +1178,8 @@ void LLFloaterModelPreview::initDecompControls()
std::string label = llformat("%.1f", value);
combo_box->add(label, value, ADD_BOTTOM, true);
}
- combo_box->setValue(param[i].mDefault.mFloat);
-
}
-
+ combo_box->setValue(is_smooth_cb ? 0: param[i].mDefault.mFloat);
combo_box->setCommitCallback(onPhysicsParamCommit, (void*) &param[i]);
}
}
@@ -1190,7 +1251,7 @@ void LLFloaterModelPreview::initDecompControls()
//LL_INFOS() << "-----------------------------" << LL_ENDL;
}
}
-
+ mDefaultDecompParams = mDecompParams;
childSetCommitCallback("physics_explode", LLFloaterModelPreview::onExplodeCommit, this);
}
@@ -1220,3089 +1281,279 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
}
//-----------------------------------------------------------------------------
-// LLModelPreview
+// addStringToLog()
//-----------------------------------------------------------------------------
-
-LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
-: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex()
-, mLodsQuery()
-, mLodsWithParsingError()
-, mPelvisZOffset( 0.0f )
-, mLegacyRigValid( false )
-, mRigValidJointUpload( false )
-, mPhysicsSearchLOD( LLModel::LOD_PHYSICS )
-, mResetJoints( false )
-, mModelNoErrors( true )
-, mLastJointUpdate( false )
-{
- mNeedsUpdate = TRUE;
- mCameraDistance = 0.f;
- mCameraYaw = 0.f;
- mCameraPitch = 0.f;
- mCameraZoom = 1.f;
- mTextureName = 0;
- mPreviewLOD = 0;
- mModelLoader = NULL;
- mMaxTriangleLimit = 0;
- mDirty = false;
- mGenLOD = false;
- mLoading = false;
- mLoadState = LLModelLoader::STARTING;
- mGroup = 0;
- mLODFrozen = false;
- mBuildShareTolerance = 0.f;
- mBuildQueueMode = GLOD_QUEUE_GREEDY;
- mBuildBorderMode = GLOD_BORDER_UNLOCK;
- mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE;
-
- for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
- {
- mRequestedTriangleCount[i] = 0;
- mRequestedCreaseAngle[i] = -1.f;
- mRequestedLoDMode[i] = 0;
- mRequestedErrorThreshold[i] = 0.f;
- mRequestedBuildOperator[i] = 0;
- mRequestedQueueMode[i] = 0;
- mRequestedBorderMode[i] = 0;
- mRequestedShareTolerance[i] = 0.f;
- }
-
- mViewOption["show_textures"] = false;
-
- mFMP = fmp;
-
- mHasPivot = false;
- mModelPivot = LLVector3( 0.0f, 0.0f, 0.0f );
-
- glodInit();
-
- createPreviewAvatar();
-}
-
-LLModelPreview::~LLModelPreview()
-{
- // glod apparently has internal mem alignment issues that are angering
- // the heap-check code in windows, these should be hunted down in that
- // TP code, if possible
- //
- // kernel32.dll!HeapFree() + 0x14 bytes
- // msvcr100.dll!free(void * pBlock) Line 51 C
- // glod.dll!glodGetGroupParameteriv() + 0x119 bytes
- // glod.dll!glodShutdown() + 0x77 bytes
- //
- //glodShutdown();
- if(mModelLoader)
- {
- mModelLoader->shutdown();
- }
-}
-
-U32 LLModelPreview::calcResourceCost()
-{
- assert_main_thread();
-
- rebuildUploadData();
-
- //Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
- if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
- {
- bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
- if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
- {
- mFMP->childDisable("ok_btn");
- }
- }
-
- std::set<LLModel*> accounted;
- U32 num_points = 0;
- U32 num_hulls = 0;
-
- F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f;
- mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f;
-
- if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() )
- {
- // FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail.
- // see also call to addAttachmentPosOverride.
- LLUUID fake_mesh_id;
- fake_mesh_id.generate();
- getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id );
- }
-
- F32 streaming_cost = 0.f;
- F32 physics_cost = 0.f;
- for (U32 i = 0; i < mUploadData.size(); ++i)
- {
- LLModelInstance& instance = mUploadData[i];
-
- if (accounted.find(instance.mModel) == accounted.end())
- {
- accounted.insert(instance.mModel);
-
- LLModel::Decomposition& decomp =
- instance.mLOD[LLModel::LOD_PHYSICS] ?
- instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
- instance.mModel->mPhysics;
-
- //update instance skin info for each lods pelvisZoffset
- for ( int j=0; j<LLModel::NUM_LODS; ++j )
- {
- if ( instance.mLOD[j] )
- {
- instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset;
- }
- }
-
- std::stringstream ostr;
- LLSD ret = LLModel::writeModel(ostr,
- instance.mLOD[4],
- instance.mLOD[3],
- instance.mLOD[2],
- instance.mLOD[1],
- instance.mLOD[0],
- decomp,
- mFMP->childGetValue("upload_skin").asBoolean(),
- mFMP->childGetValue("upload_joints").asBoolean(),
- mFMP->childGetValue("lock_scale_if_joint_position").asBoolean(),
- TRUE,
- FALSE,
- instance.mModel->mSubmodelID);
-
- num_hulls += decomp.mHull.size();
- for (U32 i = 0; i < decomp.mHull.size(); ++i)
- {
- num_points += decomp.mHull[i].size();
- }
-
- //calculate streaming cost
- LLMatrix4 transformation = instance.mTransform;
-
- LLVector3 position = LLVector3(0, 0, 0) * transformation;
-
- LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position;
- LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position;
- LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position;
- F32 x_length = x_transformed.normalize();
- F32 y_length = y_transformed.normalize();
- F32 z_length = z_transformed.normalize();
- LLVector3 scale = LLVector3(x_length, y_length, z_length);
-
- F32 radius = scale.length()*0.5f*debug_scale;
-
- LLMeshCostData costs;
- if (gMeshRepo.getCostData(ret, costs))
- {
- streaming_cost += costs.getRadiusBasedStreamingCost(radius);
- }
- }
- }
-
- F32 scale = mFMP ? mFMP->childGetValue("import_scale").asReal()*2.f : 2.f;
-
- mDetailsSignal(mPreviewScale[0]*scale, mPreviewScale[1]*scale, mPreviewScale[2]*scale, streaming_cost, physics_cost);
-
- updateStatusMessages();
-
- return (U32) streaming_cost;
-}
-
-void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
-{
- assert_main_thread();
- childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
- childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
- childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
-}
-
-void LLFloaterModelPreview::setPreviewLOD(S32 lod)
-{
- if (mModelPreview)
- {
- mModelPreview->setPreviewLOD(lod);
- }
-}
-
-
-void LLModelPreview::rebuildUploadData()
-{
- assert_main_thread();
-
- mUploadData.clear();
- mTextureSet.clear();
-
- //fill uploaddata instance vectors from scene data
-
- std::string requested_name = mFMP->getChild<LLUICtrl>("description_form")->getValue().asString();
-
- LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");
-
- F32 scale = scale_spinner->getValue().asReal();
-
- LLMatrix4 scale_mat;
- scale_mat.initScale(LLVector3(scale, scale, scale));
-
- F32 max_scale = 0.f;
-
- BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
- BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
-
- for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
- { //for each transform in scene
- LLMatrix4 mat = iter->first;
-
- // compute position
- LLVector3 position = LLVector3(0, 0, 0) * mat;
-
- // compute scale
- LLVector3 x_transformed = LLVector3(1, 0, 0) * mat - position;
- LLVector3 y_transformed = LLVector3(0, 1, 0) * mat - position;
- LLVector3 z_transformed = LLVector3(0, 0, 1) * mat - position;
- F32 x_length = x_transformed.normalize();
- F32 y_length = y_transformed.normalize();
- F32 z_length = z_transformed.normalize();
-
- max_scale = llmax(llmax(llmax(max_scale, x_length), y_length), z_length);
-
- mat *= scale_mat;
-
- for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();)
- { //for each instance with said transform applied
- LLModelInstance instance = *model_iter++;
-
- LLModel* base_model = instance.mModel;
-
- if (base_model && !requested_name.empty())
- {
- base_model->mRequestedLabel = requested_name;
- }
-
- for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--)
- {
- LLModel* lod_model = NULL;
- if (!legacyMatching)
- {
- // Fill LOD slots by finding matching meshes by label with name extensions
- // in the appropriate scene for each LOD. This fixes all kinds of issues
- // where the indexed method below fails in spectacular fashion.
- // If you don't take the time to name your LOD and PHYS meshes
- // with the name of their corresponding mesh in the HIGH LOD,
- // then the indexed method will be attempted below.
-
- LLMatrix4 transform;
-
- std::string name_to_match = instance.mLabel;
- llassert(!name_to_match.empty());
-
- int extensionLOD;
- if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty())
- {
- extensionLOD = i;
- }
- else
- {
- //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
- extensionLOD = mPhysicsSearchLOD;
- }
-
- std::string toAdd;
- switch (extensionLOD)
- {
- case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break;
- case LLModel::LOD_LOW: toAdd = "_LOD1"; break;
- case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break;
- case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break;
- case LLModel::LOD_HIGH: break;
- }
-
- if (name_to_match.find(toAdd) == -1)
- {
- name_to_match += toAdd;
- }
-
- FindModel(mScene[i], name_to_match, lod_model, transform);
-
- if (!lod_model && i != LLModel::LOD_PHYSICS)
- {
- if (importerDebug)
- {
- LL_INFOS() << "Search of" << name_to_match << " in LOD" << i << " list failed. Searching for alternative among LOD lists." << LL_ENDL;
- }
-
- int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
- while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
- {
- std::string name_to_match = instance.mLabel;
- llassert(!name_to_match.empty());
-
- std::string toAdd;
- switch (searchLOD)
- {
- case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break;
- case LLModel::LOD_LOW: toAdd = "_LOD1"; break;
- case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break;
- case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break;
- case LLModel::LOD_HIGH: break;
- }
-
- if (name_to_match.find(toAdd) == -1)
- {
- name_to_match += toAdd;
- }
-
- // See if we can find an appropriately named model in LOD 'searchLOD'
- //
- FindModel(mScene[searchLOD], name_to_match, lod_model, transform);
- searchLOD++;
- }
- }
- }
- else
- {
- // Use old method of index-based association
- U32 idx = 0;
- for (idx = 0; idx < mBaseModel.size(); ++idx)
- {
- // find reference instance for this model
- if (mBaseModel[idx] == base_model)
- {
- if (importerDebug)
- {
- LL_INFOS() << "Attempting to use model index " << idx << " for LOD " << i << " of " << instance.mLabel << LL_ENDL;
- }
- break;
- }
- }
-
- // If the model list for the current LOD includes that index...
- //
- if (mModel[i].size() > idx)
- {
- // Assign that index from the model list for our LOD as the LOD model for this instance
- //
- lod_model = mModel[i][idx];
- if (importerDebug)
- {
- LL_INFOS() << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel << LL_ENDL;
- }
- }
- else if (importerDebug)
- {
- LL_INFOS() << "List of models does not include index " << idx << LL_ENDL;
- }
- }
-
- if (lod_model)
- {
- if (importerDebug)
- {
- if (i == LLModel::LOD_PHYSICS)
- {
- LL_INFOS() << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << LL_ENDL;
- }
- }
- instance.mLOD[i] = lod_model;
- }
- else
- {
- if (i < LLModel::LOD_HIGH && !lodsReady())
- {
- // assign a placeholder from previous LOD until lod generation is complete.
- // Note: we might need to assign it regardless of conditions like named search does, to prevent crashes.
- instance.mLOD[i] = instance.mLOD[i + 1];
- }
- if (importerDebug)
- {
- LL_INFOS() << "List of models does not include " << instance.mLabel << LL_ENDL;
- }
- }
- }
-
- LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH];
- if (!high_lod_model)
- {
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- }
- else
- {
- for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
- {
- int refFaceCnt = 0;
- int modelFaceCnt = 0;
- llassert(instance.mLOD[i]);
- if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) )
- {
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- }
- }
- LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) mFMP;
- bool upload_skinweights = fmp && fmp->childGetValue("upload_skin").asBoolean();
- if (upload_skinweights && high_lod_model->mSkinInfo.mJointNames.size() > 0)
- {
- LLQuaternion bind_rot = LLSkinningUtil::getUnscaledQuaternion(high_lod_model->mSkinInfo.mBindShapeMatrix);
- LLQuaternion identity;
- if (!bind_rot.isEqualEps(identity,0.01))
- {
- LL_WARNS() << "non-identity bind shape rot. mat is " << high_lod_model->mSkinInfo.mBindShapeMatrix
- << " bind_rot " << bind_rot << LL_ENDL;
- setLoadState( LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION );
- }
- }
- }
- instance.mTransform = mat;
- mUploadData.push_back(instance);
- }
- }
-
- for (U32 lod = 0; lod < LLModel::NUM_LODS-1; lod++)
- {
- // Search for models that are not included into upload data
- // If we found any, that means something we loaded is not a sub-model.
- for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind)
- {
- bool found_model = false;
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
- if (instance.mLOD[lod] == mModel[lod][model_ind])
- {
- found_model = true;
- break;
- }
- }
- if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID)
- {
- if (importerDebug)
- {
- LL_INFOS() << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models." << LL_ENDL;
- }
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- }
- }
- }
-
- F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale;
-
- F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]);
- max_axis = llmax(max_axis, mPreviewScale.mV[2]);
- max_axis *= 2.f;
-
- //clamp scale so that total imported model bounding box is smaller than 240m on a side
- max_import_scale = llmin(max_import_scale, 240.f/max_axis);
-
- scale_spinner->setMaxValue(max_import_scale);
-
- if (max_import_scale < scale)
- {
- scale_spinner->setValue(max_import_scale);
- }
-
-}
-
-void LLModelPreview::saveUploadData(bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position)
+//static
+void LLFloaterModelPreview::addStringToLog(const std::string& message, const LLSD& args, bool flash, S32 lod)
{
- if (!mLODFile[LLModel::LOD_HIGH].empty())
- {
- std::string filename = mLODFile[LLModel::LOD_HIGH];
- std::string slm_filename;
-
- if (LLModelLoader::getSLMFilename(filename, slm_filename))
+ if (sInstance && sInstance->hasString(message))
+ {
+ std::string str;
+ switch (lod)
{
- saveUploadData(slm_filename, save_skinweights, save_joint_positions, lock_scale_if_joint_position);
- }
- }
-}
-
-void LLModelPreview::saveUploadData(const std::string& filename,
- bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position)
-{
-
- std::set<LLPointer<LLModel> > meshes;
- std::map<LLModel*, std::string> mesh_binary;
-
- LLModel::hull empty_hull;
-
- LLSD data;
-
- data["version"] = SLM_SUPPORTED_VERSION;
- if (!mBaseModel.empty())
- {
- data["name"] = mBaseModel[0]->getName();
- }
-
- S32 mesh_id = 0;
-
- //build list of unique models and initialize local id
- for (U32 i = 0; i < mUploadData.size(); ++i)
- {
- LLModelInstance& instance = mUploadData[i];
-
- if (meshes.find(instance.mModel) == meshes.end())
- {
- instance.mModel->mLocalID = mesh_id++;
- meshes.insert(instance.mModel);
-
- std::stringstream str;
- LLModel::Decomposition& decomp =
- instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?
- instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
- instance.mModel->mPhysics;
-
- LLModel::writeModel(str,
- instance.mLOD[LLModel::LOD_PHYSICS],
- instance.mLOD[LLModel::LOD_HIGH],
- instance.mLOD[LLModel::LOD_MEDIUM],
- instance.mLOD[LLModel::LOD_LOW],
- instance.mLOD[LLModel::LOD_IMPOSTOR],
- decomp,
- save_skinweights,
- save_joint_positions,
- lock_scale_if_joint_position,
- FALSE, TRUE, instance.mModel->mSubmodelID);
-
- data["mesh"][instance.mModel->mLocalID] = str.str();
- }
-
- data["instance"][i] = instance.asLLSD();
- }
-
- llofstream out(filename.c_str(), std::ios_base::out | std::ios_base::binary);
- LLSDSerialize::toBinary(data, out);
- out.flush();
- out.close();
-}
-
-void LLModelPreview::clearModel(S32 lod)
-{
- if (lod < 0 || lod > LLModel::LOD_PHYSICS)
- {
- return;
- }
-
- mVertexBuffer[lod].clear();
- mModel[lod].clear();
- mScene[lod].clear();
+ case LLModel::LOD_IMPOSTOR: str = "LOD0 "; break;
+ case LLModel::LOD_LOW: str = "LOD1 "; break;
+ case LLModel::LOD_MEDIUM: str = "LOD2 "; break;
+ case LLModel::LOD_PHYSICS: str = "PHYS "; break;
+ case LLModel::LOD_HIGH: str = "LOD3 "; break;
+ default: break;
+ }
+
+ LLStringUtil::format_map_t args_msg;
+ LLSD::map_const_iterator iter = args.beginMap();
+ LLSD::map_const_iterator end = args.endMap();
+ for (; iter != end; ++iter)
+ {
+ args_msg[iter->first] = iter->second.asString();
+ }
+ str += sInstance->getString(message, args_msg);
+ sInstance->addStringToLogTab(str, flash);
+ }
}
-void LLModelPreview::getJointAliases( JointMap& joint_map)
+// static
+void LLFloaterModelPreview::addStringToLog(const std::string& str, bool flash)
{
- // Get all standard skeleton joints from the preview avatar.
- LLVOAvatar *av = getPreviewAvatar();
-
- //Joint names and aliases come from avatar_skeleton.xml
-
- joint_map = av->getJointAliases();
-
- std::vector<std::string> cv_names, attach_names;
- av->getSortedJointNames(1, cv_names);
- av->getSortedJointNames(2, attach_names);
- for (std::vector<std::string>::iterator it = cv_names.begin(); it != cv_names.end(); ++it)
- {
- joint_map[*it] = *it;
- }
- for (std::vector<std::string>::iterator it = attach_names.begin(); it != attach_names.end(); ++it)
+ if (sInstance)
{
- joint_map[*it] = *it;
+ sInstance->addStringToLogTab(str, flash);
}
}
-void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm)
-{
- assert_main_thread();
-
- LLMutexLock lock(this);
-
- if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::NUM_LODS - 1)
- {
- LL_WARNS() << "Invalid level of detail: " << lod << LL_ENDL;
- assert(lod >= LLModel::LOD_IMPOSTOR && lod < LLModel::NUM_LODS);
- return;
- }
-
- // This triggers if you bring up the file picker and then hit CANCEL.
- // Just use the previous model (if any) and ignore that you brought up
- // the file picker.
-
- if (filename.empty())
- {
- if (mBaseModel.empty())
- {
- // this is the initial file picking. Close the whole floater
- // if we don't have a base model to show for high LOD.
- mFMP->closeFloater(false);
- }
- mLoading = false;
- return;
- }
-
- if (mModelLoader)
- {
- LL_WARNS() << "Incompleted model load operation pending." << LL_ENDL;
- return;
- }
-
- mLODFile[lod] = filename;
-
- if (lod == LLModel::LOD_HIGH)
- {
- clearGLODGroup();
- }
-
- std::map<std::string, std::string> joint_alias_map;
- getJointAliases(joint_alias_map);
-
- mModelLoader = new LLDAELoader(
- filename,
- lod,
- &LLModelPreview::loadedCallback,
- &LLModelPreview::lookupJointByName,
- &LLModelPreview::loadTextures,
- &LLModelPreview::stateChangedCallback,
- this,
- mJointTransformMap,
- mJointsFromNode,
- joint_alias_map,
- LLSkinningUtil::getMaxJointCount(),
- gSavedSettings.getU32("ImporterModelLimit"),
- gSavedSettings.getBOOL("ImporterPreprocessDAE"));
-
- if (force_disable_slm)
- {
- mModelLoader->mTrySLM = false;
- }
- else
- {
- // For MAINT-6647, we have set force_disable_slm to true,
- // which means this code path will never be taken. Trying to
- // re-use SLM files has never worked properly; in particular,
- // it tends to force the UI into strange checkbox options
- // which cannot be altered.
-
- //only try to load from slm if viewer is configured to do so and this is the
- //initial model load (not an LoD or physics shape)
- mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty();
- }
- mModelLoader->start();
-
- mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file"));
-
- setPreviewLOD(lod);
-
- if ( getLoadState() >= LLModelLoader::ERROR_PARSING )
- {
- mFMP->childDisable("ok_btn");
- mFMP->childDisable( "calculate_btn" );
- }
-
- if (lod == mPreviewLOD)
- {
- mFMP->childSetValue("lod_file_" + lod_name[lod], mLODFile[lod]);
- }
- else if (lod == LLModel::LOD_PHYSICS)
- {
- mFMP->childSetValue("physics_file", mLODFile[lod]);
- }
-
- mFMP->openFloater();
-}
-
-void LLModelPreview::setPhysicsFromLOD(S32 lod)
-{
- assert_main_thread();
-
- if (lod >= 0 && lod <= 3)
- {
- mPhysicsSearchLOD = lod;
- mModel[LLModel::LOD_PHYSICS] = mModel[lod];
- mScene[LLModel::LOD_PHYSICS] = mScene[lod];
- mLODFile[LLModel::LOD_PHYSICS].clear();
- mFMP->childSetValue("physics_file", mLODFile[LLModel::LOD_PHYSICS]);
- mVertexBuffer[LLModel::LOD_PHYSICS].clear();
- rebuildUploadData();
- refresh();
- updateStatusMessages();
- }
-}
-
-void LLModelPreview::clearIncompatible(S32 lod)
-{
- //Don't discard models if specified model is the physic rep
- if ( lod == LLModel::LOD_PHYSICS )
- {
- return;
- }
-
- // at this point we don't care about sub-models,
- // different amount of sub-models means face count mismatch, not incompatibility
- U32 lod_size = countRootModels(mModel[lod]);
- for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
- { //clear out any entries that aren't compatible with this model
- if (i != lod)
- {
- if (countRootModels(mModel[i]) != lod_size)
- {
- mModel[i].clear();
- mScene[i].clear();
- mVertexBuffer[i].clear();
-
- if (i == LLModel::LOD_HIGH)
- {
- mBaseModel = mModel[lod];
- clearGLODGroup();
- mBaseScene = mScene[lod];
- mVertexBuffer[5].clear();
- }
- }
- }
- }
-}
-
-void LLModelPreview::clearGLODGroup()
-{
- if (mGroup)
- {
- for (std::map<LLPointer<LLModel>, U32>::iterator iter = mObject.begin(); iter != mObject.end(); ++iter)
- {
- glodDeleteObject(iter->second);
- stop_gloderror();
- }
- mObject.clear();
-
- glodDeleteGroup(mGroup);
- stop_gloderror();
- mGroup = 0;
- }
-}
-
-void LLModelPreview::loadModelCallback(S32 loaded_lod)
-{
- assert_main_thread();
-
- LLMutexLock lock(this);
- if (!mModelLoader)
- {
- mLoading = false ;
- return;
- }
- if(getLoadState() >= LLModelLoader::ERROR_PARSING)
- {
- mLoading = false ;
- mModelLoader = NULL;
- mLodsWithParsingError.push_back(loaded_lod);
- return ;
- }
-
- mLodsWithParsingError.erase(std::remove(mLodsWithParsingError.begin(), mLodsWithParsingError.end(), loaded_lod), mLodsWithParsingError.end());
- if(mLodsWithParsingError.empty())
- {
- mFMP->childEnable( "calculate_btn" );
- }
-
- // Copy determinations about rig so UI will reflect them
- //
- setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
- setLegacyRigValid(mModelLoader->isLegacyRigValid());
-
- mModelLoader->loadTextures() ;
-
- if (loaded_lod == -1)
- { //populate all LoDs from model loader scene
- mBaseModel.clear();
- mBaseScene.clear();
-
- bool skin_weights = false;
- bool joint_positions = false;
- bool lock_scale_if_joint_position = false;
-
- for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
- { //for each LoD
-
- //clear scene and model info
- mScene[lod].clear();
- mModel[lod].clear();
- mVertexBuffer[lod].clear();
-
- if (mModelLoader->mScene.begin()->second[0].mLOD[lod].notNull())
- { //if this LoD exists in the loaded scene
-
- //copy scene to current LoD
- mScene[lod] = mModelLoader->mScene;
-
- //touch up copied scene to look like current LoD
- for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter)
- {
- LLModelLoader::model_instance_list& list = iter->second;
-
- for (LLModelLoader::model_instance_list::iterator list_iter = list.begin(); list_iter != list.end(); ++list_iter)
- {
- //override displayed model with current LoD
- list_iter->mModel = list_iter->mLOD[lod];
-
- if (!list_iter->mModel)
- {
- continue;
- }
-
- //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index)
- S32 idx = list_iter->mModel->mLocalID;
-
- if (mModel[lod].size() <= idx)
- { //stretch model list to fit model at given index
- mModel[lod].resize(idx+1);
- }
-
- mModel[lod][idx] = list_iter->mModel;
- if (!list_iter->mModel->mSkinWeights.empty())
- {
- skin_weights = true;
-
- if (!list_iter->mModel->mSkinInfo.mAlternateBindMatrix.empty())
- {
- joint_positions = true;
- }
- if (list_iter->mModel->mSkinInfo.mLockScaleIfJointPosition)
- {
- lock_scale_if_joint_position = true;
- }
- }
- }
- }
- }
- }
-
- if (mFMP)
- {
- LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) mFMP;
-
- if (skin_weights)
- { //enable uploading/previewing of skin weights if present in .slm file
- fmp->enableViewOption("show_skin_weight");
- mViewOption["show_skin_weight"] = true;
- fmp->childSetValue("upload_skin", true);
- }
-
- if (joint_positions)
- {
- fmp->enableViewOption("show_joint_positions");
- mViewOption["show_joint_positions"] = true;
- fmp->childSetValue("upload_joints", true);
- }
-
- if (lock_scale_if_joint_position)
- {
- fmp->enableViewOption("lock_scale_if_joint_position");
- mViewOption["lock_scale_if_joint_position"] = true;
- fmp->childSetValue("lock_scale_if_joint_position", true);
- }
- }
-
- //copy high lod to base scene for LoD generation
- mBaseScene = mScene[LLModel::LOD_HIGH];
- mBaseModel = mModel[LLModel::LOD_HIGH];
-
- mDirty = true;
- resetPreviewTarget();
- }
- else
- { //only replace given LoD
- mModel[loaded_lod] = mModelLoader->mModelList;
- mScene[loaded_lod] = mModelLoader->mScene;
- mVertexBuffer[loaded_lod].clear();
-
- setPreviewLOD(loaded_lod);
-
- if (loaded_lod == LLModel::LOD_HIGH)
- { //save a copy of the highest LOD for automatic LOD manipulation
- if (mBaseModel.empty())
- { //first time we've loaded a model, auto-gen LoD
- mGenLOD = true;
- }
-
- mBaseModel = mModel[loaded_lod];
- clearGLODGroup();
-
- mBaseScene = mScene[loaded_lod];
- mVertexBuffer[5].clear();
- }
- else
- {
- BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
- BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
- if (!legacyMatching)
- {
- if (!mBaseModel.empty())
- {
- BOOL name_based = FALSE;
- BOOL has_submodels = FALSE;
- for (U32 idx = 0; idx < mBaseModel.size(); ++idx)
- {
- if (mBaseModel[idx]->mSubmodelID)
- { // don't do index-based renaming when the base model has submodels
- has_submodels = TRUE;
- if (importerDebug)
- {
- LL_INFOS() << "High LOD has submodels" << LL_ENDL;
- }
- break;
- }
- }
-
- for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx)
- {
- std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
-
- LLModel* found_model = NULL;
- LLMatrix4 transform;
- FindModel(mBaseScene, loaded_name, found_model, transform);
- if (found_model)
- { // don't rename correctly named models (even if they are placed in a wrong order)
- name_based = TRUE;
- }
-
- if (mModel[loaded_lod][idx]->mSubmodelID)
- { // don't rename the models when loaded LOD model has submodels
- has_submodels = TRUE;
- }
- }
-
- if (importerDebug)
- {
- LL_INFOS() << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found" << LL_ENDL;
- }
-
- if (!name_based && !has_submodels)
- { // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601)
- // this actually works like "ImporterLegacyMatching" for this particular LOD
- for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx)
- {
- std::string name = mBaseModel[idx]->mLabel;
- std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
-
- if (loaded_name != name)
- {
- switch (loaded_lod)
- {
- case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
- case LLModel::LOD_LOW: name += "_LOD1"; break;
- case LLModel::LOD_MEDIUM: name += "_LOD2"; break;
- case LLModel::LOD_PHYSICS: name += "_PHYS"; break;
- case LLModel::LOD_HIGH: break;
- }
-
- if (importerDebug)
- {
- LL_WARNS() << "Loded model name " << mModel[loaded_lod][idx]->mLabel << " for LOD " << loaded_lod << " doesn't match the base model. Renaming to " << name << LL_ENDL;
- }
-
- mModel[loaded_lod][idx]->mLabel = name;
- }
- }
- }
- }
- }
- }
-
- clearIncompatible(loaded_lod);
-
- mDirty = true;
-
- if (loaded_lod == LLModel::LOD_HIGH)
- {
- resetPreviewTarget();
- }
- }
-
- mLoading = false;
- if (mFMP)
- {
- mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE);
- if (!mBaseModel.empty())
- {
- const std::string& model_name = mBaseModel[0]->getName();
- LLLineEditor* description_form = mFMP->getChild<LLLineEditor>("description_form");
- if (description_form->getText().empty())
- {
- description_form->setText(model_name);
- }
- }
- }
- refresh();
-
- mModelLoadedSignal();
-
- mModelLoader = NULL;
-}
-
-void LLModelPreview::resetPreviewTarget()
-{
- if ( mModelLoader )
- {
- mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f;
- mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f;
- }
-
- setPreviewTarget(mPreviewScale.magVec()*10.f);
-}
-
-void LLModelPreview::generateNormals()
-{
- assert_main_thread();
-
- S32 which_lod = mPreviewLOD;
-
- if (which_lod > 4 || which_lod < 0 ||
- mModel[which_lod].empty())
- {
- return;
- }
-
- F32 angle_cutoff = mFMP->childGetValue("crease_angle").asReal();
-
- mRequestedCreaseAngle[which_lod] = angle_cutoff;
-
- angle_cutoff *= DEG_TO_RAD;
-
- if (which_lod == 3 && !mBaseModel.empty())
- {
- if(mBaseModelFacesCopy.empty())
- {
- mBaseModelFacesCopy.reserve(mBaseModel.size());
- for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it)
- {
- v_LLVolumeFace_t faces;
- (*it)->copyFacesTo(faces);
- mBaseModelFacesCopy.push_back(faces);
- }
- }
-
- for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it)
- {
- (*it)->generateNormals(angle_cutoff);
- }
-
- mVertexBuffer[5].clear();
- }
-
- bool perform_copy = mModelFacesCopy[which_lod].empty();
- if(perform_copy) {
- mModelFacesCopy[which_lod].reserve(mModel[which_lod].size());
- }
-
- for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it)
- {
- if(perform_copy)
- {
- v_LLVolumeFace_t faces;
- (*it)->copyFacesTo(faces);
- mModelFacesCopy[which_lod].push_back(faces);
- }
-
- (*it)->generateNormals(angle_cutoff);
- }
-
- mVertexBuffer[which_lod].clear();
- refresh();
- updateStatusMessages();
-}
-
-void LLModelPreview::restoreNormals()
+// static
+void LLFloaterModelPreview::addStringToLog(const std::ostringstream& strm, bool flash)
{
- S32 which_lod = mPreviewLOD;
-
- if (which_lod > 4 || which_lod < 0 ||
- mModel[which_lod].empty())
- {
- return;
- }
-
- if(!mBaseModelFacesCopy.empty())
- {
- llassert(mBaseModelFacesCopy.size() == mBaseModel.size());
-
- vv_LLVolumeFace_t::const_iterator itF = mBaseModelFacesCopy.begin();
- for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it, ++itF)
- {
- (*it)->copyFacesFrom((*itF));
- }
-
- mBaseModelFacesCopy.clear();
- }
-
- if(!mModelFacesCopy[which_lod].empty())
- {
- vv_LLVolumeFace_t::const_iterator itF = mModelFacesCopy[which_lod].begin();
- for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it, ++itF)
- {
- (*it)->copyFacesFrom((*itF));
- }
-
- mModelFacesCopy[which_lod].clear();
- }
-
- mVertexBuffer[which_lod].clear();
- refresh();
- updateStatusMessages();
+ if (sInstance)
+ {
+ sInstance->addStringToLogTab(strm.str(), flash);
+ }
}
-void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
+void LLFloaterModelPreview::clearAvatarTab()
{
- // Allow LoD from -1 to LLModel::LOD_PHYSICS
- if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
- {
- LL_WARNS() << "Invalid level of detail: " << which_lod << LL_ENDL;
- assert(which_lod >= -1 && which_lod < LLModel::NUM_LODS);
- return;
- }
-
- if (mBaseModel.empty())
- {
- return;
- }
-
- LLVertexBuffer::unbind();
-
- bool no_ff = LLGLSLShader::sNoFixedFunction;
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- LLGLSLShader::sNoFixedFunction = false;
-
- if (shader)
- {
- shader->unbind();
- }
-
- stop_gloderror();
- static U32 cur_name = 1;
-
- S32 limit = -1;
-
- U32 triangle_count = 0;
-
- U32 instanced_triangle_count = 0;
-
- //get the triangle count for the whole scene
- for (LLModelLoader::scene::iterator iter = mBaseScene.begin(), endIter = mBaseScene.end(); iter != endIter; ++iter)
- {
- for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
- {
- LLModel* mdl = instance->mModel;
- if (mdl)
- {
- instanced_triangle_count += mdl->getNumTriangles();
- }
- }
- }
-
- //get the triangle count for the non-instanced set of models
- for (U32 i = 0; i < mBaseModel.size(); ++i)
- {
- triangle_count += mBaseModel[i]->getNumTriangles();
- }
-
- //get ratio of uninstanced triangles to instanced triangles
- F32 triangle_ratio = (F32) triangle_count / (F32) instanced_triangle_count;
-
- U32 base_triangle_count = triangle_count;
-
- U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
-
- U32 lod_mode = 0;
-
- F32 lod_error_threshold = 0;
-
- // The LoD should be in range from Lowest to High
- if (which_lod > -1 && which_lod < NUM_LOD)
- {
- LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode_" + lod_name[which_lod]);
- if (iface)
- {
- lod_mode = iface->getFirstSelectedIndex();
- }
-
- lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
- }
-
- if (which_lod != -1)
- {
- mRequestedLoDMode[which_lod] = lod_mode;
- }
-
- if (lod_mode == 0)
- {
- lod_mode = GLOD_TRIANGLE_BUDGET;
-
- // The LoD should be in range from Lowest to High
- if (which_lod > -1 && which_lod < NUM_LOD)
- {
- limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger();
- //convert from "scene wide" to "non-instanced" triangle limit
- limit = (S32) ( (F32) limit*triangle_ratio );
- }
- }
- else
- {
- lod_mode = GLOD_ERROR_THRESHOLD;
- }
-
- bool object_dirty = false;
-
- if (mGroup == 0)
- {
- object_dirty = true;
- mGroup = cur_name++;
- glodNewGroup(mGroup);
- }
-
- if (object_dirty)
- {
- for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter)
- { //build GLOD objects for each model in base model list
- LLModel* mdl = *iter;
-
- if (mObject[mdl] != 0)
- {
- glodDeleteObject(mObject[mdl]);
- }
-
- mObject[mdl] = cur_name++;
-
- glodNewObject(mObject[mdl], mGroup, GLOD_DISCRETE);
- stop_gloderror();
-
- if (iter == mBaseModel.begin() && !mdl->mSkinWeights.empty())
- { //regenerate vertex buffer for skinned models to prevent animation feedback during LOD generation
- mVertexBuffer[5].clear();
- }
-
- if (mVertexBuffer[5].empty())
- {
- genBuffers(5, false);
- }
-
- U32 tri_count = 0;
- for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i)
- {
- LLVertexBuffer* buff = mVertexBuffer[5][mdl][i];
- buff->setBuffer(type_mask & buff->getTypeMask());
-
- U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();
- if (num_indices > 2)
- {
- glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*) mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
- }
- tri_count += num_indices/3;
- stop_gloderror();
- }
-
- glodBuildObject(mObject[mdl]);
- stop_gloderror();
- }
- }
-
-
- S32 start = LLModel::LOD_HIGH;
- S32 end = 0;
-
- if (which_lod != -1)
- {
- start = end = which_lod;
- }
-
- mMaxTriangleLimit = base_triangle_count;
-
- for (S32 lod = start; lod >= end; --lod)
- {
- if (which_lod == -1)
- {
- if (lod < start)
- {
- triangle_count /= decimation;
- }
- }
- else
- {
- if (enforce_tri_limit)
- {
- triangle_count = limit;
- }
- else
- {
- for (S32 j=LLModel::LOD_HIGH; j>which_lod; --j)
- {
- triangle_count /= decimation;
- }
- }
- }
-
- mModel[lod].clear();
- mModel[lod].resize(mBaseModel.size());
- mVertexBuffer[lod].clear();
-
- U32 actual_tris = 0;
- U32 actual_verts = 0;
- U32 submeshes = 0;
-
- mRequestedTriangleCount[lod] = (S32) ( (F32) triangle_count / triangle_ratio );
- mRequestedErrorThreshold[lod] = lod_error_threshold;
-
- glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode);
- stop_gloderror();
-
- glodGroupParameteri(mGroup, GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR);
- stop_gloderror();
-
- glodGroupParameterf(mGroup, GLOD_OBJECT_SPACE_ERROR_THRESHOLD, lod_error_threshold);
- stop_gloderror();
-
- if (lod_mode != GLOD_TRIANGLE_BUDGET)
- {
- glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, 0);
- }
- else
- {
- //SH-632: always add 1 to desired amount to avoid decimating below desired amount
- glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, triangle_count+1);
- }
-
- stop_gloderror();
- glodAdaptGroup(mGroup);
- stop_gloderror();
-
- for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
- {
- LLModel* base = mBaseModel[mdl_idx];
-
- GLint patch_count = 0;
- glodGetObjectParameteriv(mObject[base], GLOD_NUM_PATCHES, &patch_count);
- stop_gloderror();
-
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
- mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
-
- std::string name = base->mLabel;
-
- switch (lod)
- {
- case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
- case LLModel::LOD_LOW: name += "_LOD1"; break;
- case LLModel::LOD_MEDIUM: name += "_LOD2"; break;
- case LLModel::LOD_PHYSICS: name += "_PHYS"; break;
- case LLModel::LOD_HIGH: break;
- }
-
- mModel[lod][mdl_idx]->mLabel = name;
- mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
-
- GLint* sizes = new GLint[patch_count*2];
- glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);
- stop_gloderror();
-
- GLint* names = new GLint[patch_count];
- glodGetObjectParameteriv(mObject[base], GLOD_PATCH_NAMES, names);
- stop_gloderror();
-
- mModel[lod][mdl_idx]->setNumVolumeFaces(patch_count);
+ LLPanel *panel = mTabContainer->getPanelByName("rigging_panel");
+ LLScrollListCtrl *joints_list = panel->getChild<LLScrollListCtrl>("joints_list");
+ joints_list->deleteAllItems();
+ LLScrollListCtrl *joints_pos = panel->getChild<LLScrollListCtrl>("pos_overrides_list");
+ joints_pos->deleteAllItems(); mSelectedJointName.clear();
- LLModel* target_model = mModel[lod][mdl_idx];
-
- for (GLint i = 0; i < patch_count; ++i)
- {
- type_mask = mVertexBuffer[5][base][i]->getTypeMask();
-
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
-
- if (sizes[i*2+1] > 0 && sizes[i*2] > 0)
- {
- if (!buff->allocateBuffer(sizes[i * 2 + 1], sizes[i * 2], true))
- {
- // Todo: find a way to stop preview in this case instead of crashing
- LL_ERRS() << "Failed buffer allocation during preview LOD generation."
- << " Vertices: " << sizes[i * 2 + 1]
- << " Indices: " << sizes[i * 2] << LL_ENDL;
- }
- buff->setBuffer(type_mask);
- glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*) buff->getIndicesPointer());
- stop_gloderror();
- }
- else
- {
- // This face was eliminated or we failed to allocate buffer,
- // attempt to create a dummy triangle (one vertex, 3 indices, all 0)
- buff->allocateBuffer(1, 3, true);
- memset((U8*) buff->getMappedData(), 0, buff->getSize());
- memset((U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize());
- }
-
- buff->validateRange(0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
-
- LLStrider<LLVector3> pos;
- LLStrider<LLVector3> norm;
- LLStrider<LLVector2> tc;
- LLStrider<U16> index;
-
- buff->getVertexStrider(pos);
- if (type_mask & LLVertexBuffer::MAP_NORMAL)
- {
- buff->getNormalStrider(norm);
- }
- if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
- {
- buff->getTexCoord0Strider(tc);
- }
-
- buff->getIndexStrider(index);
-
- target_model->setVolumeFaceData(names[i], pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices());
- actual_tris += buff->getNumIndices()/3;
- actual_verts += buff->getNumVerts();
- ++submeshes;
-
- if (!validate_face(target_model->getVolumeFace(names[i])))
- {
- LL_ERRS() << "Invalid face generated during LOD generation." << LL_ENDL;
- }
- }
-
- //blind copy skin weights and just take closest skin weight to point on
- //decimated mesh for now (auto-generating LODs with skin weights is still a bit
- //of an open problem).
- target_model->mPosition = base->mPosition;
- target_model->mSkinWeights = base->mSkinWeights;
- target_model->mSkinInfo = base->mSkinInfo;
- //copy material list
- target_model->mMaterialList = base->mMaterialList;
-
- if (!validate_model(target_model))
- {
- LL_ERRS() << "Invalid model generated when creating LODs" << LL_ENDL;
- }
+ for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
+ {
+ mJointOverrides[i].clear();
+ }
- delete [] sizes;
- delete [] names;
- }
+ LLTextBox *joint_total_descr = panel->getChild<LLTextBox>("conflicts_description");
+ joint_total_descr->setTextArg("[CONFLICTS]", llformat("%d", 0));
+ joint_total_descr->setTextArg("[JOINTS_COUNT]", llformat("%d", 0));
- //rebuild scene based on mBaseScene
- mScene[lod].clear();
- mScene[lod] = mBaseScene;
- for (U32 i = 0; i < mBaseModel.size(); ++i)
- {
- LLModel* mdl = mBaseModel[i];
- LLModel* target = mModel[lod][i];
- if (target)
- {
- for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter)
- {
- for (U32 j = 0; j < iter->second.size(); ++j)
- {
- if (iter->second[j].mModel == mdl)
- {
- iter->second[j].mModel = target;
- }
- }
- }
- }
- }
- }
-
- mResourceCost = calcResourceCost();
-
- LLVertexBuffer::unbind();
- LLGLSLShader::sNoFixedFunction = no_ff;
- if (shader)
- {
- shader->bind();
- }
+ LLTextBox *joint_pos_descr = panel->getChild<LLTextBox>("pos_overrides_descr");
+ joint_pos_descr->setTextArg("[JOINT]", std::string("mPelvis")); // Might be better to hide it
}
-void LLModelPreview::updateStatusMessages()
+void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides)
{
- assert_main_thread();
-
- //triangle/vertex/submesh count for each mesh asset for each lod
- std::vector<S32> tris[LLModel::NUM_LODS];
- std::vector<S32> verts[LLModel::NUM_LODS];
- std::vector<S32> submeshes[LLModel::NUM_LODS];
-
- //total triangle/vertex/submesh count for each lod
- S32 total_tris[LLModel::NUM_LODS];
- S32 total_verts[LLModel::NUM_LODS];
- S32 total_submeshes[LLModel::NUM_LODS];
-
- for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
+ S32 display_lod = mModelPreview->mPreviewLOD;
+ if (mModelPreview->mModel[display_lod].empty())
{
- total_tris[i] = 0;
- total_verts[i] = 0;
- total_submeshes[i] = 0;
+ mSelectedJointName.clear();
+ return;
}
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
-
- LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH];
- if (!model_high_lod)
- {
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- continue;
- }
-
- for (U32 i = 0; i < LLModel::NUM_LODS-1; i++)
- {
- LLModel* lod_model = instance.mLOD[i];
- if (!lod_model)
+ // Joints will be listed as long as they are listed in mAlternateBindMatrix
+ // even if they are for some reason identical to defaults.
+ // Todo: Are overrides always identical for all lods? They normally are, but there might be situations where they aren't.
+ if (mJointOverrides[display_lod].empty())
+ {
+ // populate map
+ for (LLModelLoader::scene::iterator iter = mModelPreview->mScene[display_lod].begin(); iter != mModelPreview->mScene[display_lod].end(); ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
{
- setLoadState( LLModelLoader::ERROR_MATERIALS );
- mFMP->childDisable( "calculate_btn" );
- }
- else
- {
- //for each model in the lod
- S32 cur_tris = 0;
- S32 cur_verts = 0;
- S32 cur_submeshes = lod_model->getNumVolumeFaces();
-
- for (S32 j = 0; j < cur_submeshes; ++j)
- { //for each submesh (face), add triangles and vertices to current total
- const LLVolumeFace& face = lod_model->getVolumeFace(j);
- cur_tris += face.mNumIndices/3;
- cur_verts += face.mNumVertices;
- }
-
- std::string instance_name = instance.mLabel;
-
- BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug");
- if (importerDebug)
+ LLModelInstance& instance = *model_iter;
+ LLModel* model = instance.mModel;
+ const LLMeshSkinInfo *skin = &model->mSkinInfo;
+ U32 joint_count = LLSkinningUtil::getMeshJointCount(skin);
+ U32 bind_count = highlight_overrides ? skin->mAlternateBindMatrix.size() : 0; // simply do not include overrides if data is not needed
+ if (bind_count > 0 && bind_count != joint_count)
{
- // Useful for debugging generalized complaints below about total submeshes which don't have enough
- // context to address exactly what needs to be fixed to move towards compliance with the rules.
- //
- LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts << LL_ENDL;
- LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris << LL_ENDL;
- LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes << LL_ENDL;
-
- LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin();
- while (mat_iter != lod_model->mMaterialList.end())
+ std::ostringstream out;
+ out << "Invalid joint overrides for model " << model->getName();
+ out << ". Amount of joints " << joint_count;
+ out << ", is different from amount of overrides " << bind_count;
+ LL_INFOS() << out.str() << LL_ENDL;
+ addStringToLog(out.str(), true);
+ // Disable overrides for this model
+ bind_count = 0;
+ }
+ if (bind_count > 0)
+ {
+ for (U32 j = 0; j < joint_count; ++j)
{
- LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << LL_ENDL;
- mat_iter++;
+ const LLVector3& joint_pos = skin->mAlternateBindMatrix[j].getTranslation();
+ LLJointOverrideData &data = mJointOverrides[display_lod][skin->mJointNames[j]];
+
+ LLJoint* pJoint = LLModelPreview::lookupJointByName(skin->mJointNames[j], mModelPreview);
+ if (pJoint)
+ {
+ // see how voavatar uses aboveJointPosThreshold
+ if (pJoint->aboveJointPosThreshold(joint_pos))
+ {
+ // valid override
+ if (data.mPosOverrides.size() > 0
+ && (data.mPosOverrides.begin()->second - joint_pos).lengthSquared() > (LL_JOINT_TRESHOLD_POS_OFFSET * LL_JOINT_TRESHOLD_POS_OFFSET))
+ {
+ // File contains multiple meshes with conflicting joint offsets
+ // preview may be incorrect, upload result might wary (depends onto
+ // mesh_id that hasn't been generated yet).
+ data.mHasConflicts = true;
+ }
+ data.mPosOverrides[model->getName()] = joint_pos;
+ }
+ else
+ {
+ // default value, it won't be accounted for by avatar
+ data.mModelsNoOverrides.insert(model->getName());
+ }
+ }
}
}
-
- //add this model to the lod total
- total_tris[i] += cur_tris;
- total_verts[i] += cur_verts;
- total_submeshes[i] += cur_submeshes;
-
- //store this model's counts to asset data
- tris[i].push_back(cur_tris);
- verts[i].push_back(cur_verts);
- submeshes[i].push_back(cur_submeshes);
- }
- }
+ else
+ {
+ for (U32 j = 0; j < joint_count; ++j)
+ {
+ LLJointOverrideData &data = mJointOverrides[display_lod][skin->mJointNames[j]];
+ data.mModelsNoOverrides.insert(model->getName());
+ }
+ }
+ }
+ }
}
- if (mMaxTriangleLimit == 0)
- {
- mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
- }
-
- bool has_degenerate = false;
-
- {//check for degenerate triangles in physics mesh
- U32 lod = LLModel::LOD_PHYSICS;
- const LLVector4a scale(0.5f);
- for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i)
- { //for each model in the lod
- if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())
- { //no decomp exists
- S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
- for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j)
- { //for each submesh (face), add triangles and vertices to current total
- LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
- for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; )
- {
- U16 index_a = face.mIndices[k+0];
- U16 index_b = face.mIndices[k+1];
- U16 index_c = face.mIndices[k+2];
-
- LLVector4a v1; v1.setMul(face.mPositions[index_a], scale);
- LLVector4a v2; v2.setMul(face.mPositions[index_b], scale);
- LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);
-
- if (ll_is_degenerate(v1,v2,v3))
- {
- has_degenerate = true;
- }
- else
- {
- k += 3;
- }
- }
- }
- }
- }
- }
-
- mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
-
- std::string mesh_status_na = mFMP->getString("mesh_status_na");
-
- S32 upload_status[LLModel::LOD_HIGH+1];
-
- mModelNoErrors = true;
-
- const U32 lod_high = LLModel::LOD_HIGH;
- U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]);
-
- for (S32 lod = 0; lod <= lod_high; ++lod)
- {
- upload_status[lod] = 0;
-
- std::string message = "mesh_status_good";
-
- if (total_tris[lod] > 0)
- {
- mFMP->childSetValue(lod_triangles_name[lod], llformat("%d", total_tris[lod]));
- mFMP->childSetValue(lod_vertices_name[lod], llformat("%d", total_verts[lod]));
- }
- else
- {
- if (lod == lod_high)
- {
- upload_status[lod] = 2;
- message = "mesh_status_missing_lod";
- }
- else
- {
- for (S32 i = lod-1; i >= 0; --i)
- {
- if (total_tris[i] > 0)
- {
- upload_status[lod] = 2;
- message = "mesh_status_missing_lod";
- }
- }
- }
-
- mFMP->childSetValue(lod_triangles_name[lod], mesh_status_na);
- mFMP->childSetValue(lod_vertices_name[lod], mesh_status_na);
- }
-
- if (lod != lod_high)
- {
- if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high])
- { //number of submeshes is different
- message = "mesh_status_submesh_mismatch";
- upload_status[lod] = 2;
- }
- else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count)
- {//number of submodels is different, not all faces are matched correctly.
- message = "mesh_status_submesh_mismatch";
- upload_status[lod] = 2;
- // Note: Submodels in instance were loaded from higher LOD and as result face count
- // returns same value and total_submeshes[lod] is identical to high_lod one.
- }
- else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size())
- { //number of meshes is different
- message = "mesh_status_mesh_mismatch";
- upload_status[lod] = 2;
- }
- else if (!verts[lod].empty())
- {
- S32 sum_verts_higher_lod = 0;
- S32 sum_verts_this_lod = 0;
- for (U32 i = 0; i < verts[lod].size(); ++i)
- {
- sum_verts_higher_lod += ((i < verts[lod+1].size()) ? verts[lod+1][i] : 0);
- sum_verts_this_lod += verts[lod][i];
- }
-
- if ((sum_verts_higher_lod > 0) &&
- (sum_verts_this_lod > sum_verts_higher_lod))
- {
- //too many vertices in this lod
- message = "mesh_status_too_many_vertices";
- upload_status[lod] = 1;
- }
- }
- }
-
- LLIconCtrl* icon = mFMP->getChild<LLIconCtrl>(lod_icon_name[lod]);
- LLUIImagePtr img = LLUI::getUIImage(lod_status_image[upload_status[lod]]);
- icon->setVisible(true);
- icon->setImage(img);
-
- if (upload_status[lod] >= 2)
- {
- mModelNoErrors = false;
- }
-
- if (lod == mPreviewLOD)
- {
- mFMP->childSetValue("lod_status_message_text", mFMP->getString(message));
- icon = mFMP->getChild<LLIconCtrl>("lod_status_message_icon");
- icon->setImage(img);
- }
-
- updateLodControls(lod);
- }
-
-
- //warn if hulls have more than 256 points in them
- BOOL physExceededVertexLimit = FALSE;
- for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
- {
- LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i];
-
- if (mdl)
- {
- for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j)
- {
- if (mdl->mPhysics.mHull[j].size() > 256)
- {
- physExceededVertexLimit = TRUE;
- LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL;
- break;
- }
- }
- }
- }
- mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit);
- LLIconCtrl* physStatusIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon");
- physStatusIcon->setVisible(physExceededVertexLimit);
- if (physExceededVertexLimit)
- {
- mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded"));
- LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning");
- physStatusIcon->setImage(img);
- }
-
- if (getLoadState() >= LLModelLoader::ERROR_PARSING)
- {
- mModelNoErrors = false;
- LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL;
- }
-
- bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
- bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
-
- if ( uploadingSkin )
- {
- if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
- {
- mModelNoErrors = false;
- LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL;
- }
- }
-
- if(mModelNoErrors && mModelLoader)
- {
- if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
- {
- // Some textures are still loading, prevent upload until they are done
- mModelNoErrors = false;
- }
- }
-
- // Todo: investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics
- // current use of has_degenerate won't block upload permanently - later checks will restore the button
- if (!mModelNoErrors || has_degenerate)
- {
- mFMP->childDisable("ok_btn");
- }
+ LLPanel *panel = mTabContainer->getPanelByName("rigging_panel");
+ LLScrollListCtrl *joints_list = panel->getChild<LLScrollListCtrl>("joints_list");
- if (mModelNoErrors && mLodsWithParsingError.empty())
- {
- mFMP->childEnable("calculate_btn");
- }
- else
+ if (joints_list->isEmpty())
{
- mFMP->childDisable("calculate_btn");
- }
-
- //add up physics triangles etc
- S32 phys_tris = 0;
- S32 phys_hulls = 0;
- S32 phys_points = 0;
-
- //get the triangle count for the whole scene
- for (LLModelLoader::scene::iterator iter = mScene[LLModel::LOD_PHYSICS].begin(), endIter = mScene[LLModel::LOD_PHYSICS].end(); iter != endIter; ++iter)
- {
- for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
- {
- LLModel* model = instance->mModel;
- if (model)
- {
- S32 cur_submeshes = model->getNumVolumeFaces();
-
- LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull;
-
- if (!decomp.empty())
- {
- phys_hulls += decomp.size();
- for (U32 i = 0; i < decomp.size(); ++i)
- {
- phys_points += decomp[i].size();
- }
- }
- else
- { //choose physics shape OR decomposition, can't use both
- for (S32 j = 0; j < cur_submeshes; ++j)
- { //for each submesh (face), add triangles and vertices to current total
- const LLVolumeFace& face = model->getVolumeFace(j);
- phys_tris += face.mNumIndices/3;
- }
- }
- }
- }
- }
-
- if (phys_tris > 0)
- {
- mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]", llformat("%d", phys_tris));
- }
- else
- {
- mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]", mesh_status_na);
- }
-
- if (phys_hulls > 0)
- {
- mFMP->childSetTextArg("physics_hulls", "[HULLS]", llformat("%d", phys_hulls));
- mFMP->childSetTextArg("physics_points", "[POINTS]", llformat("%d", phys_points));
- }
- else
- {
- mFMP->childSetTextArg("physics_hulls", "[HULLS]", mesh_status_na);
- mFMP->childSetTextArg("physics_points", "[POINTS]", mesh_status_na);
- }
-
- LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
- if (fmp)
- {
- if (phys_tris > 0 || phys_hulls > 0)
- {
- if (!fmp->isViewOptionEnabled("show_physics"))
- {
- fmp->enableViewOption("show_physics");
- mViewOption["show_physics"] = true;
- fmp->childSetValue("show_physics", true);
- }
- }
- else
- {
- fmp->disableViewOption("show_physics");
- mViewOption["show_physics"] = false;
- fmp->childSetValue("show_physics", false);
-
- }
-
- //bool use_hull = fmp->childGetValue("physics_use_hull").asBoolean();
-
- //fmp->childSetEnabled("physics_optimize", !use_hull);
-
- bool enable = (phys_tris > 0 || phys_hulls > 0) && fmp->mCurRequest.empty();
- //enable = enable && !use_hull && fmp->childGetValue("physics_optimize").asBoolean();
-
- //enable/disable "analysis" UI
- LLPanel* panel = fmp->getChild<LLPanel>("physics analysis");
- LLView* child = panel->getFirstChild();
- while (child)
- {
- child->setEnabled(enable);
- child = panel->findNextSibling(child);
- }
-
- enable = phys_hulls > 0 && fmp->mCurRequest.empty();
- //enable/disable "simplification" UI
- panel = fmp->getChild<LLPanel>("physics simplification");
- child = panel->getFirstChild();
- while (child)
- {
- child->setEnabled(enable);
- child = panel->findNextSibling(child);
- }
-
- if (fmp->mCurRequest.empty())
- {
- fmp->childSetVisible("Simplify", true);
- fmp->childSetVisible("simplify_cancel", false);
- fmp->childSetVisible("Decompose", true);
- fmp->childSetVisible("decompose_cancel", false);
-
- if (phys_hulls > 0)
- {
- fmp->childEnable("Simplify");
- }
-
- if (phys_tris || phys_hulls > 0)
- {
- fmp->childEnable("Decompose");
- }
- }
- else
- {
- fmp->childEnable("simplify_cancel");
- fmp->childEnable("decompose_cancel");
- }
- }
-
-
- LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo");
- S32 which_mode = 0;
- S32 file_mode = 1;
- if (iface)
- {
- which_mode = iface->getFirstSelectedIndex();
- file_mode = iface->getItemCount() - 1;
- }
-
- if (which_mode == file_mode)
- {
- mFMP->childEnable("physics_file");
- mFMP->childEnable("physics_browse");
- }
- else
- {
- mFMP->childDisable("physics_file");
- mFMP->childDisable("physics_browse");
- }
-
- LLSpinCtrl* crease = mFMP->getChild<LLSpinCtrl>("crease_angle");
-
- if (mRequestedCreaseAngle[mPreviewLOD] == -1.f)
- {
- mFMP->childSetColor("crease_label", LLColor4::grey);
- crease->forceSetValue(75.f);
- }
- else
- {
- mFMP->childSetColor("crease_label", LLColor4::white);
- crease->forceSetValue(mRequestedCreaseAngle[mPreviewLOD]);
- }
-
- mModelUpdatedSignal(true);
-
-}
-
-void LLModelPreview::updateLodControls(S32 lod)
-{
- if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::LOD_HIGH)
- {
- LL_WARNS() << "Invalid level of detail: " << lod << LL_ENDL;
- assert(lod >= LLModel::LOD_IMPOSTOR && lod <= LLModel::LOD_HIGH);
- return;
- }
-
- const char* lod_controls[] =
- {
- "lod_mode_",
- "lod_triangle_limit_",
- "lod_error_threshold_"
- };
- const U32 num_lod_controls = sizeof(lod_controls)/sizeof(char*);
-
- const char* file_controls[] =
- {
- "lod_browse_",
- "lod_file_",
- };
- const U32 num_file_controls = sizeof(file_controls)/sizeof(char*);
-
- LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
- if (!fmp) return;
-
- LLComboBox* lod_combo = mFMP->findChild<LLComboBox>("lod_source_" + lod_name[lod]);
- if (!lod_combo) return;
-
- S32 lod_mode = lod_combo->getCurrentIndex();
- if (lod_mode == LOD_FROM_FILE) // LoD from file
- {
- fmp->mLODMode[lod] = 0;
- for (U32 i = 0; i < num_file_controls; ++i)
- {
- mFMP->childSetVisible(file_controls[i] + lod_name[lod], true);
- }
-
- for (U32 i = 0; i < num_lod_controls; ++i)
- {
- mFMP->childSetVisible(lod_controls[i] + lod_name[lod], false);
- }
- }
- else if (lod_mode == USE_LOD_ABOVE) // use LoD above
- {
- fmp->mLODMode[lod] = 2;
- for (U32 i = 0; i < num_file_controls; ++i)
- {
- mFMP->childSetVisible(file_controls[i] + lod_name[lod], false);
- }
-
- for (U32 i = 0; i < num_lod_controls; ++i)
- {
- mFMP->childSetVisible(lod_controls[i] + lod_name[lod], false);
- }
-
- if (lod < LLModel::LOD_HIGH)
- {
- mModel[lod] = mModel[lod + 1];
- mScene[lod] = mScene[lod + 1];
- mVertexBuffer[lod].clear();
-
- // Also update lower LoD
- if (lod > LLModel::LOD_IMPOSTOR)
- {
- updateLodControls(lod - 1);
- }
- }
- }
- else // auto generate, the default case for all LoDs except High
- {
- fmp->mLODMode[lod] = 1;
-
- //don't actually regenerate lod when refreshing UI
- mLODFrozen = true;
-
- for (U32 i = 0; i < num_file_controls; ++i)
- {
- mFMP->getChildView(file_controls[i] + lod_name[lod])->setVisible(false);
- }
-
- for (U32 i = 0; i < num_lod_controls; ++i)
- {
- mFMP->getChildView(lod_controls[i] + lod_name[lod])->setVisible(true);
- }
-
-
- LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>("lod_error_threshold_" + lod_name[lod]);
- LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod]);
-
- limit->setMaxValue(mMaxTriangleLimit);
- limit->forceSetValue(mRequestedTriangleCount[lod]);
-
- threshold->forceSetValue(mRequestedErrorThreshold[lod]);
-
- mFMP->getChild<LLComboBox>("lod_mode_" + lod_name[lod])->selectNthItem(mRequestedLoDMode[lod]);
-
- if (mRequestedLoDMode[lod] == 0)
- {
- limit->setVisible(true);
- threshold->setVisible(false);
-
- limit->setMaxValue(mMaxTriangleLimit);
- limit->setIncrement(mMaxTriangleLimit/32);
- }
- else
- {
- limit->setVisible(false);
- threshold->setVisible(true);
- }
-
- mLODFrozen = false;
- }
-}
-
-void LLModelPreview::setPreviewTarget(F32 distance)
-{
- mCameraDistance = distance;
- mCameraZoom = 1.f;
- mCameraPitch = 0.f;
- mCameraYaw = 0.f;
- mCameraOffset.clearVec();
-}
-
-void LLModelPreview::clearBuffers()
-{
- for (U32 i = 0; i < 6; i++)
- {
- mVertexBuffer[i].clear();
- }
-}
-
-void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
-{
- U32 tri_count = 0;
- U32 vertex_count = 0;
- U32 mesh_count = 0;
-
-
- LLModelLoader::model_list* model = NULL;
-
- if (lod < 0 || lod > 4)
- {
- model = &mBaseModel;
- lod = 5;
- }
- else
- {
- model = &(mModel[lod]);
- }
-
- if (!mVertexBuffer[lod].empty())
- {
- mVertexBuffer[lod].clear();
- }
-
- mVertexBuffer[lod].clear();
-
- LLModelLoader::model_list::iterator base_iter = mBaseModel.begin();
-
- for (LLModelLoader::model_list::iterator iter = model->begin(); iter != model->end(); ++iter)
- {
- LLModel* mdl = *iter;
- if (!mdl)
- {
- continue;
- }
-
- LLModel* base_mdl = *base_iter;
- base_iter++;
-
- S32 num_faces = mdl->getNumVolumeFaces();
- for (S32 i = 0; i < num_faces; ++i)
- {
- const LLVolumeFace &vf = mdl->getVolumeFace(i);
- U32 num_vertices = vf.mNumVertices;
- U32 num_indices = vf.mNumIndices;
-
- if (!num_vertices || ! num_indices)
- {
- continue;
- }
-
- LLVertexBuffer* vb = NULL;
+ // Populate table
- bool skinned = include_skin_weights && !mdl->mSkinWeights.empty();
+ std::map<std::string, std::string> joint_alias_map;
+ mModelPreview->getJointAliases(joint_alias_map);
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0 ;
-
- if (skinned)
- {
- mask |= LLVertexBuffer::MAP_WEIGHT4;
- }
-
- vb = new LLVertexBuffer(mask, 0);
-
- if (!vb->allocateBuffer(num_vertices, num_indices, TRUE))
- {
- // We are likely to crash due this failure, if this happens, find a way to gracefully stop preview
- LL_WARNS() << "Failed to allocate Vertex Buffer for model preview "
- << num_vertices << " vertices and "
- << num_indices << " indices" << LL_ENDL;
- }
-
- LLStrider<LLVector3> vertex_strider;
- LLStrider<LLVector3> normal_strider;
- LLStrider<LLVector2> tc_strider;
- LLStrider<U16> index_strider;
- LLStrider<LLVector4> weights_strider;
-
- vb->getVertexStrider(vertex_strider);
- vb->getIndexStrider(index_strider);
-
- if (skinned)
- {
- vb->getWeight4Strider(weights_strider);
- }
-
- LLVector4a::memcpyNonAliased16((F32*) vertex_strider.get(), (F32*) vf.mPositions, num_vertices*4*sizeof(F32));
-
- if (vf.mTexCoords)
- {
- vb->getTexCoord0Strider(tc_strider);
- S32 tex_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF;
- LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, tex_size);
- }
-
- if (vf.mNormals)
- {
- vb->getNormalStrider(normal_strider);
- LLVector4a::memcpyNonAliased16((F32*) normal_strider.get(), (F32*) vf.mNormals, num_vertices*4*sizeof(F32));
- }
-
- if (skinned)
- {
- for (U32 i = 0; i < num_vertices; i++)
- {
- //find closest weight to vf.mVertices[i].mPosition
- LLVector3 pos(vf.mPositions[i].getF32ptr());
-
- const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos);
- llassert(weight_list.size()>0 && weight_list.size() <= 4); // LLModel::loadModel() should guarantee this
-
- LLVector4 w(0,0,0,0);
-
- for (U32 i = 0; i < weight_list.size(); ++i)
- {
- F32 wght = llclamp(weight_list[i].mWeight, 0.001f, 0.999f);
- F32 joint = (F32) weight_list[i].mJointIdx;
- w.mV[i] = joint + wght;
- llassert(w.mV[i]-(S32)w.mV[i]>0.0f); // because weights are non-zero, and range of wt values
- //should not cause floating point precision issues.
- }
-
- *(weights_strider++) = w;
- }
- }
-
- // build indices
- for (U32 i = 0; i < num_indices; i++)
- {
- *(index_strider++) = vf.mIndices[i];
- }
-
- mVertexBuffer[lod][mdl].push_back(vb);
+ S32 conflicts = 0;
+ joint_override_data_map_t::iterator joint_iter = mJointOverrides[display_lod].begin();
+ joint_override_data_map_t::iterator joint_end = mJointOverrides[display_lod].end();
+ while (joint_iter != joint_end)
+ {
+ const std::string& listName = joint_iter->first;
- vertex_count += num_vertices;
- tri_count += num_indices/3;
- ++mesh_count;
+ LLScrollListItem::Params item_params;
+ item_params.value(listName);
- }
- }
-}
+ LLScrollListCell::Params cell_params;
+ cell_params.font = LLFontGL::getFontSansSerif();
+ cell_params.value = listName;
+ if (joint_alias_map.find(listName) == joint_alias_map.end())
+ {
+ // Missing names
+ cell_params.color = LLColor4::red;
+ }
+ if (joint_iter->second.mHasConflicts)
+ {
+ // Conflicts
+ cell_params.color = LLColor4::orange;
+ conflicts++;
+ }
+ if (highlight_overrides && joint_iter->second.mPosOverrides.size() > 0)
+ {
+ cell_params.font.style = "BOLD";
+ }
-void LLModelPreview::update()
-{
- if (mGenLOD)
- {
- bool subscribe_for_generation = mLodsQuery.empty();
- mGenLOD = false;
- mDirty = true;
- mLodsQuery.clear();
+ item_params.columns.add(cell_params);
- for (S32 lod = LLModel::LOD_HIGH; lod >= 0; --lod)
- {
- // adding all lods into query for generation
- mLodsQuery.push_back(lod);
+ joints_list->addRow(item_params, ADD_BOTTOM);
+ joint_iter++;
}
-
- if (subscribe_for_generation)
+ joints_list->selectFirstItem();
+ LLScrollListItem *selected = joints_list->getFirstSelected();
+ if (selected)
{
- doOnIdleRepeating(lodQueryCallback);
+ mSelectedJointName = selected->getValue().asString();
}
- }
- if (mDirty && mLodsQuery.empty())
- {
- mDirty = false;
- mResourceCost = calcResourceCost();
- refresh();
- updateStatusMessages();
- }
-}
-
-//-----------------------------------------------------------------------------
-// createPreviewAvatar
-//-----------------------------------------------------------------------------
-void LLModelPreview::createPreviewAvatar( void )
-{
- mPreviewAvatar = (LLVOAvatar*)gObjectList.createObjectViewer( LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR );
- if ( mPreviewAvatar )
- {
- mPreviewAvatar->createDrawable( &gPipeline );
- mPreviewAvatar->mSpecialRenderMode = 1;
- mPreviewAvatar->startMotion( ANIM_AGENT_STAND );
- mPreviewAvatar->hideSkirt();
- }
- else
- {
- LL_INFOS() << "Failed to create preview avatar for upload model window" << LL_ENDL;
- }
-}
-
-//static
-U32 LLModelPreview::countRootModels(LLModelLoader::model_list models)
-{
- U32 root_models = 0;
- model_list::iterator model_iter = models.begin();
- while (model_iter != models.end())
- {
- LLModel* mdl = *model_iter;
- if (mdl && mdl->mSubmodelID == 0)
- {
- root_models++;
- }
- model_iter++;
- }
- return root_models;
-}
-
-void LLModelPreview::loadedCallback(
- LLModelLoader::scene& scene,
- LLModelLoader::model_list& model_list,
- S32 lod,
- void* opaque)
-{
- LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
- if (pPreview && !LLModelPreview::sIgnoreLoadedCallback)
- {
- pPreview->loadModelCallback(lod);
- }
-}
-
-void LLModelPreview::stateChangedCallback(U32 state,void* opaque)
-{
- LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
- if (pPreview)
- {
- pPreview->setLoadState(state);
- }
-}
-
-LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque)
-{
- LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
- if (pPreview)
- {
- return pPreview->getPreviewAvatar()->getJoint(str);
- }
- return NULL;
-}
-
-U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque)
-{
- (void)opaque;
-
- if (material.mDiffuseMapFilename.size())
- {
- material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >;
- LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData));
-
- tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
- tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE);
- tex->forceToSaveRawImage(0, F32_MAX);
- material.setDiffuseMap(tex->getID()); // record tex ID
- return 1;
- }
-
- material.mOpaqueData = NULL;
- return 0;
+ LLTextBox *joint_conf_descr = panel->getChild<LLTextBox>("conflicts_description");
+ joint_conf_descr->setTextArg("[CONFLICTS]", llformat("%d", conflicts));
+ joint_conf_descr->setTextArg("[JOINTS_COUNT]", llformat("%d", mJointOverrides[display_lod].size()));
+ }
}
-void LLModelPreview::addEmptyFace( LLModel* pTarget )
-{
- U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
-
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
-
- buff->allocateBuffer(1, 3, true);
- memset( (U8*) buff->getMappedData(), 0, buff->getSize() );
- memset( (U8*) buff->getIndicesPointer(), 0, buff->getIndicesSize() );
-
- buff->validateRange( 0, buff->getNumVerts()-1, buff->getNumIndices(), 0 );
-
- LLStrider<LLVector3> pos;
- LLStrider<LLVector3> norm;
- LLStrider<LLVector2> tc;
- LLStrider<U16> index;
-
- buff->getVertexStrider(pos);
-
- if ( type_mask & LLVertexBuffer::MAP_NORMAL )
- {
- buff->getNormalStrider(norm);
- }
- if ( type_mask & LLVertexBuffer::MAP_TEXCOORD0 )
- {
- buff->getTexCoord0Strider(tc);
- }
-
- buff->getIndexStrider(index);
-
- //resize face array
- int faceCnt = pTarget->getNumVolumeFaces();
- pTarget->setNumVolumeFaces( faceCnt+1 );
- pTarget->setVolumeFaceData( faceCnt+1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices() );
-
-}
-
//-----------------------------------------------------------------------------
-// render()
+// addStringToLogTab()
//-----------------------------------------------------------------------------
-BOOL LLModelPreview::render()
+void LLFloaterModelPreview::addStringToLogTab(const std::string& str, bool flash)
{
- assert_main_thread();
-
- LLMutexLock lock(this);
- mNeedsUpdate = FALSE;
-
- bool use_shaders = LLGLSLShader::sNoFixedFunction;
-
- bool edges = mViewOption["show_edges"];
- bool joint_positions = mViewOption["show_joint_positions"];
- bool skin_weight = mViewOption["show_skin_weight"];
- bool textures = mViewOption["show_textures"];
- bool physics = mViewOption["show_physics"];
-
- S32 width = getWidth();
- S32 height = getHeight();
-
- LLGLSUIDefault def; // GL_BLEND, GL_ALPHA_TEST, GL_CULL_FACE, depth test
- LLGLDisable no_blend(GL_BLEND);
- LLGLDepthTest depth(GL_FALSE); // SL-12781 disable z-buffer to render background color
- LLGLDisable fog(GL_FOG);
-
- {
- if (use_shaders)
- {
- gUIProgram.bind();
- }
- //clear background to grey
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.ortho(0.0f, width, 0.0f, height, -1.0f, 1.0f);
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- gGL.color4f(0.169f, 0.169f, 0.169f, 1.f);
-
- gl_rect_2d_simple( width, height );
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- if (use_shaders)
- {
- gUIProgram.unbind();
- }
- }
-
- LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
-
- bool has_skin_weights = false;
- bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();
- bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean();
-
- if ( upload_joints != mLastJointUpdate )
- {
- mLastJointUpdate = upload_joints;
- }
-
- for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
- {
- for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
- {
- LLModelInstance& instance = *model_iter;
- LLModel* model = instance.mModel;
- model->mPelvisOffset = mPelvisZOffset;
- if (!model->mSkinWeights.empty())
- {
- has_skin_weights = true;
- }
- }
- }
-
- if (has_skin_weights && lodsReady())
- { //model has skin weights, enable view options for skin weights and joint positions
- if (fmp && isLegacyRigValid() )
- {
- fmp->enableViewOption("show_skin_weight");
- fmp->setViewOptionEnabled("show_joint_positions", skin_weight);
- mFMP->childEnable("upload_skin");
- mFMP->childSetValue("show_skin_weight", skin_weight);
- }
- }
- else
- {
- mFMP->childDisable("upload_skin");
- if (fmp)
- {
- mViewOption["show_skin_weight"] = false;
- fmp->disableViewOption("show_skin_weight");
- fmp->disableViewOption("show_joint_positions");
-
- skin_weight = false;
- mFMP->childSetValue("show_skin_weight", false);
- fmp->setViewOptionEnabled("show_skin_weight", skin_weight);
- }
- }
-
- if (upload_skin && !has_skin_weights)
- { //can't upload skin weights if model has no skin weights
- mFMP->childSetValue("upload_skin", false);
- upload_skin = false;
- }
+ if (str.empty())
+ {
+ return;
+ }
- if (!upload_skin && upload_joints)
- { //can't upload joints if not uploading skin weights
- mFMP->childSetValue("upload_joints", false);
- upload_joints = false;
- }
+ LLWString text = utf8str_to_wstring(str);
+ S32 add_text_len = text.length() + 1; // newline
+ S32 editor_max_len = mUploadLogText->getMaxTextLength();
+ if (add_text_len > editor_max_len)
+ {
+ return;
+ }
- if (upload_skin && upload_joints)
+ // Make sure we have space for new string
+ S32 editor_text_len = mUploadLogText->getLength();
+ if (editor_max_len < (editor_text_len + add_text_len)
+ && mUploadLogText->getLineCount() <= 0)
{
- mFMP->childEnable("lock_scale_if_joint_position");
+ mUploadLogText->getTextBoundingRect();// forces a reflow() to fix line count
}
- else
+ while (editor_max_len < (editor_text_len + add_text_len))
{
- mFMP->childDisable("lock_scale_if_joint_position");
- mFMP->childSetValue("lock_scale_if_joint_position", false);
+ S32 shift = mUploadLogText->removeFirstLine();
+ if (shift > 0)
+ {
+ // removed a line
+ editor_text_len -= shift;
+ }
+ else
+ {
+ //nothing to remove?
+ LL_WARNS() << "Failed to clear log lines" << LL_ENDL;
+ break;
+ }
}
-
- //Only enable joint offsets if it passed the earlier critiquing
- if ( isRigValidForJointPositionUpload() )
- {
- mFMP->childSetEnabled("upload_joints", upload_skin);
- }
-
- F32 explode = mFMP->childGetValue("physics_explode").asReal();
-
- LLGLDepthTest gls_depth(GL_TRUE); // SL-12781 re-enable z-buffer for 3D model preview
-
- LLRect preview_rect;
-
- preview_rect = mFMP->getChildView("preview_panel")->getRect();
-
- F32 aspect = (F32) preview_rect.getWidth()/preview_rect.getHeight();
-
- LLViewerCamera::getInstance()->setAspect(aspect);
-
- LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
- LLVector3 offset = mCameraOffset;
- LLVector3 target_pos = mPreviewTarget+offset;
+ mUploadLogText->appendText(str, true);
- F32 z_near = 0.001f;
- F32 z_far = mCameraDistance*10.0f+mPreviewScale.magVec()+mCameraOffset.magVec();
-
- if (skin_weight)
- {
- target_pos = getPreviewAvatar()->getPositionAgent();
- z_near = 0.01f;
- z_far = 1024.f;
-
- //render avatar previews every frame
- refresh();
- }
-
- if (use_shaders)
- {
- gObjectPreviewProgram.bind();
- }
-
- gGL.loadIdentity();
- gPipeline.enableLightsPreview();
-
- LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) *
- LLQuaternion(mCameraYaw, LLVector3::z_axis);
-
- LLQuaternion av_rot = camera_rot;
- LLViewerCamera::getInstance()->setOriginAndLookAt(
- target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera
- LLVector3::z_axis, // up
- target_pos); // point of interest
-
-
- z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f);
-
- LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, width, height, FALSE, z_near, z_far);
-
- stop_glerror();
-
- gGL.pushMatrix();
- const F32 BRIGHTNESS = 0.9f;
- gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS);
-
- const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
-
- LLGLEnable normalize(GL_NORMALIZE);
-
- if (!mBaseModel.empty() && mVertexBuffer[5].empty())
- {
- genBuffers(-1, skin_weight);
- //genBuffers(3);
- //genLODs();
- }
-
- if (!mModel[mPreviewLOD].empty())
- {
- mFMP->childEnable("reset_btn");
-
- bool regen = mVertexBuffer[mPreviewLOD].empty();
- if (!regen)
- {
- const std::vector<LLPointer<LLVertexBuffer> >& vb_vec = mVertexBuffer[mPreviewLOD].begin()->second;
- if (!vb_vec.empty())
- {
- const LLVertexBuffer* buff = vb_vec[0];
- regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight;
- }
- else
- {
- LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
- regen = TRUE;
- }
- }
-
- if (regen)
- {
- genBuffers(mPreviewLOD, skin_weight);
- }
-
- if (!skin_weight)
- {
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
-
- LLModel* model = instance.mLOD[mPreviewLOD];
-
- if (!model)
- {
- continue;
- }
-
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
-
- gGL.multMatrix((GLfloat*) mat.mMatrix);
-
-
- U32 num_models = mVertexBuffer[mPreviewLOD][model].size();
- for (U32 i = 0; i < num_models; ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-
- buffer->setBuffer(type_mask & buffer->getTypeMask());
-
- if (textures)
- {
- int materialCnt = instance.mModel->mMaterialList.size();
- if ( i < materialCnt )
- {
- const std::string& binding = instance.mModel->mMaterialList[i];
- const LLImportMaterial& material = instance.mMaterial[binding];
-
- gGL.diffuseColor4fv(material.mDiffuseColor.mV);
-
- // Find the tex for this material, bind it, and add it to our set
- //
- LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
- if (tex)
- {
- mTextureSet.insert(tex);
- }
- }
- }
- else
- {
- gGL.diffuseColor4f(1,1,1,1);
- }
-
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
-
- if (edges)
- {
- glLineWidth(3.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
- }
- }
- gGL.popMatrix();
- }
-
- if (physics)
- {
- glClear(GL_DEPTH_BUFFER_BIT);
-
- for (U32 pass = 0; pass < 2; pass++)
- {
- if (pass == 0)
- { //depth only pass
- gGL.setColorMask(false, false);
- }
- else
- {
- gGL.setColorMask(true, true);
- }
-
- //enable alpha blending on second pass but not first pass
- LLGLState blend(GL_BLEND, pass);
-
- gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
-
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
-
- LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
-
- if (!model)
- {
- continue;
- }
-
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
-
- gGL.multMatrix((GLfloat*) mat.mMatrix);
-
-
- bool render_mesh = true;
-
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
-
- LLModel::Decomposition& physics = model->mPhysics;
-
- if (!physics.mHull.empty())
- {
- render_mesh = false;
-
- if (physics.mMesh.empty())
- { //build vertex buffer for physics mesh
- gMeshRepo.buildPhysicsMesh(physics);
- }
-
- if (!physics.mMesh.empty())
- { //render hull instead of mesh
- for (U32 i = 0; i < physics.mMesh.size(); ++i)
- {
- if (explode > 0.f)
- {
- gGL.pushMatrix();
-
- LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
- offset *= explode;
-
- gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
- }
-
- static std::vector<LLColor4U> hull_colors;
-
- if (i+1 >= hull_colors.size())
- {
- hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128));
- }
-
- gGL.diffuseColor4ubv(hull_colors[i].mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
-
- if (explode > 0.f)
- {
- gGL.popMatrix();
- }
- }
- }
- }
- }
-
- if (render_mesh)
- {
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
- {
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
-
- U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
- for (U32 i = 0; i < num_models; ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f);
-
- buffer->setBuffer(type_mask & buffer->getTypeMask());
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
-
- gGL.diffuseColor3f(1.f, 1.f, 0.f);
-
- glLineWidth(2.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
-
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
- }
- }
-
- gGL.popMatrix();
- }
-
- glLineWidth(3.f);
- glPointSize(8.f);
- gPipeline.enableLightsFullbright();
- //show degenerate triangles
- LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
- LLGLDisable cull(GL_CULL_FACE);
- gGL.diffuseColor4f(1.f,0.f,0.f,1.f);
- const LLVector4a scale(0.5f);
-
- for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
- {
- LLModelInstance& instance = *iter;
-
- LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
-
- if (!model)
- {
- continue;
- }
-
- gGL.pushMatrix();
- LLMatrix4 mat = instance.mTransform;
-
- gGL.multMatrix((GLfloat*) mat.mMatrix);
-
-
- LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
- if (decomp)
- {
- LLMutexLock(decomp->mMutex);
-
- LLModel::Decomposition& physics = model->mPhysics;
-
- if (physics.mHull.empty())
- {
- if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
- {
- genBuffers(LLModel::LOD_PHYSICS, false);
- }
-
- for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
-
- buffer->setBuffer(type_mask & buffer->getTypeMask());
-
- LLStrider<LLVector3> pos_strider;
- buffer->getVertexStrider(pos_strider, 0);
- LLVector4a* pos = (LLVector4a*) pos_strider.get();
-
- LLStrider<U16> idx;
- buffer->getIndexStrider(idx, 0);
-
- for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
- {
- LLVector4a v1; v1.setMul(pos[*idx++], scale);
- LLVector4a v2; v2.setMul(pos[*idx++], scale);
- LLVector4a v3; v3.setMul(pos[*idx++], scale);
-
- if (ll_is_degenerate(v1,v2,v3))
- {
- buffer->draw(LLRender::LINE_LOOP, 3, i);
- buffer->draw(LLRender::POINTS, 3, i);
- }
- }
- }
- }
- }
-
- gGL.popMatrix();
- }
- glLineWidth(1.f);
- glPointSize(1.f);
- gPipeline.enableLightsPreview();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
- }
- }
- else
- {
- target_pos = getPreviewAvatar()->getPositionAgent();
-
- LLViewerCamera::getInstance()->setOriginAndLookAt(
- target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera
- LLVector3::z_axis, // up
- target_pos); // point of interest
-
- for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
- {
- for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
- {
- LLModelInstance& instance = *model_iter;
- LLModel* model = instance.mModel;
-
- if (!model->mSkinWeights.empty())
- {
- for (U32 i = 0, e = mVertexBuffer[mPreviewLOD][model].size(); i < e; ++i)
- {
- LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
-
- const LLVolumeFace& face = model->getVolumeFace(i);
-
- LLStrider<LLVector3> position;
- buffer->getVertexStrider(position);
-
- LLStrider<LLVector4> weight;
- buffer->getWeight4Strider(weight);
-
- //quick 'n dirty software vertex skinning
-
- //build matrix palette
-
- LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
- const LLMeshSkinInfo *skin = &model->mSkinInfo;
- U32 count = LLSkinningUtil::getMeshJointCount(skin);
- LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, count,
- skin, getPreviewAvatar());
- LLMatrix4a bind_shape_matrix;
- bind_shape_matrix.loadu(skin->mBindShapeMatrix);
- U32 max_joints = LLSkinningUtil::getMaxJointCount();
- for (U32 j = 0; j < buffer->getNumVerts(); ++j)
- {
- LLMatrix4a final_mat;
- F32 *wptr = weight[j].mV;
- LLSkinningUtil::getPerVertexSkinMatrix(wptr, mat, true, final_mat, max_joints);
-
- //VECTORIZE THIS
- LLVector4a& v = face.mPositions[j];
-
- LLVector4a t;
- LLVector4a dst;
- bind_shape_matrix.affineTransform(v, t);
- final_mat.affineTransform(t, dst);
-
- position[j][0] = dst[0];
- position[j][1] = dst[1];
- position[j][2] = dst[2];
- }
-
- llassert(model->mMaterialList.size() > i);
- const std::string& binding = instance.mModel->mMaterialList[i];
- const LLImportMaterial& material = instance.mMaterial[binding];
-
- buffer->setBuffer(type_mask & buffer->getTypeMask());
- gGL.diffuseColor4fv(material.mDiffuseColor.mV);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- // Find the tex for this material, bind it, and add it to our set
- //
- LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
- if (tex)
- {
- mTextureSet.insert(tex);
- }
-
- buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
- gGL.diffuseColor3f(0.4f, 0.4f, 0.4f);
-
- if (edges)
- {
- glLineWidth(3.f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glLineWidth(1.f);
- }
- }
- }
- }
- }
-
- if (joint_positions)
- {
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- if (shader)
- {
- gDebugProgram.bind();
- }
- getPreviewAvatar()->renderCollisionVolumes();
- getPreviewAvatar()->renderBones();
- if (shader)
- {
- shader->bind();
- }
- }
-
- }
- }
-
- if (use_shaders)
- {
- gObjectPreviewProgram.unbind();
- }
-
- gGL.popMatrix();
-
- return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// refresh()
-//-----------------------------------------------------------------------------
-void LLModelPreview::refresh()
-{
- mNeedsUpdate = TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// rotate()
-//-----------------------------------------------------------------------------
-void LLModelPreview::rotate(F32 yaw_radians, F32 pitch_radians)
-{
- mCameraYaw = mCameraYaw + yaw_radians;
-
- mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f);
-}
-
-//-----------------------------------------------------------------------------
-// zoom()
-//-----------------------------------------------------------------------------
-void LLModelPreview::zoom(F32 zoom_amt)
-{
- F32 new_zoom = mCameraZoom+zoom_amt;
-
- mCameraZoom = llclamp(new_zoom, 1.f, 10.f);
+ if (flash)
+ {
+ LLPanel* panel = mTabContainer->getPanelByName("logs_panel");
+ if (mTabContainer->getCurrentPanel() != panel)
+ {
+ mTabContainer->setTabPanelFlashing(panel, true);
+ }
+ }
}
-void LLModelPreview::pan(F32 right, F32 up)
+void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
{
- mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f);
- mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f);
+ assert_main_thread();
+ childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
+ childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
+ childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
}
-void LLModelPreview::setPreviewLOD(S32 lod)
+void LLFloaterModelPreview::setPreviewLOD(S32 lod)
{
- lod = llclamp(lod, 0, (S32) LLModel::LOD_HIGH);
-
- if (lod != mPreviewLOD)
+ if (mModelPreview)
{
- mPreviewLOD = lod;
-
- LLComboBox* combo_box = mFMP->getChild<LLComboBox>("preview_lod_combo");
- combo_box->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order
- mFMP->childSetValue("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]);
-
- LLComboBox* combo_box2 = mFMP->getChild<LLComboBox>("preview_lod_combo2");
- combo_box2->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order
-
- LLComboBox* combo_box3 = mFMP->getChild<LLComboBox>("preview_lod_combo3");
- combo_box3->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order
-
- LLColor4 highlight_color = LLUIColorTable::instance().getColor("MeshImportTableHighlightColor");
- LLColor4 normal_color = LLUIColorTable::instance().getColor("MeshImportTableNormalColor");
-
- for (S32 i = 0; i <= LLModel::LOD_HIGH; ++i)
- {
- const LLColor4& color = (i == lod) ? highlight_color : normal_color;
-
- mFMP->childSetColor(lod_status_name[i], color);
- mFMP->childSetColor(lod_label_name[i], color);
- mFMP->childSetColor(lod_triangles_name[i], color);
- mFMP->childSetColor(lod_vertices_name[i], color);
- }
+ mModelPreview->setPreviewLOD(lod);
}
- refresh();
- updateStatusMessages();
}
void LLFloaterModelPreview::onBrowseLOD(S32 lod)
@@ -4317,12 +1568,16 @@ void LLFloaterModelPreview::onReset(void* user_data)
{
assert_main_thread();
+
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data;
fmp->childDisable("reset_btn");
+ fmp->clearLogTab();
+ fmp->clearAvatarTab();
LLModelPreview* mp = fmp->mModelPreview;
std::string filename = mp->mLODFile[LLModel::LOD_HIGH];
fmp->resetDisplayOptions();
+ fmp->resetUploadOptions();
//reset model preview
fmp->initModelPreview();
@@ -4336,6 +1591,7 @@ void LLFloaterModelPreview::onUpload(void* user_data)
assert_main_thread();
LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data;
+ mp->clearLogTab();
mp->mUploadBtn->setEnabled(false);
@@ -4364,60 +1620,6 @@ void LLFloaterModelPreview::refresh()
sInstance->mModelPreview->mDirty = true;
}
-//static
-void LLModelPreview::textureLoadedCallback(
- BOOL success,
- LLViewerFetchedTexture *src_vi,
- LLImageRaw* src,
- LLImageRaw* src_aux,
- S32 discard_level,
- BOOL final,
- void* userdata )
-{
- LLModelPreview* preview = (LLModelPreview*) userdata;
- preview->refresh();
-
- if(final && preview->mModelLoader)
- {
- if(preview->mModelLoader->mNumOfFetchingTextures > 0)
- {
- preview->mModelLoader->mNumOfFetchingTextures-- ;
- }
- }
-}
-
-// static
-bool LLModelPreview::lodQueryCallback()
-{
- // not the best solution, but model preview belongs to floater
- // so it is an easy way to check that preview still exists.
- LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
- if (fmp && fmp->mModelPreview)
- {
- LLModelPreview* preview = fmp->mModelPreview;
- if (preview->mLodsQuery.size() > 0)
- {
- S32 lod = preview->mLodsQuery.back();
- preview->mLodsQuery.pop_back();
- preview->genLODs(lod);
-
- // return false to continue cycle
- return false;
- }
- }
- // nothing to process
- return true;
-}
-
-void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
-{
- if (!mLODFrozen)
- {
- genLODs(lod, 3, enforce_tri_limit);
- refresh();
- }
-}
-
LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl)
{
mStage = stage;
@@ -4430,6 +1632,26 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL
assignData(mdl) ;
}
+void LLFloaterModelPreview::setCtrlLoadFromFile(S32 lod)
+{
+ if (lod == LLModel::LOD_PHYSICS)
+ {
+ LLComboBox* lod_combo = findChild<LLComboBox>("physics_lod_combo");
+ if (lod_combo)
+ {
+ lod_combo->setCurrentByIndex(5);
+ }
+ }
+ else
+ {
+ LLComboBox* lod_combo = findChild<LLComboBox>("lod_source_" + lod_name[lod]);
+ if (lod_combo)
+ {
+ lod_combo->setCurrentByIndex(0);
+ }
+ }
+}
+
void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
{
LLMutexLock lock(mStatusLock);
@@ -4476,11 +1698,15 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
{
childSetTextArg("upload_fee", "[FEE]", tbd);
}
- childSetTextArg("price_breakdown", "[STREAMING]", tbd);
- childSetTextArg("price_breakdown", "[PHYSICS]", tbd);
- childSetTextArg("price_breakdown", "[INSTANCES]", tbd);
- childSetTextArg("price_breakdown", "[TEXTURES]", tbd);
- childSetTextArg("price_breakdown", "[MODEL]", tbd);
+ std::string dashes = hasString("--") ? getString("--") : "--";
+ childSetTextArg("price_breakdown", "[STREAMING]", dashes);
+ childSetTextArg("price_breakdown", "[PHYSICS]", dashes);
+ childSetTextArg("price_breakdown", "[INSTANCES]", dashes);
+ childSetTextArg("price_breakdown", "[TEXTURES]", dashes);
+ childSetTextArg("price_breakdown", "[MODEL]", dashes);
+ childSetTextArg("physics_breakdown", "[PCH]", dashes);
+ childSetTextArg("physics_breakdown", "[PM]", dashes);
+ childSetTextArg("physics_breakdown", "[PHU]", dashes);
}
}
@@ -4507,6 +1733,44 @@ void LLFloaterModelPreview::resetDisplayOptions()
}
}
+void LLFloaterModelPreview::resetUploadOptions()
+{
+ childSetValue("import_scale", 1);
+ childSetValue("pelvis_offset", 0);
+ childSetValue("physics_explode", 0);
+ childSetValue("physics_file", "");
+ childSetVisible("Retain%", false);
+ childSetVisible("Retain%_label", false);
+ childSetVisible("Detail Scale", true);
+ childSetVisible("Detail Scale label", true);
+
+ getChild<LLComboBox>("lod_source_" + lod_name[NUM_LOD - 1])->setCurrentByIndex(LLModelPreview::LOD_FROM_FILE);
+ for (S32 lod = 0; lod < NUM_LOD - 1; ++lod)
+ {
+ getChild<LLComboBox>("lod_source_" + lod_name[lod])->setCurrentByIndex(LLModelPreview::GENERATE);
+ childSetValue("lod_file_" + lod_name[lod], "");
+ }
+
+ for(auto& p : mDefaultDecompParams)
+ {
+ std::string ctrl_name(p.first);
+ LLUICtrl* ctrl = getChild<LLUICtrl>(ctrl_name);
+ if (ctrl)
+ {
+ ctrl->setValue(p.second);
+ }
+ }
+ getChild<LLComboBox>("physics_lod_combo")->setCurrentByIndex(0);
+ getChild<LLComboBox>("Cosine%")->setCurrentByIndex(0);
+}
+
+void LLFloaterModelPreview::clearLogTab()
+{
+ mUploadLogText->clear();
+ LLPanel* panel = mTabContainer->getPanelByName("logs_panel");
+ mTabContainer->setTabPanelFlashing(panel, false);
+}
+
void LLFloaterModelPreview::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url)
{
mModelPhysicsFee = result;
@@ -4530,6 +1794,16 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
childSetTextArg("price_breakdown", "[INSTANCES]", llformat("%d", result["upload_price_breakdown"]["mesh_instance"].asInteger()));
childSetTextArg("price_breakdown", "[TEXTURES]", llformat("%d", result["upload_price_breakdown"]["texture"].asInteger()));
childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger()));
+
+ childSetTextArg("physics_breakdown", "[PCH]", llformat("%0.3f", result["model_physics_cost"]["hull"].asReal()));
+ childSetTextArg("physics_breakdown", "[PM]", llformat("%0.3f", result["model_physics_cost"]["mesh"].asReal()));
+ childSetTextArg("physics_breakdown", "[PHU]", llformat("%0.3f", result["model_physics_cost"]["decomposition"].asReal()));
+ childSetTextArg("streaming_breakdown", "[STR_TOTAL]", llformat("%d", result["streaming_cost"].asInteger()));
+ childSetTextArg("streaming_breakdown", "[STR_HIGH]", llformat("%d", result["streaming_params"]["high_lod"].asInteger()));
+ childSetTextArg("streaming_breakdown", "[STR_MED]", llformat("%d", result["streaming_params"]["medium_lod"].asInteger()));
+ childSetTextArg("streaming_breakdown", "[STR_LOW]", llformat("%d", result["streaming_params"]["low_lod"].asInteger()));
+ childSetTextArg("streaming_breakdown", "[STR_LOWEST]", llformat("%d", result["streaming_params"]["lowest_lod"].asInteger()));
+
childSetVisible("upload_fee", true);
childSetVisible("price_breakdown", true);
mUploadBtn->setEnabled(isModelUploadAllowed());
@@ -4537,7 +1811,11 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived()
void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(S32 status, const std::string& reason, const LLSD& result)
{
- LL_WARNS() << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << LL_ENDL;
+ std::ostringstream out;
+ out << "LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(" << status;
+ out << " : " << reason << ")";
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
doOnIdleOneTime(boost::bind(&LLFloaterModelPreview::toggleCalculateButton, this, true));
if (result.has("upload_price"))
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 1c66570650..8a01b0c307 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -28,36 +28,26 @@
#define LL_LLFLOATERMODELPREVIEW_H
#include "llfloaternamedesc.h"
-
-#include "lldynamictexture.h"
-#include "llquaternion.h"
-#include "llmeshrepository.h"
-#include "llmodel.h"
-#include "llthread.h"
-#include "llviewermenufile.h"
#include "llfloatermodeluploadbase.h"
-
-#include "lldaeloader.h"
+#include "llmeshrepository.h"
class LLComboBox;
class LLJoint;
-class LLViewerJointMesh;
-class LLVOAvatar;
-class LLTextBox;
-class LLVertexBuffer;
+class LLMeshFilePicker;
class LLModelPreview;
-class LLFloaterModelPreview;
-class DAE;
-class daeElement;
-class domProfile_COMMON;
-class domInstance_geometry;
-class domNode;
-class domTranslate;
-class domController;
-class domSkin;
-class domMesh;
-class LLMenuButton;
-class LLToggleableMenu;
+class LLTabContainer;
+class LLViewerTextEditor;
+
+
+class LLJointOverrideData
+{
+public:
+ LLJointOverrideData() : mHasConflicts(false) {};
+ std::map<std::string, LLVector3> mPosOverrides; // models with overrides
+ std::set<std::string> mModelsNoOverrides; // models without defined overrides
+ bool mHasConflicts;
+};
+typedef std::map<std::string, LLJointOverrideData> joint_override_data_map_t;
class LLFloaterModelPreview : public LLFloaterModelUploadBase
{
@@ -80,6 +70,7 @@ public:
virtual ~LLFloaterModelPreview();
virtual BOOL postBuild();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
void initModelPreview();
@@ -93,6 +84,11 @@ public:
static void onMouseCaptureLostModelPreview(LLMouseHandler*);
static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
+ static void addStringToLog(const std::string& message, const LLSD& args, bool flash, S32 lod = -1);
+ static void addStringToLog(const std::string& str, bool flash);
+ static void addStringToLog(const std::ostringstream& strm, bool flash);
+ void clearAvatarTab(); // clears table
+ void updateAvatarTab(bool highlight_overrides); // populates table and data as nessesary
void setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost);
void setPreviewLOD(S32 lod);
@@ -107,13 +103,17 @@ public:
void loadModel(S32 lod);
void loadModel(S32 lod, const std::string& file_name, bool force_disable_slm = false);
+
+ void loadHighLodModel();
void onViewOptionChecked(LLUICtrl* ctrl);
+ void onUploadOptionChecked(LLUICtrl* ctrl);
bool isViewOptionChecked(const LLSD& userdata);
bool isViewOptionEnabled(const LLSD& userdata);
void setViewOptionEnabled(const std::string& option, bool enabled);
void enableViewOption(const std::string& option);
void disableViewOption(const std::string& option);
+ void onShowSkinWeightChecked(LLUICtrl* ctrl);
bool isModelLoading();
@@ -142,8 +142,6 @@ protected:
static void onImportScaleCommit(LLUICtrl*, void*);
static void onPelvisOffsetCommit(LLUICtrl*, void*);
- static void onUploadJointsCommit(LLUICtrl*,void*);
- static void onUploadSkinCommit(LLUICtrl*,void*);
static void onPreviewLODCommit(LLUICtrl*,void*);
@@ -154,6 +152,7 @@ protected:
static void onAutoFillCommit(LLUICtrl*,void*);
void onLODParamCommit(S32 lod, bool enforce_tri_limit);
+ void draw3dPreview();
static void onExplodeCommit(LLUICtrl*, void*);
@@ -175,11 +174,15 @@ protected:
// FIXME - this function and mStatusMessage have no visible effect, and the
// actual status messages are managed by directly manipulation of
// the UI element.
- void setStatusMessage(const std::string& msg);
+ void setStatusMessage(const std::string& msg);
+ void addStringToLogTab(const std::string& str, bool flash);
+
+ void setCtrlLoadFromFile(S32 lod);
LLModelPreview* mModelPreview;
LLPhysicsDecomp::decomp_params mDecompParams;
+ LLPhysicsDecomp::decomp_params mDefaultDecompParams;
S32 mLastMouseX;
S32 mLastMouseY;
@@ -203,223 +206,34 @@ protected:
LLSD mModelPhysicsFee;
private:
- void onClickCalculateBtn();
- void toggleCalculateButton();
+ void onClickCalculateBtn();
+ void onJointListSelection();
void onLoDSourceCommit(S32 lod);
void modelUpdated(bool calculate_visible);
// Toggles between "Calculate weights & fee" and "Upload" buttons.
+ void toggleCalculateButton();
void toggleCalculateButton(bool visible);
// resets display options of model preview to their defaults.
void resetDisplayOptions();
+ void resetUploadOptions();
+ void clearLogTab();
+
void createSmoothComboBox(LLComboBox* combo_box, float min, float max);
LLButton* mUploadBtn;
LLButton* mCalculateBtn;
-};
-
-class LLMeshFilePicker : public LLFilePickerThread
-{
-public:
- LLMeshFilePicker(LLModelPreview* mp, S32 lod);
- virtual void notify(const std::vector<std::string>& filenames);
-
-private:
- LLModelPreview* mMP;
- S32 mLOD;
-};
-
-
-class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
-{
- typedef boost::signals2::signal<void (F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t;
- typedef boost::signals2::signal<void (void)> model_loaded_signal_t;
- typedef boost::signals2::signal<void (bool)> model_updated_signal_t;
-
-public:
-
- typedef enum
- {
- LOD_FROM_FILE = 0,
- GENERATE,
- USE_LOD_ABOVE,
- } eLoDMode;
-
-public:
- LLModelPreview(S32 width, S32 height, LLFloater* fmp);
- virtual ~LLModelPreview();
-
- void resetPreviewTarget();
- void setPreviewTarget(F32 distance);
- void setTexture(U32 name) { mTextureName = name; }
-
- void setPhysicsFromLOD(S32 lod);
- BOOL render();
- void update();
- void genBuffers(S32 lod, bool skinned);
- void clearBuffers();
- void refresh();
- void rotate(F32 yaw_radians, F32 pitch_radians);
- void zoom(F32 zoom_amt);
- void pan(F32 right, F32 up);
- virtual BOOL needsRender() { return mNeedsUpdate; }
- void setPreviewLOD(S32 lod);
- void clearModel(S32 lod);
- void getJointAliases(JointMap& joint_map);
- void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
- void loadModelCallback(S32 lod);
- bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
- void queryLODs() { mGenLOD = true; };
- void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
- void generateNormals();
- void restoreNormals();
- U32 calcResourceCost();
- void rebuildUploadData();
- void saveUploadData(bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position);
- void saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position);
- void clearIncompatible(S32 lod);
- void updateStatusMessages();
- void updateLodControls(S32 lod);
- void clearGLODGroup();
- void onLODParamCommit(S32 lod, bool enforce_tri_limit);
- void addEmptyFace( LLModel* pTarget );
-
- const bool getModelPivot( void ) const { return mHasPivot; }
- void setHasPivot( bool val ) { mHasPivot = val; }
- void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
-
- //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
- //Accessors for joint position upload friendly rigs
- const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
- void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
-
- //Accessors for the legacy rigs
- const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
- void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
-
- static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
- static bool lodQueryCallback();
-
- boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){ return mDetailsSignal.connect(cb); }
- boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){ return mModelLoadedSignal.connect(cb); }
- boost::signals2::connection setModelUpdatedCallback( const model_updated_signal_t::slot_type& cb ){ return mModelUpdatedSignal.connect(cb); }
-
- void setLoadState( U32 state ) { mLoadState = state; }
- U32 getLoadState() { return mLoadState; }
-
- static bool sIgnoreLoadedCallback;
- std::vector<S32> mLodsQuery;
- std::vector<S32> mLodsWithParsingError;
-
-protected:
-
- static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque);
- static void stateChangedCallback(U32 state, void* opaque);
-
- static LLJoint* lookupJointByName(const std::string&, void* opaque);
- static U32 loadTextures(LLImportMaterial& material, void* opaque);
-
-private:
- //Utility function for controller vertex compare
- bool verifyCount( int expected, int result );
- //Creates the dummy avatar for the preview window
- void createPreviewAvatar( void );
- //Accessor for the dummy avatar
- LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
- // Count amount of original models, excluding sub-models
- static U32 countRootModels(LLModelLoader::model_list models);
-
- protected:
- friend class LLModelLoader;
- friend class LLFloaterModelPreview;
- friend class LLFloaterModelPreview::DecompRequest;
- friend class LLPhysicsDecomp;
-
- LLFloater* mFMP;
-
- BOOL mNeedsUpdate;
- bool mDirty;
- bool mGenLOD;
- U32 mTextureName;
- F32 mCameraDistance;
- F32 mCameraYaw;
- F32 mCameraPitch;
- F32 mCameraZoom;
- LLVector3 mCameraOffset;
- LLVector3 mPreviewTarget;
- LLVector3 mPreviewScale;
- S32 mPreviewLOD;
- S32 mPhysicsSearchLOD;
- U32 mResourceCost;
- std::string mLODFile[LLModel::NUM_LODS];
- bool mLoading;
- U32 mLoadState;
- bool mResetJoints;
- bool mModelNoErrors;
-
- std::map<std::string, bool> mViewOption;
-
- //GLOD object parameters (must rebuild object if these change)
- bool mLODFrozen;
- F32 mBuildShareTolerance;
- U32 mBuildQueueMode;
- U32 mBuildOperator;
- U32 mBuildBorderMode;
- U32 mRequestedLoDMode[LLModel::NUM_LODS];
- S32 mRequestedTriangleCount[LLModel::NUM_LODS];
- F32 mRequestedErrorThreshold[LLModel::NUM_LODS];
- U32 mRequestedBuildOperator[LLModel::NUM_LODS];
- U32 mRequestedQueueMode[LLModel::NUM_LODS];
- U32 mRequestedBorderMode[LLModel::NUM_LODS];
- F32 mRequestedShareTolerance[LLModel::NUM_LODS];
- F32 mRequestedCreaseAngle[LLModel::NUM_LODS];
-
- LLModelLoader* mModelLoader;
-
- LLModelLoader::scene mScene[LLModel::NUM_LODS];
- LLModelLoader::scene mBaseScene;
-
- LLModelLoader::model_list mModel[LLModel::NUM_LODS];
- LLModelLoader::model_list mBaseModel;
-
- typedef std::vector<LLVolumeFace> v_LLVolumeFace_t;
- typedef std::vector<v_LLVolumeFace_t> vv_LLVolumeFace_t;
-
- vv_LLVolumeFace_t mModelFacesCopy[LLModel::NUM_LODS];
- vv_LLVolumeFace_t mBaseModelFacesCopy;
-
- U32 mGroup;
- std::map<LLPointer<LLModel>, U32> mObject;
- U32 mMaxTriangleLimit;
-
- LLMeshUploadThread::instance_list mUploadData;
- std::set<LLViewerFetchedTexture * > mTextureSet;
-
- //map of vertex buffers to models (one vertex buffer in vector per face in model
- std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS+1];
-
- details_signal_t mDetailsSignal;
- model_loaded_signal_t mModelLoadedSignal;
- model_updated_signal_t mModelUpdatedSignal;
-
- LLVector3 mModelPivot;
- bool mHasPivot;
-
- float mPelvisZOffset;
-
- bool mRigValidJointUpload;
- bool mLegacyRigValid;
-
- bool mLastJointUpdate;
+ LLViewerTextEditor* mUploadLogText;
+ LLTabContainer* mTabContainer;
- JointNameSet mJointsFromNode;
- JointTransformMap mJointTransformMap;
+ S32 mAvatarTabIndex; // just to avoid any issues in case of xml changes
+ std::string mSelectedJointName;
- LLPointer<LLVOAvatar> mPreviewAvatar;
+ joint_override_data_map_t mJointOverrides[LLModel::NUM_LODS];
};
#endif // LL_LLFLOATERMODELPREVIEW_H
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 3968f43485..649a107d74 100644
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -178,7 +178,6 @@ void LLFloaterPermsDefault::sendInitialPerms()
if(!mCapSent)
{
updateCap();
- setCapSent(true);
}
}
@@ -240,7 +239,7 @@ void LLFloaterPermsDefault::updateCapCoro(std::string url)
{
const std::string& reason = status.toString();
// Do not display the same error more than once in a row
- if (reason != previousReason)
+ if ((reason != previousReason) && mCapSent)
{
previousReason = reason;
LLSD args;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 81f4b2234c..1cd8841bb4 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1094,6 +1094,7 @@ void LLFloaterPreference::onBtnCancel(const LLSD& userdata)
if (userdata.asString() == "closeadvanced")
{
LLFloaterReg::hideInstance("prefs_graphics_advanced");
+ updateMaxComplexity();
}
else
{
@@ -1321,9 +1322,11 @@ void LLFloaterPreference::refreshEnabledState()
//Deferred/SSAO/Shadows
BOOL bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump");
+ BOOL transparent_water = LLFeatureManager::getInstance()->isFeatureAvailable("RenderTransparentWater") && gSavedSettings.getBOOL("RenderTransparentWater");
BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
bumpshiny &&
+ transparent_water &&
shaders &&
gGLManager.mHasFramebufferObject &&
gSavedSettings.getBOOL("RenderAvatarVP") &&
@@ -1346,7 +1349,10 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps;
ctrl_reflections->setEnabled(reflections);
reflections_text->setEnabled(reflections);
-
+
+ // Transparent Water
+ LLCheckBoxCtrl* transparent_water_ctrl = getChild<LLCheckBoxCtrl>("TransparentWater");
+
// Bump & Shiny
LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
@@ -1397,6 +1403,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
+ ((transparent_water_ctrl && transparent_water_ctrl->get()) ? TRUE : FALSE) &&
gGLManager.mHasFramebufferObject &&
gSavedSettings.getBOOL("RenderAvatarVP") &&
(ctrl_wind_light->get()) ? TRUE : FALSE;
@@ -1926,6 +1933,8 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
getChildView("log_path_button")->setEnabled(TRUE);
getChildView("chat_font_size")->setEnabled(TRUE);
getChildView("conversation_log_combo")->setEnabled(TRUE);
+ getChild<LLUICtrl>("voice_call_friends_only_check")->setEnabled(TRUE);
+ getChild<LLUICtrl>("voice_call_friends_only_check")->setValue(gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly"));
}
@@ -2034,6 +2043,14 @@ void LLFloaterPreference::updateMaxComplexity()
LLAvatarComplexityControls::updateMax(
getChild<LLSliderCtrl>("IndirectMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText"));
+
+ LLFloaterPreferenceGraphicsAdvanced* floater_graphics_advanced = LLFloaterReg::findTypedInstance<LLFloaterPreferenceGraphicsAdvanced>("prefs_graphics_advanced");
+ if (floater_graphics_advanced)
+ {
+ LLAvatarComplexityControls::updateMax(
+ floater_graphics_advanced->getChild<LLSliderCtrl>("IndirectMaxComplexity"),
+ floater_graphics_advanced->getChild<LLTextBox>("IndirectMaxComplexityText"));
+ }
}
bool LLFloaterPreference::loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map)
@@ -2081,6 +2098,14 @@ void LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity()
LLAvatarComplexityControls::updateMax(
getChild<LLSliderCtrl>("IndirectMaxComplexity"),
getChild<LLTextBox>("IndirectMaxComplexityText"));
+
+ LLFloaterPreference* floater_preferences = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+ if (floater_preferences)
+ {
+ LLAvatarComplexityControls::updateMax(
+ floater_preferences->getChild<LLSliderCtrl>("IndirectMaxComplexity"),
+ floater_preferences->getChild<LLTextBox>("IndirectMaxComplexityText"));
+ }
}
void LLFloaterPreference::onChangeMaturity()
@@ -2554,9 +2579,13 @@ void LLPanelPreference::showMultipleViewersWarning(LLUICtrl* checkbox, const LLS
void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& value)
{
- if (checkbox && checkbox->getValue())
+ if (checkbox)
{
- LLNotificationsUtil::add("FriendsAndGroupsOnly");
+ gSavedPerAccountSettings.setBOOL("VoiceCallsFriendsOnly", checkbox->getValue().asBoolean());
+ if (checkbox->getValue())
+ {
+ LLNotificationsUtil::add("FriendsAndGroupsOnly");
+ }
}
}
@@ -2659,7 +2688,6 @@ class LLPanelPreferencePrivacy : public LLPanelPreference
public:
LLPanelPreferencePrivacy()
{
- mAccountIndependentSettings.push_back("VoiceCallsFriendsOnly");
mAccountIndependentSettings.push_back("AutoDisengageMic");
}
@@ -2916,6 +2944,7 @@ void LLFloaterPreferenceGraphicsAdvanced::onClickCloseBtn(bool app_quitting)
{
instance->cancel();
}
+ updateMaxComplexity();
}
LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy()
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 702d612343..7bfba2a6d7 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -930,7 +930,7 @@ void LLFloaterReporter::takeNewSnapshot()
// Take a screenshot, but don't draw this floater.
setVisible(FALSE);
- if (!gViewerWindow->rawSnapshot(mImageRaw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, gSavedSettings.getBOOL("RenderHUDInSnapshot"), TRUE, FALSE))
+ if (!gViewerWindow->rawSnapshot(mImageRaw,IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE /*UI*/, TRUE, FALSE))
{
LL_WARNS() << "Unable to take screenshot" << LL_ENDL;
setVisible(TRUE);
diff --git a/indra/newview/llfloatersaveprefpreset.cpp b/indra/newview/llfloatersaveprefpreset.cpp
index 5f3cf9d95b..dd47d02bfa 100644
--- a/indra/newview/llfloatersaveprefpreset.cpp
+++ b/indra/newview/llfloatersaveprefpreset.cpp
@@ -86,7 +86,10 @@ void LLFloaterSavePrefPreset::onBtnSave()
{
std::string name = mPresetCombo->getSimple();
- if ((name == LLTrans::getString(PRESETS_DEFAULT)) || (name == PRESETS_DEFAULT))
+ std::string upper_name(name);
+ LLStringUtil::toUpper(upper_name);
+
+ if ((name == LLTrans::getString(PRESETS_DEFAULT)) || (upper_name == PRESETS_DEFAULT_UPPER))
{
LLNotificationsUtil::add("DefaultPresetNotSaved");
}
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index bcba14d63d..8221b0a637 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -34,6 +34,7 @@
class LLSpinCtrl;
class LLSnapshotLivePreview;
+class LLToolset;
class LLFloaterSnapshotBase : public LLFloater
{
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index fce945df6c..97e99297cf 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -33,7 +33,6 @@
#define LL_LLFLOATERWORLDMAP_H
#include "llfloater.h"
-#include "llhudtext.h"
#include "llmapimagetype.h"
#include "lltracker.h"
#include "llslurl.h"
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index dbf7639539..32f88b49ac 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -944,10 +944,14 @@ static void formatDateString(std::string &date_string)
}
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_MEMBERS_REPLY("Process Group Members");
+
// static
void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
{
- LL_DEBUGS() << "LLGroupMgr::processGroupMembersReply" << LL_ENDL;
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_MEMBERS_REPLY);
+
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupMembersReply" << LL_ENDL;
LLUUID agent_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
if (gAgent.getID() != agent_id)
@@ -1050,10 +1054,14 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_PROPERTIES_REPLY("Process Group Properties");
+
//static
void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
{
- LL_DEBUGS() << "LLGroupMgr::processGroupPropertiesReply" << LL_ENDL;
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_PROPERTIES_REPLY);
+
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupPropertiesReply" << LL_ENDL;
if (!msg)
{
LL_ERRS() << "Can't access the messaging system" << LL_ENDL;
@@ -1119,13 +1127,25 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
group_datap->mGroupPropertiesDataComplete = true;
group_datap->mChanged = TRUE;
+ properties_request_map_t::iterator request = LLGroupMgr::getInstance()->mPropRequests.find(group_id);
+ if (request != LLGroupMgr::getInstance()->mPropRequests.end())
+ {
+ LLGroupMgr::getInstance()->mPropRequests.erase(request);
+ }
+ else
+ {
+ LL_DEBUGS("GrpMgr") << "GroupPropertyResponse received with no pending request. Response was slow." << LL_ENDL;
+ }
LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_ROLE_DATA_REPLY("Process Group Role Data");
// static
void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
{
- LL_DEBUGS() << "LLGroupMgr::processGroupRoleDataReply" << LL_ENDL;
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_ROLE_DATA_REPLY);
+
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleDataReply" << LL_ENDL;
LLUUID agent_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
if (gAgent.getID() != agent_id)
@@ -1186,7 +1206,7 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
- LL_DEBUGS() << "Adding role data: " << name << " {" << role_id << "}" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "Adding role data: " << name << " {" << role_id << "}" << LL_ENDL;
LLGroupRoleData* rd = new LLGroupRoleData(role_id,name,title,desc,powers,member_count);
group_datap->mRoles[role_id] = rd;
}
@@ -1207,10 +1227,13 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA);
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_ROLE_MEMBERS_REPLY("Process Group Role Members");
// static
void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
{
- LL_DEBUGS() << "LLGroupMgr::processGroupRoleMembersReply" << LL_ENDL;
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_ROLE_MEMBERS_REPLY);
+
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleMembersReply" << LL_ENDL;
LLUUID agent_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
if (gAgent.getID() != agent_id)
@@ -1271,7 +1294,7 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
if (rd && md)
{
- LL_DEBUGS() << "Adding role-member pair: " << role_id << ", " << member_id << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "Adding role-member pair: " << role_id << ", " << member_id << LL_ENDL;
rd->addMember(member_id);
md->addRole(role_id,rd);
}
@@ -1323,7 +1346,7 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
// static
void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
{
- LL_DEBUGS() << "LLGroupMgr::processGroupTitlesReply" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupTitlesReply" << LL_ENDL;
LLUUID agent_id;
msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
if (gAgent.getID() != agent_id)
@@ -1356,7 +1379,7 @@ void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
if (!title.mTitle.empty())
{
- LL_DEBUGS() << "LLGroupMgr adding title: " << title.mTitle << ", " << title.mRoleID << ", " << (title.mSelected ? 'Y' : 'N') << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr adding title: " << title.mTitle << ", " << title.mRoleID << ", " << (title.mSelected ? 'Y' : 'N') << LL_ENDL;
group_datap->mTitles.push_back(title);
}
}
@@ -1368,7 +1391,7 @@ void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
// static
void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data)
{
- LL_DEBUGS() << "processEjectGroupMemberReply" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "processEjectGroupMemberReply" << LL_ENDL;
LLUUID group_id;
msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
BOOL success;
@@ -1384,7 +1407,7 @@ void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data
// static
void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
{
- LL_DEBUGS() << "processJoinGroupReply" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "processJoinGroupReply" << LL_ENDL;
LLUUID group_id;
BOOL success;
msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
@@ -1404,7 +1427,7 @@ void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
// static
void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void ** data)
{
- LL_DEBUGS() << "processLeaveGroupReply" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "processLeaveGroupReply" << LL_ENDL;
LLUUID group_id;
BOOL success;
msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
@@ -1488,6 +1511,28 @@ LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
return group_datap;
}
+bool LLGroupMgr::hasPendingPropertyRequest(const LLUUID & id)
+{
+ properties_request_map_t::iterator existing_req = LLGroupMgr::getInstance()->mPropRequests.find(id);
+ if (existing_req != LLGroupMgr::getInstance()->mPropRequests.end())
+ {
+ if (gFrameTime - existing_req->second < MIN_GROUP_PROPERTY_REQUEST_FREQ)
+ {
+ return true;
+ }
+ else
+ {
+ LLGroupMgr::getInstance()->mPropRequests.erase(existing_req);
+ }
+ }
+ return false;
+}
+
+void LLGroupMgr::addPendingPropertyRequest(const LLUUID& id)
+{
+ LLGroupMgr::getInstance()->mPropRequests[id] = gFrameTime;
+}
+
void LLGroupMgr::notifyObservers(LLGroupChange gc)
{
for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi)
@@ -1566,10 +1611,17 @@ void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap)
void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupPropertiesRequest" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupPropertiesRequest" << LL_ENDL;
// This will happen when we get the reply
//LLGroupMgrGroupData* group_datap = createGroupData(group_id);
+ if (LLGroupMgr::getInstance()->hasPendingPropertyRequest(group_id))
+ {
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupPropertiesRequest suppressed repeat for " << group_id << LL_ENDL;
+ return;
+ }
+ LLGroupMgr::getInstance()->addPendingPropertyRequest(group_id);
+
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("GroupProfileRequest");
msg->nextBlock("AgentData");
@@ -1582,7 +1634,7 @@ void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupMembersRequest" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupMembersRequest" << LL_ENDL;
LLGroupMgrGroupData* group_datap = createGroupData(group_id);
if (group_datap->mMemberRequestID.isNull())
{
@@ -1604,7 +1656,7 @@ void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id)
void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupRoleDataRequest" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupRoleDataRequest" << LL_ENDL;
LLGroupMgrGroupData* group_datap = createGroupData(group_id);
if (group_datap->mRoleDataRequestID.isNull())
{
@@ -1625,7 +1677,7 @@ void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id)
void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupRoleMembersRequest" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupRoleMembersRequest" << LL_ENDL;
LLGroupMgrGroupData* group_datap = createGroupData(group_id);
if (group_datap->mRoleMembersRequestID.isNull())
@@ -1635,7 +1687,7 @@ void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
|| !group_datap->isRoleDataComplete())
{
// *TODO: KLW FIXME: Should we start a member or role data request?
- LL_INFOS() << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")
+ LL_INFOS("GrpMgr") << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")
<< " MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")
<< " RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << LL_ENDL;
group_datap->mPendingRoleMemberRequest = TRUE;
@@ -1659,7 +1711,7 @@ void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
void LLGroupMgr::sendGroupTitlesRequest(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupTitlesRequest" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupTitlesRequest" << LL_ENDL;
LLGroupMgrGroupData* group_datap = createGroupData(group_id);
group_datap->mTitles.clear();
@@ -1678,7 +1730,7 @@ void LLGroupMgr::sendGroupTitlesRequest(const LLUUID& group_id)
void LLGroupMgr::sendGroupTitleUpdate(const LLUUID& group_id, const LLUUID& title_role_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupTitleUpdate" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupTitleUpdate" << LL_ENDL;
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("GroupTitleUpdate");
@@ -1737,7 +1789,7 @@ void LLGroupMgr::sendCreateGroupRequest(const std::string& name,
void LLGroupMgr::sendUpdateGroupInfo(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendUpdateGroupInfo" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendUpdateGroupInfo" << LL_ENDL;
LLGroupMgrGroupData* group_datap = createGroupData(group_id);
LLMessageSystem* msg = gMessageSystem;
@@ -1766,7 +1818,7 @@ void LLGroupMgr::sendUpdateGroupInfo(const LLUUID& group_id)
void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupRoleMemberChanges" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupRoleMemberChanges" << LL_ENDL;
LLGroupMgrGroupData* group_datap = createGroupData(group_id);
if (group_datap->mRoleMemberChanges.empty()) return;
@@ -2313,7 +2365,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::sendGroupRoleChanges" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupRoleChanges" << LL_ENDL;
LLGroupMgrGroupData* group_datap = getGroupData(group_id);
if (group_datap && group_datap->pendingRoleChanges())
@@ -2328,7 +2380,7 @@ void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
void LLGroupMgr::cancelGroupRoleChanges(const LLUUID& group_id)
{
- LL_DEBUGS() << "LLGroupMgr::cancelGroupRoleChanges" << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "LLGroupMgr::cancelGroupRoleChanges" << LL_ENDL;
LLGroupMgrGroupData* group_datap = getGroupData(group_id);
if (group_datap) group_datap->cancelRoleChanges();
@@ -2362,7 +2414,7 @@ bool LLGroupMgr::parseRoleActions(const std::string& xml_filename)
std::string action_set_name;
if (action_set->getAttributeString("name", action_set_name))
{
- LL_DEBUGS() << "Loading action set " << action_set_name << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "Loading action set " << action_set_name << LL_ENDL;
role_action_data->mName = action_set_name;
}
else
@@ -2403,7 +2455,7 @@ bool LLGroupMgr::parseRoleActions(const std::string& xml_filename)
std::string action_name;
if (action->getAttributeString("name", action_name))
{
- LL_DEBUGS() << "Loading action " << action_name << LL_ENDL;
+ LL_DEBUGS("GrpMgr") << "Loading action " << action_name << LL_ENDL;
role_action->mName = action_name;
}
else
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index cf9735e38a..0d25e8fb22 100644
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -448,6 +448,8 @@ private:
void notifyObserver(const LLUUID& group_id, LLGroupChange gc);
void addGroup(LLGroupMgrGroupData* group_datap);
LLGroupMgrGroupData* createGroupData(const LLUUID &id);
+ bool hasPendingPropertyRequest(const LLUUID& id);
+ void addPendingPropertyRequest(const LLUUID& id);
typedef std::multimap<LLUUID,LLGroupMgrObserver*> observer_multimap_t;
observer_multimap_t mObservers;
@@ -455,6 +457,10 @@ private:
typedef std::map<LLUUID, LLGroupMgrGroupData*> group_map_t;
group_map_t mGroups;
+ const U64MicrosecondsImplicit MIN_GROUP_PROPERTY_REQUEST_FREQ = 100000;//100ms between requests should be enough to avoid spamming.
+ typedef std::map<LLUUID, U64MicrosecondsImplicit> properties_request_map_t;
+ properties_request_map_t mPropRequests;
+
typedef std::set<LLParticularGroupObserver*> observer_set_t;
typedef std::map<LLUUID,observer_set_t> observer_map_t;
observer_map_t mParticularObservers;
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index 81d862a827..4ed802138d 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -415,7 +415,8 @@ void LLHUDNameTag::clearString()
void LLHUDNameTag::addLine(const std::string &text_utf8,
const LLColor4& color,
const LLFontGL::StyleFlags style,
- const LLFontGL* font)
+ const LLFontGL* font,
+ const bool use_ellipses)
{
LLWString wline = utf8str_to_wstring(text_utf8);
if (!wline.empty())
@@ -432,18 +433,52 @@ void LLHUDNameTag::addLine(const std::string &text_utf8,
tokenizer tokens(wline, sep);
tokenizer::iterator iter = tokens.begin();
- while (iter != tokens.end())
- {
- U32 line_length = 0;
- do
- {
- F32 max_pixels = HUD_TEXT_MAX_WIDTH;
- S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
- LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
- mTextSegments.push_back(segment);
- line_length += segment_length;
- }
- while (line_length != iter->size());
+ const F32 max_pixels = HUD_TEXT_MAX_WIDTH;
+ while (iter != tokens.end())
+ {
+ U32 line_length = 0;
+ if (use_ellipses)
+ {
+ // "QualityAssuranceAssuresQuality1" will end up like "QualityAssuranceAssuresQual..."
+ // "QualityAssuranceAssuresQuality QualityAssuranceAssuresQuality" will end up like "QualityAssuranceAssuresQual..."
+ // "QualityAssurance AssuresQuality1" will end up as "QualityAssurance AssuresQua..." because we are enforcing single line
+ do
+ {
+ S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::ANYWHERE);
+ if (segment_length + line_length < wline.length()) // since we only draw one string, line_length should be 0
+ {
+ // token does does not fit into signle line, need to draw "...".
+ // Use four dots for ellipsis width to generate padding
+ const LLWString dots_pad(utf8str_to_wstring(std::string("....")));
+ S32 elipses_width = font->getWidthF32(dots_pad.c_str());
+ // truncated string length
+ segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels - elipses_width, wline.length(), LLFontGL::ANYWHERE);
+ const LLWString dots(utf8str_to_wstring(std::string("...")));
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length) + dots, style, color, font);
+ mTextSegments.push_back(segment);
+ break; // consider it to be complete
+ }
+ else
+ {
+ // token fits fully into string
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+ mTextSegments.push_back(segment);
+ line_length += segment_length;
+ }
+ } while (line_length != iter->size());
+ }
+ else
+ {
+ // "QualityAssuranceAssuresQuality 1" will be split into two lines "QualityAssuranceAssuresQualit" and "y 1"
+ // "QualityAssurance AssuresQuality 1" will be split into two lines "QualityAssurance" and "AssuresQuality"
+ do
+ {
+ S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+ mTextSegments.push_back(segment);
+ line_length += segment_length;
+ } while (line_length != iter->size());
+ }
++iter;
}
}
diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h
index 38a4f18415..20272a8232 100644
--- a/indra/newview/llhudnametag.h
+++ b/indra/newview/llhudnametag.h
@@ -92,7 +92,7 @@ public:
void clearString();
// Add text a line at a time, allowing custom formatting
- void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
+ void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL, const bool use_ellipses = false);
// For bubble chat, set the part above the chat text
void setLabel(const std::string& label_utf8);
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index 2f7a98c86c..ce128519ea 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -102,7 +102,7 @@ protected:
static void sortObjects();
LLHUDObject(const U8 type);
- ~LLHUDObject();
+ virtual ~LLHUDObject();
virtual void render() = 0;
virtual void renderForTimer() {};
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 82824861a9..72d28a3d44 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -565,7 +565,10 @@ S32 LLHUDText::getMaxLines()
void LLHUDText::markDead()
{
- sTextObjects.erase(LLPointer<LLHUDText>(this));
+ // make sure we have at least one pointer
+ // till the end of the function
+ LLPointer<LLHUDText> ptr(this);
+ sTextObjects.erase(ptr);
LLHUDObject::markDead();
}
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index e1b58dde51..1e43e4ea3a 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -450,7 +450,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
|| (dialog == IM_FROM_TASK && LLMuteList::getInstance()->isMuted(session_id));
BOOL is_owned_by_me = FALSE;
BOOL is_friend = (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL) ? false : true;
- BOOL accept_im_from_only_friend = gSavedSettings.getBOOL("VoiceCallsFriendsOnly");
+ BOOL accept_im_from_only_friend = gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly");
BOOL is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT &&
LLMuteList::getInstance()->isLinden(name);
@@ -1164,7 +1164,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
{
return;
}
- else if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL))
+ else if (gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(from_id) == NULL))
{
return;
}
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index d5142a4496..d17bb982e1 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -515,6 +515,7 @@ LLIMModel::LLIMModel()
{
addNewMsgCallback(boost::bind(&LLFloaterIMSession::newIMCallback, _1));
addNewMsgCallback(boost::bind(&on_new_message, _1));
+ LLCallDialogManager::instance();
}
LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const uuid_vec_t& ids, bool voice, bool has_offline_msg)
@@ -2683,7 +2684,7 @@ void LLIMMgr::addMessage(
}
bool skip_message = false;
bool from_linden = LLMuteList::getInstance()->isLinden(from);
- if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && !from_linden)
+ if (gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly") && !from_linden)
{
// Evaluate if we need to skip this message when that setting is true (default is false)
skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends...
@@ -2742,7 +2743,7 @@ void LLIMMgr::addMessage(
}
//Play sound for new conversations
- if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE))
+ if (!skip_message & !gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE))
{
make_ui_sound("UISndNewIncomingIMSession");
}
@@ -3072,7 +3073,7 @@ void LLIMMgr::inviteToSession(
if (voice_invite)
{
bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup"));
- bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL));
+ bool isRejectNonFriendCall = (gSavedPerAccountSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL));
if (isRejectGroupCall || isRejectNonFriendCall || gAgent.isDoNotDisturb())
{
if (gAgent.isDoNotDisturb() && !isRejectGroupCall && !isRejectNonFriendCall)
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 657c65c68d..e9aaca13eb 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4101,12 +4101,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.push_back(std::string("New Body Parts"));
items.push_back(std::string("New Settings"));
items.push_back(std::string("upload_def"));
-
- if (!LLEnvironment::instance().isInventoryEnabled())
- {
- disabled_items.push_back("New Settings");
- }
-
}
}
getClipboardEntries(false, items, disabled_items, flags);
@@ -6385,6 +6379,14 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
{
LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding.
}
+ else if ("touch" == action)
+ {
+ handle_attachment_touch(mUUID);
+ }
+ else if ("edit" == action)
+ {
+ handle_attachment_edit(mUUID);
+ }
else if (isRemoveAction(action))
{
LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
@@ -6535,6 +6537,19 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
if( get_is_item_worn( mUUID ) )
{
items.push_back(std::string("Wearable And Object Separator"));
+
+ items.push_back(std::string("Attachment Touch"));
+ if ( ((flags & FIRST_SELECTED_ITEM) == 0) || !enable_attachment_touch(mUUID) )
+ {
+ disabled_items.push_back(std::string("Attachment Touch"));
+ }
+
+ items.push_back(std::string("Wearable Edit"));
+ if ( ((flags & FIRST_SELECTED_ITEM) == 0) || !get_is_item_editable(mUUID) )
+ {
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+
items.push_back(std::string("Detach From Yourself"));
}
else if (!isItemInTrash() && !isLinkedObjectInTrash() && !isLinkedObjectMissing() && !isCOFFolder())
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 745b953996..72013f7396 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -192,10 +192,15 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
// when applying a filter, matching folders get their contents downloaded first
// but make sure we are not interfering with pre-download
if (isNotDefault()
- && !gInventory.isCategoryComplete(folder_id)
&& LLStartUp::getStartupState() > STATE_WEARABLES_WAIT)
- {
- LLInventoryModelBackgroundFetch::instance().start(folder_id);
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id);
+ if (!cat || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN))
+ {
+ // At the moment background fetch only cares about VERSION_UNKNOWN,
+ // so do not check isCategoryComplete that compares descendant count
+ LLInventoryModelBackgroundFetch::instance().start(folder_id);
+ }
}
// Marketplace folder filtering
@@ -287,21 +292,34 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent
// Pass if this item's type is of the correct filter type
if (filterTypes & FILTERTYPE_OBJECT)
{
-
- // If it has no type, pass it, unless it's a link.
- if (object_type == LLInventoryType::IT_NONE)
- {
- if (object && object->getIsLinkType())
- {
- return FALSE;
- }
- }
- else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
- {
- return FALSE;
- }
+ switch (object_type)
+ {
+ case LLInventoryType::IT_NONE:
+ // If it has no type, pass it, unless it's a link.
+ if (object && object->getIsLinkType())
+ {
+ return FALSE;
+ }
+ break;
+ case LLInventoryType::IT_UNKNOWN:
+ {
+ // Unknows are only shown when we show every type.
+ // Unknows are 255 and won't fit in 64 bits.
+ if (mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL)
+ {
+ return FALSE;
+ }
+ break;
+ }
+ default:
+ if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
+ {
+ return FALSE;
+ }
+ break;
+ }
}
-
+
if(filterTypes & FILTERTYPE_WORN)
{
if (!get_is_item_worn(object_id))
@@ -426,18 +444,32 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) cons
// Pass if this item's type is of the correct filter type
if (filterTypes & FILTERTYPE_OBJECT)
{
- // If it has no type, pass it, unless it's a link.
- if (object_type == LLInventoryType::IT_NONE)
- {
- if (item && item->getIsLinkType())
- {
- return false;
- }
- }
- else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
- {
- return false;
- }
+ switch (object_type)
+ {
+ case LLInventoryType::IT_NONE:
+ // If it has no type, pass it, unless it's a link.
+ if (item && item->getIsLinkType())
+ {
+ return FALSE;
+ }
+ break;
+ case LLInventoryType::IT_UNKNOWN:
+ {
+ // Unknows are only shown when we show every type.
+ // Unknows are 255 and won't fit in 64 bits.
+ if (mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL)
+ {
+ return FALSE;
+ }
+ break;
+ }
+ default:
+ if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
+ {
+ return FALSE;
+ }
+ break;
+ }
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 646d92b9e1..d069aa3223 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -78,6 +78,7 @@
#include "lltooldraganddrop.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
+#include "llviewermenu.h"
#include "llviewermessage.h"
#include "llviewerfoldertype.h"
#include "llviewerobjectlist.h"
@@ -655,6 +656,50 @@ BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id)
return TRUE;
}
+bool get_is_item_editable(const LLUUID& inv_item_id)
+{
+ if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id))
+ {
+ switch (inv_item->getType())
+ {
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ return gAgentWearables.isWearableModifiable(inv_item_id);
+ case LLAssetType::AT_OBJECT:
+ return true;
+ default:
+ return false;;
+ }
+ }
+ return gAgentAvatarp->getWornAttachment(inv_item_id) != nullptr;
+}
+
+void handle_item_edit(const LLUUID& inv_item_id)
+{
+ if (get_is_item_editable(inv_item_id))
+ {
+ if (const LLInventoryItem* inv_item = gInventory.getLinkedItem(inv_item_id))
+ {
+ switch (inv_item->getType())
+ {
+ case LLAssetType::AT_BODYPART:
+ case LLAssetType::AT_CLOTHING:
+ LLAgentWearables::editWearable(inv_item_id);
+ break;
+ case LLAssetType::AT_OBJECT:
+ handle_attachment_edit(inv_item_id);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ handle_attachment_edit(inv_item_id);
+ }
+ }
+}
+
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)
{
// NOTE: This function doesn't check the folder's children.
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index fd106bc2d8..04eb962372 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -53,6 +53,10 @@ BOOL get_can_item_be_worn(const LLUUID& id);
BOOL get_is_item_removable(const LLInventoryModel* model, const LLUUID& id);
+// Performs the appropiate edit action (if one exists) for this item
+bool get_is_item_editable(const LLUUID& inv_item_id);
+void handle_item_edit(const LLUUID& inv_item_id);
+
BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id);
BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id);
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 17e80dca89..28db6a5808 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -56,6 +56,7 @@
#include "llcallbacklist.h"
#include "llvoavatarself.h"
#include "llgesturemgr.h"
+#include "llsdserialize.h"
#include "llsdutil.h"
#include "bufferarray.h"
#include "bufferstream.h"
@@ -76,8 +77,8 @@ BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;
///----------------------------------------------------------------------------
//BOOL decompress_file(const char* src_filename, const char* dst_filename);
-static const char PRODUCTION_CACHE_FORMAT_STRING[] = "%s.inv";
-static const char GRID_CACHE_FORMAT_STRING[] = "%s.%s.inv";
+static const char PRODUCTION_CACHE_FORMAT_STRING[] = "%s.inv.llsd";
+static const char GRID_CACHE_FORMAT_STRING[] = "%s.%s.inv.llsd";
static const char * const LOG_INV("Inventory");
struct InventoryIDPtrLess
@@ -678,17 +679,59 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
LLUUID categoryId = result["folder_id"].asUUID();
- // Add the category to the internal representation
- LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId,
- result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(),
- result["name"].asString(), gAgent.getID());
+ LLViewerInventoryCategory* folderp = gInventory.getCategory(categoryId);
+ if (!folderp)
+ {
+ // Add the category to the internal representation
+ LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId,
+ result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(),
+ result["name"].asString(), gAgent.getID());
- cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
- cat->setDescendentCount(0);
- LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
-
- accountForUpdate(update);
- updateCategory(cat);
+ LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
+ accountForUpdate(update);
+
+ cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
+ cat->setDescendentCount(0);
+ updateCategory(cat);
+ }
+ else
+ {
+ // bulk processing was faster than coroutine (coro request->processBulkUpdateInventory->coro response)
+ // category already exists, but needs an update
+ if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_INITIAL
+ || folderp->getDescendentCount() != LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
+ {
+ LL_WARNS() << "Inventory desync on folder creation. Newly created folder already has descendants or got a version.\n"
+ << "Name: " << folderp->getName()
+ << " Id: " << folderp->getUUID()
+ << " Version: " << folderp->getVersion()
+ << " Descendants: " << folderp->getDescendentCount()
+ << LL_ENDL;
+ }
+ // Recreate category with correct values
+ // Creating it anew just simplifies figuring out needed change-masks
+ // and making all needed updates, see updateCategory
+ LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(categoryId,
+ result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(),
+ result["name"].asString(), gAgent.getID());
+
+ if (folderp->getParentUUID() != cat->getParentUUID())
+ {
+ LL_WARNS() << "Inventory desync on folder creation. Newly created folder has wrong parent.\n"
+ << "Name: " << folderp->getName()
+ << " Id: " << folderp->getUUID()
+ << " Expected parent: " << cat->getParentUUID()
+ << " Actual parent: " << folderp->getParentUUID()
+ << LL_ENDL;
+ LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
+ accountForUpdate(update);
+ }
+ // else: Do not update parent, parent is already aware of the change. See processBulkUpdateInventory
+
+ cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
+ cat->setDescendentCount(0);
+ updateCategory(cat);
+ }
if (callback)
{
@@ -903,16 +946,29 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
LLUUID new_parent_id = item->getParentUUID();
bool update_parent_on_server = false;
- if (new_parent_id.isNull())
+ if (new_parent_id.isNull() && !LLApp::isExiting())
{
- // item with null parent will end in random location and then in Lost&Found,
- // either move to default folder as if it is new item or don't move at all
- LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID()
- << " to null folder. Moving to Lost&Found. Old item name: " << old_item->getName()
- << ". New name: " << item->getName()
- << "." << LL_ENDL;
- new_parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
- update_parent_on_server = true;
+ if (old_parent_id.isNull())
+ {
+ // Item with null parent will end in random location and then in Lost&Found,
+ // either move to default folder as if it is new item or don't move at all
+ LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID()
+ << " to null folder. Moving to Lost&Found. Old item name: " << old_item->getName()
+ << ". New name: " << item->getName()
+ << "." << LL_ENDL;
+ new_parent_id = findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+ update_parent_on_server = true;
+ }
+ else
+ {
+ // Probably not the best way to handle this, we might encounter real case of 'lost&found' at some point
+ LL_WARNS(LOG_INV) << "Update attempts to reparent item " << item->getUUID()
+ << " to null folder. Old parent not null. Moving to old parent. Old item name: " << old_item->getName()
+ << ". New name: " << item->getName()
+ << "." << LL_ENDL;
+ new_parent_id = old_parent_id;
+ update_parent_on_server = true;
+ }
}
if(old_parent_id != new_parent_id)
@@ -2648,29 +2704,37 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
{
if(filename.empty())
{
- LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL;
+ LL_ERRS(LOG_INV) << "filename is Null!" << LL_ENDL;
return false;
}
- LL_INFOS(LOG_INV) << "LLInventoryModel::loadFromFile(" << filename << ")" << LL_ENDL;
- LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
- if(!file)
+ LL_INFOS(LOG_INV) << "loading inventory from: (" << filename << ")" << LL_ENDL;
+
+ llifstream file(filename.c_str());
+
+ if (!file.is_open())
{
LL_INFOS(LOG_INV) << "unable to load inventory from: " << filename << LL_ENDL;
return false;
}
- // *NOTE: This buffer size is hard coded into scanf() below.
- char buffer[MAX_STRING]; /*Flawfinder: ignore*/
- char keyword[MAX_STRING]; /*Flawfinder: ignore*/
- char value[MAX_STRING]; /*Flawfinder: ignore*/
- is_cache_obsolete = true; // Obsolete until proven current
- while(!feof(file) && fgets(buffer, MAX_STRING, file))
+
+ is_cache_obsolete = true; // Obsolete until proven current
+
+ std::string line;
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+ while (std::getline(file, line))
{
- sscanf(buffer, " %126s %126s", keyword, value); /* Flawfinder: ignore */
- if(0 == strcmp("inv_cache_version", keyword))
+ LLSD s_item;
+ std::istringstream iss(line);
+ if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ LL_WARNS(LOG_INV)<< "Parsing inventory cache failed" << LL_ENDL;
+ break;
+ }
+
+ if (s_item.has("inv_cache_version"))
{
- S32 version;
- int succ = sscanf(value,"%d",&version);
- if ((1 == succ) && (version == sCurrentInvCacheVersion))
+ S32 version = s_item["inv_cache_version"].asInteger();
+ if (version == sCurrentInvCacheVersion)
{
// Cache is up to date
is_cache_obsolete = false;
@@ -2678,43 +2742,33 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
}
else
{
- // Cache is out of date
+ LL_WARNS(LOG_INV)<< "Inventory cache is out of date" << LL_ENDL;
break;
}
}
- else if(0 == strcmp("inv_category", keyword))
+ else if (s_item.has("cat_id"))
{
if (is_cache_obsolete)
break;
-
+
LLPointer<LLViewerInventoryCategory> inv_cat = new LLViewerInventoryCategory(LLUUID::null);
- if(inv_cat->importFileLocal(file))
+ if(inv_cat->importLLSD(s_item))
{
categories.push_back(inv_cat);
}
- else
- {
- LL_WARNS(LOG_INV) << "loadInventoryFromFile(). Ignoring invalid inventory category: " << inv_cat->getName() << LL_ENDL;
- //delete inv_cat; // automatic when inv_cat is reassigned or destroyed
- }
}
- else if(0 == strcmp("inv_item", keyword))
+ else if (s_item.has("item_id"))
{
if (is_cache_obsolete)
break;
LLPointer<LLViewerInventoryItem> inv_item = new LLViewerInventoryItem;
- if( inv_item->importFileLocal(file) )
+ if( inv_item->fromLLSD(s_item) )
{
- // *FIX: Need a better solution, this prevents the
- // application from freezing, but breaks inventory
- // caching.
if(inv_item->getUUID().isNull())
{
- //delete inv_item; // automatic when inv_cat is reassigned or destroyed
LL_WARNS(LOG_INV) << "Ignoring inventory with null item id: "
- << inv_item->getName() << LL_ENDL;
-
+ << inv_item->getName() << LL_ENDL;
}
else
{
@@ -2727,62 +2781,63 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
items.push_back(inv_item);
}
}
- }
- else
- {
- LL_WARNS(LOG_INV) << "loadInventoryFromFile(). Ignoring invalid inventory item: " << inv_item->getName() << LL_ENDL;
- //delete inv_item; // automatic when inv_cat is reassigned or destroyed
- }
- }
- else
- {
- LL_WARNS(LOG_INV) << "Unknown token in inventory file '" << keyword << "'"
- << LL_ENDL;
+ }
}
}
- fclose(file);
- if (is_cache_obsolete)
- return false;
- return true;
+
+ file.close();
+
+ return !is_cache_obsolete;
}
// static
bool LLInventoryModel::saveToFile(const std::string& filename,
- const cat_array_t& categories,
- const item_array_t& items)
+ const cat_array_t& categories,
+ const item_array_t& items)
{
- if(filename.empty())
+ if (filename.empty())
{
LL_ERRS(LOG_INV) << "Filename is Null!" << LL_ENDL;
return false;
}
- LL_INFOS(LOG_INV) << "LLInventoryModel::saveToFile(" << filename << ")" << LL_ENDL;
- LLFILE* file = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/
- if(!file)
+
+ LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL;
+
+ llofstream fileXML(filename.c_str());
+ if (!fileXML.is_open())
{
LL_WARNS(LOG_INV) << "unable to save inventory to: " << filename << LL_ENDL;
return false;
}
- fprintf(file, "\tinv_cache_version\t%d\n",sCurrentInvCacheVersion);
+ LLSD cache_ver;
+ cache_ver["inv_cache_version"] = sCurrentInvCacheVersion;
+
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl;
+
S32 count = categories.size();
+ S32 cat_count = 0;
S32 i;
for(i = 0; i < count; ++i)
{
LLViewerInventoryCategory* cat = categories[i];
if(cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
{
- cat->exportFileLocal(file);
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl;
+ cat_count++;
}
}
- count = items.size();
- for(i = 0; i < count; ++i)
+ S32 it_count = items.size();
+ for(i = 0; i < it_count; ++i)
{
- items[i]->exportFile(file);
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl;
}
- fclose(file);
+ fileXML.close();
+
+ LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
+
return true;
}
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index c6075b4066..277dfe9e28 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -146,7 +146,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mCompletionObserver(NULL),
mScroller(NULL),
mSortOrderSetting(p.sort_order_setting),
- mInventory(p.inventory),
+ mInventory(p.inventory), //inventory("", &gInventory)
mAcceptsDragAndDrop(p.accepts_drag_and_drop),
mAllowMultiSelect(p.allow_multi_select),
mAllowDrag(p.allow_drag),
@@ -512,7 +512,18 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
view_item->destroyView();
removeItemID(idp);
}
- view_item = buildNewViews(item_id);
+
+ LLInventoryObject const* objectp = mInventory->getObject(item_id);
+ if (objectp)
+ {
+ // providing NULL directly avoids unnessesary getItemByID calls
+ view_item = buildNewViews(item_id, objectp, NULL);
+ }
+ else
+ {
+ view_item = NULL;
+ }
+
viewmodel_item =
static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);
view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
@@ -555,7 +566,13 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
if (model_item && !view_item)
{
// Add the UI element for this item.
- buildNewViews(item_id);
+ LLInventoryObject const* objectp = mInventory->getObject(item_id);
+ if (objectp)
+ {
+ // providing NULL directly avoids unnessesary getItemByID calls
+ buildNewViews(item_id, objectp, NULL);
+ }
+
// Select any newly created object that has the auto rename at top of folder root set.
if(mFolderRoot.get()->getRoot()->needsAutoRename())
{
@@ -852,7 +869,7 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge
LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
{
- LLInventoryObject const* objectp = gInventory.getObject(id);
+ LLInventoryObject const* objectp = mInventory->getObject(id);
return buildNewViews(id, objectp);
}
@@ -862,11 +879,43 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO
{
return NULL;
}
+ if (!typedViewsFilter(id, objectp))
+ {
+ // if certain types are not allowed permanently, no reason to create views
+ return NULL;
+ }
+
+ const LLUUID &parent_id = objectp->getParentUUID();
LLFolderViewItem* folder_view_item = getItemByID(id);
+ LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id);
+
+ return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder);
+}
+
+LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryObject const* objectp, LLFolderViewItem *folder_view_item)
+{
+ if (!objectp)
+ {
+ return NULL;
+ }
+ if (!typedViewsFilter(id, objectp))
+ {
+ // if certain types are not allowed permanently, no reason to create views
+ return NULL;
+ }
const LLUUID &parent_id = objectp->getParentUUID();
- LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id);
-
+ LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id);
+
+ return buildViewsTree(id, parent_id, objectp, folder_view_item, parent_folder);
+}
+
+LLFolderViewItem* LLInventoryPanel::buildViewsTree(const LLUUID& id,
+ const LLUUID& parent_id,
+ LLInventoryObject const* objectp,
+ LLFolderViewItem *folder_view_item,
+ LLFolderViewFolder *parent_folder)
+{
// Force the creation of an extra root level folder item if required by the inventory panel (default is "false")
bool allow_drop = true;
bool create_root = false;
@@ -887,7 +936,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO
{
if (objectp->getType() <= LLAssetType::AT_NONE)
{
- LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
+ LL_WARNS() << "LLInventoryPanel::buildViewsTree called with invalid objectp->mType : "
<< ((S32)objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
<< LL_ENDL;
return NULL;
@@ -896,7 +945,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO
if (objectp->getType() >= LLAssetType::AT_COUNT)
{
// Example: Happens when we add assets of new, not yet supported type to library
- LL_DEBUGS() << "LLInventoryPanel::buildNewViews called with unknown objectp->mType : "
+ LL_DEBUGS() << "LLInventoryPanel::buildViewsTree called with unknown objectp->mType : "
<< ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
<< LL_ENDL;
@@ -973,26 +1022,58 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryO
LLViewerInventoryCategory::cat_array_t* categories;
LLViewerInventoryItem::item_array_t* items;
mInventory->lockDirectDescendentArrays(id, categories, items);
-
+
+ LLFolderViewFolder *parentp = dynamic_cast<LLFolderViewFolder*>(folder_view_item);
+
if(categories)
- {
+ {
+ bool has_folders = parentp->getFoldersCount() > 0;
for (LLViewerInventoryCategory::cat_array_t::const_iterator cat_iter = categories->begin();
cat_iter != categories->end();
++cat_iter)
{
const LLViewerInventoryCategory* cat = (*cat_iter);
- buildNewViews(cat->getUUID());
+ if (typedViewsFilter(cat->getUUID(), cat))
+ {
+ if (has_folders)
+ {
+ // This can be optimized: we don't need to call getItemByID()
+ // each time, especially since content is growing, we can just
+ // iter over copy of mItemMap in some way
+ LLFolderViewItem* view_itemp = getItemByID(cat->getUUID());
+ buildViewsTree(cat->getUUID(), id, cat, view_itemp, parentp);
+ }
+ else
+ {
+ buildViewsTree(cat->getUUID(), id, cat, NULL, parentp);
+ }
+ }
}
}
if(items)
- {
+ {
+ bool has_items = parentp->getItemsCount() > 0;
for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();
item_iter != items->end();
++item_iter)
{
const LLViewerInventoryItem* item = (*item_iter);
- buildNewViews(item->getUUID());
+ if (typedViewsFilter(item->getUUID(), item))
+ {
+ if (has_items)
+ {
+ // This can be optimized: we don't need to call getItemByID()
+ // each time, especially since content is growing, we can just
+ // iter over copy of mItemMap in some way
+ LLFolderViewItem* view_itemp = getItemByID(item->getUUID());
+ buildViewsTree(item->getUUID(), id, item, view_itemp, parentp);
+ }
+ else
+ {
+ buildViewsTree(item->getUUID(), id, item, NULL, parentp);
+ }
+ }
}
}
mInventory->unlockDirectDescendentArrays(id);
@@ -1755,41 +1836,7 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
/************************************************************************/
/* Asset Pre-Filtered Inventory Panel related class */
-/* Exchanges filter's flexibility for speed of generation and */
-/* improved performance */
/************************************************************************/
-class LLAssetFilteredInventoryPanel : public LLInventoryPanel
-{
-public:
- struct Params
- : public LLInitParam::Block<Params, LLInventoryPanel::Params>
- {
- Mandatory<std::string> filter_asset_type;
-
- Params() : filter_asset_type("filter_asset_type") {}
- };
-
- void initFromParams(const Params& p);
-protected:
- LLAssetFilteredInventoryPanel(const Params& p) : LLInventoryPanel(p) {}
- friend class LLUICtrlFactory;
-public:
- ~LLAssetFilteredInventoryPanel() {}
-
- /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg) override;
-
-protected:
- /*virtual*/ LLFolderViewItem* buildNewViews(const LLUUID& id) override;
- /*virtual*/ void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override;
-
-private:
- LLAssetType::EType mAssetType;
-};
-
void LLAssetFilteredInventoryPanel::initFromParams(const Params& p)
{
@@ -1823,21 +1870,20 @@ BOOL LLAssetFilteredInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, B
return result;
}
-LLFolderViewItem* LLAssetFilteredInventoryPanel::buildNewViews(const LLUUID& id)
+/*virtual*/
+bool LLAssetFilteredInventoryPanel::typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp)
{
- LLInventoryObject const* objectp = gInventory.getObject(id);
-
if (!objectp)
{
- return NULL;
+ return false;
}
if (objectp->getType() != mAssetType && objectp->getType() != LLAssetType::AT_CATEGORY)
{
- return NULL;
+ return false;
}
- return LLInventoryPanel::buildNewViews(id, objectp);
+ return true;
}
void LLAssetFilteredInventoryPanel::itemChanged(const LLUUID& id, U32 mask, const LLInventoryObject* model_item)
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index b55eb2b828..c202333f45 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -325,8 +325,15 @@ protected:
static LLUIColor sLibraryColor;
static LLUIColor sLinkColor;
- virtual LLFolderViewItem* buildNewViews(const LLUUID& id);
- LLFolderViewItem* buildNewViews(const LLUUID& id, LLInventoryObject const* objectp);
+ LLFolderViewItem* buildNewViews(const LLUUID& id);
+ LLFolderViewItem* buildNewViews(const LLUUID& id,
+ LLInventoryObject const* objectp);
+ LLFolderViewItem* buildNewViews(const LLUUID& id,
+ LLInventoryObject const* objectp,
+ LLFolderViewItem *target_view);
+ // if certain types are not allowed, no reason to create views
+ virtual bool typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) { return true; }
+
virtual void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item);
BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const;
@@ -334,8 +341,75 @@ protected:
virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop);
virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge);
private:
+ // buildViewsTree does not include some checks and is meant
+ // for recursive use, use buildNewViews() for first call
+ LLFolderViewItem* buildViewsTree(const LLUUID& id,
+ const LLUUID& parent_id,
+ LLInventoryObject const* objectp,
+ LLFolderViewItem *target_view,
+ LLFolderViewFolder *parent_folder_view);
+
bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild()
bool mViewsInitialized; // Views have been generated
};
+
+class LLInventoryFavoriteItemsPanel : public LLInventoryPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {};
+
+ void initFromParams(const Params& p);
+ bool isSelectionRemovable() { return false; }
+ void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
+
+protected:
+ LLInventoryFavoriteItemsPanel(const Params& params);
+ ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); }
+ void updateFavoritesRootFolder();
+
+ boost::signals2::connection mFolderChangedSignal;
+ boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback;
+ friend class LLUICtrlFactory;
+};
+
+/************************************************************************/
+/* Asset Pre-Filtered Inventory Panel related class */
+/* Exchanges filter's flexibility for speed of generation and */
+/* improved performance */
+/************************************************************************/
+
+class LLAssetFilteredInventoryPanel : public LLInventoryPanel
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {
+ Mandatory<std::string> filter_asset_type;
+
+ Params() : filter_asset_type("filter_asset_type") {}
+ };
+
+ void initFromParams(const Params& p);
+protected:
+ LLAssetFilteredInventoryPanel(const Params& p) : LLInventoryPanel(p) {}
+ friend class LLUICtrlFactory;
+public:
+ ~LLAssetFilteredInventoryPanel() {}
+
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg) override;
+
+protected:
+ /*virtual*/ bool typedViewsFilter(const LLUUID& id, LLInventoryObject const* objectp) override;
+ /*virtual*/ void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override;
+
+private:
+ LLAssetType::EType mAssetType;
+};
+
#endif // LL_LLINVENTORYPANEL_H
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index c58540914e..b4236c406b 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -39,6 +39,11 @@
// Globals
LLLandmarkList gLandmarkList;
+// number is mostly arbitrary, but it should be below DEFAULT_QUEUE_SIZE pool size,
+// which is 4096, to not overfill the pool if user has more than 4K of landmarks
+// and it should leave some space for other potential simultaneous asset request
+const S32 MAX_SIMULTANEOUS_REQUESTS = 512;
+
////////////////////////////////////////////////////////////////////////////
// LLLandmarkList
@@ -69,6 +74,11 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
{
return NULL;
}
+ if ( mWaitList.find(asset_uuid) != mWaitList.end() )
+ {
+ // Landmark is sheduled for download, but not requested yet
+ return NULL;
+ }
landmark_requested_list_t::iterator iter = mRequestedList.find(asset_uuid);
if (iter != mRequestedList.end())
@@ -86,6 +96,17 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
mLoadedCallbackMap.insert(vt);
}
+ if (mRequestedList.size() > MAX_SIMULTANEOUS_REQUESTS)
+ {
+ // Workarounds for corutines pending list size limit:
+ // Postpone download till queue is emptier.
+ // Coroutines have own built in 'pending' list, but unfortunately
+ // it is too small compared to potential amount of landmarks
+ // or assets.
+ mWaitList.insert(asset_uuid);
+ return NULL;
+ }
+
gAssetStorage->getAssetData(asset_uuid,
LLAssetType::AT_LANDMARK,
LLLandmarkList::processGetAssetReply,
@@ -155,8 +176,32 @@ void LLLandmarkList::processGetAssetReply(
}
gLandmarkList.mBadList.insert(uuid);
+ gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests
+ // todo: this should clean mLoadedCallbackMap!
}
+ // getAssetData can fire callback immediately, causing
+ // a recursion which is suboptimal for very large wait list.
+ // 'scheduling' indicates that we are inside request and
+ // shouldn't be launching more requests.
+ static bool scheduling = false;
+ if (!scheduling && !gLandmarkList.mWaitList.empty())
+ {
+ scheduling = true;
+ while (!gLandmarkList.mWaitList.empty() && gLandmarkList.mRequestedList.size() < MAX_SIMULTANEOUS_REQUESTS)
+ {
+ // start new download from wait list
+ landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin();
+ LLUUID asset_uuid = *iter;
+ gLandmarkList.mWaitList.erase(iter);
+ gAssetStorage->getAssetData(asset_uuid,
+ LLAssetType::AT_LANDMARK,
+ LLLandmarkList::processGetAssetReply,
+ NULL);
+ gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds;
+ }
+ scheduling = false;
+ }
}
BOOL LLLandmarkList::isAssetInLoadedCallbackMap(const LLUUID& asset_uuid)
diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h
index 3356f866ce..2e7bd25610 100644
--- a/indra/newview/lllandmarklist.h
+++ b/indra/newview/lllandmarklist.h
@@ -70,9 +70,10 @@ protected:
typedef std::map<LLUUID, LLLandmark*> landmark_list_t;
landmark_list_t mList;
- typedef std::set<LLUUID> landmark_bad_list_t;
- landmark_bad_list_t mBadList;
-
+ typedef std::set<LLUUID> landmark_uuid_list_t;
+ landmark_uuid_list_t mBadList;
+ landmark_uuid_list_t mWaitList;
+
typedef std::map<LLUUID,F32> landmark_requested_list_t;
landmark_requested_list_t mRequestedList;
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 0c64531783..415781bc27 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -133,6 +133,16 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
messages.back()[LL_IM_TEXT] = im_text;
}
+std::string remove_utf8_bom(const char* buf)
+{
+ std::string res(buf);
+ if (res[0] == (char)0xEF && res[1] == (char)0xBB && res[2] == (char)0xBF)
+ {
+ res.erase(0, 3);
+ }
+ return res;
+}
+
class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner>
{
LLSINGLETON(LLLogChatTimeScanner);
@@ -417,7 +427,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
continue;
}
- std::string line(buffer);
+ std::string line(remove_utf8_bom(buffer));
//updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message
if (' ' == line[0])
@@ -761,8 +771,8 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group)
{
std::string file_name;
gCacheName->getGroupName(avatar_id, file_name);
- file_name = makeLogFileName(file_name);
- return isTranscriptFileFound(makeLogFileName(file_name));
+ file_name = makeLogFileName(file_name + GROUP_CHAT_SUFFIX);
+ return isTranscriptFileFound(file_name);
}
return false;
}
@@ -805,7 +815,7 @@ bool LLLogChat::isTranscriptFileFound(std::string fullname)
{
//matching a timestamp
boost::match_results<std::string::const_iterator> matches;
- if (boost::regex_match(std::string(buffer), matches, TIMESTAMP))
+ if (boost::regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP))
{
result = true;
}
@@ -1126,7 +1136,7 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL
firstline = FALSE;
continue;
}
- std::string line(buffer);
+ std::string line(remove_utf8_bom(buffer));
//updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message
if (' ' == line[0])
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index f158aae3d2..c3e39429a2 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -447,6 +447,7 @@ BOOL LLManipRotate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
}
mMouseCur = mMouseDown;
+ mAgentSelfAtAxis = gAgent.getAtAxis(); // no point checking if avatar was selected, just save the value
// Route future Mouse messages here preemptively. (Release on mouse up.)
setMouseCapture( TRUE );
@@ -610,6 +611,26 @@ void LLManipRotate::drag( S32 x, S32 y )
else
{
object->setRotation(new_rot, damped);
+ LLVOAvatar* avatar = object->asAvatar();
+ if (avatar && avatar->isSelf()
+ && LLSelectMgr::getInstance()->mAllowSelectAvatar
+ && !object->getParent())
+ {
+ // Normal avatars use object's orienttion, but self uses
+ // separate LLCoordFrame
+ // See LVOAvatar::updateOrientation()
+ if (gAgentCamera.getFocusOnAvatar())
+ {
+ //Don't rotate camera with avatar
+ gAgentCamera.setFocusOnAvatar(false, false, false);
+ }
+
+ LLVector3 at_axis = mAgentSelfAtAxis;
+ at_axis *= mRotation;
+ at_axis.mV[VZ] = 0.f;
+ at_axis.normalize();
+ gAgent.resetAxes(at_axis);
+ }
rebuild(object);
}
@@ -717,7 +738,7 @@ void LLManipRotate::drag( S32 x, S32 y )
LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit();
if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() &&
((root_object == NULL) || !root_object->isPermanentEnforced()) &&
- !cur->isAvatar())
+ (!cur->isAvatar() || LLSelectMgr::getInstance()->mAllowSelectAvatar))
{
selectNode->mLastRotation = cur->getRotation();
selectNode->mLastPositionLocal = cur->getPosition();
diff --git a/indra/newview/llmaniprotate.h b/indra/newview/llmaniprotate.h
index e8f1c24c58..dc36ef796a 100644
--- a/indra/newview/llmaniprotate.h
+++ b/indra/newview/llmaniprotate.h
@@ -95,6 +95,7 @@ private:
LLVector3 mMouseDown;
LLVector3 mMouseCur;
+ LLVector3 mAgentSelfAtAxis; // Own agent uses separate rotation method
F32 mRadiusMeters;
LLVector3 mCenterToCam;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index c5ced425f6..3e8731dfe6 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -99,7 +99,7 @@
// locking actions. In particular, the following operations
// on LLMeshRepository are very averse to any stalls:
// * loadMesh
-// * getMeshHeader (For structural details, see:
+// * search in mMeshHeader (For structural details, see:
// http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format)
// * notifyLoadedMeshes
// * getSkinInfo
@@ -1553,7 +1553,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (!zero)
{ //attempt to parse
- if (physicsShapeReceived(mesh_id, buffer, size))
+ if (physicsShapeReceived(mesh_id, buffer, size) == MESH_OK)
{
delete[] buffer;
return true;
@@ -1647,7 +1647,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, bool c
LLMeshRepository::sCacheBytesRead += bytes;
++LLMeshRepository::sCacheReads;
file.read(buffer, bytes);
- if (headerReceived(mesh_params, buffer, bytes))
+ if (headerReceived(mesh_params, buffer, bytes) == MESH_OK)
{
// Found mesh in VFS cache
return true;
@@ -1794,7 +1794,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
return retval;
}
-bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size)
+EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size)
{
const LLUUID mesh_id = mesh_params.getSculptID();
LLSD header;
@@ -1802,30 +1802,39 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
U32 header_size = 0;
if (data_size > 0)
{
- std::string res_str((char*) data, data_size);
+ std::istringstream stream;
+ try
+ {
+ std::string res_str((char*)data, data_size);
- std::string deprecated_header("<? LLSD/Binary ?>");
+ std::string deprecated_header("<? LLSD/Binary ?>");
- if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
- {
- res_str = res_str.substr(deprecated_header.size()+1, data_size);
- header_size = deprecated_header.size()+1;
- }
- data_size = res_str.size();
+ if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
+ {
+ res_str = res_str.substr(deprecated_header.size() + 1, data_size);
+ header_size = deprecated_header.size() + 1;
+ }
+ data_size = res_str.size();
- std::istringstream stream(res_str);
+ stream.str(res_str);
+ }
+ catch (std::bad_alloc&)
+ {
+ // out of memory, we won't be able to process this mesh
+ return MESH_OUT_OF_MEMORY;
+ }
if (!LLSDSerialize::fromBinary(header, stream, data_size))
{
LL_WARNS(LOG_MESH) << "Mesh header parse error. Not a valid mesh asset! ID: " << mesh_id
<< LL_ENDL;
- return false;
+ return MESH_PARSE_FAILURE;
}
if (!header.isMap())
{
LL_WARNS(LOG_MESH) << "Mesh header is invalid for ID: " << mesh_id << LL_ENDL;
- return false;
+ return MESH_INVALID;
}
if (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION)
@@ -1871,7 +1880,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
}
}
- return true;
+ return MESH_OK;
}
EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
@@ -1902,6 +1911,12 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
{
LLMutexLock lock(mMutex);
mLoadedQ.push(mesh);
+ // LLPointer is not thread safe, since we added this pointer into
+ // threaded list, make sure counter gets decreased inside mutex lock
+ // and won't affect mLoadedQ processing
+ volume = NULL;
+ // might be good idea to turn mesh into pointer to avoid making a copy
+ mesh.mVolume = NULL;
}
return MESH_OK;
}
@@ -1916,18 +1931,25 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
if (data_size > 0)
{
- std::string res_str((char*) data, data_size);
-
- std::istringstream stream(res_str);
+ try
+ {
+ std::string res_str((char*)data, data_size);
+ std::istringstream stream(res_str);
- U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size);
- if (uzip_result != LLUZipHelper::ZR_OK)
- {
- LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id
- << " uzip result" << uzip_result
- << LL_ENDL;
- return false;
- }
+ U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size);
+ if (uzip_result != LLUZipHelper::ZR_OK)
+ {
+ LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id
+ << " uzip result" << uzip_result
+ << LL_ENDL;
+ return false;
+ }
+ }
+ catch (std::bad_alloc&)
+ {
+ LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;
+ return false;
+ }
}
{
@@ -1949,19 +1971,26 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
LLSD decomp;
if (data_size > 0)
- {
- std::string res_str((char*) data, data_size);
-
- std::istringstream stream(res_str);
+ {
+ try
+ {
+ std::string res_str((char*)data, data_size);
+ std::istringstream stream(res_str);
- U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size);
- if (uzip_result != LLUZipHelper::ZR_OK)
- {
- LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id
- << " uzip result: " << uzip_result
- << LL_ENDL;
- return false;
- }
+ U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size);
+ if (uzip_result != LLUZipHelper::ZR_OK)
+ {
+ LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id
+ << " uzip result: " << uzip_result
+ << LL_ENDL;
+ return false;
+ }
+ }
+ catch (std::bad_alloc&)
+ {
+ LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;
+ return false;
+ }
}
{
@@ -1976,7 +2005,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
return true;
}
-bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
+EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
{
LLSD physics_shape;
@@ -1993,8 +2022,19 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH);
LLPointer<LLVolume> volume = new LLVolume(volume_params,0);
- std::string mesh_string((char*) data, data_size);
- std::istringstream stream(mesh_string);
+
+ std::istringstream stream;
+ try
+ {
+ std::string mesh_string((char*)data, data_size);
+ stream.str(mesh_string);
+ }
+ catch (std::bad_alloc&)
+ {
+ // out of memory, we won't be able to process this mesh
+ delete d;
+ return MESH_OUT_OF_MEMORY;
+ }
if (volume->unpackVolumeFaces(stream, data_size))
{
@@ -2033,7 +2073,7 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
LLMutexLock lock(mMutex);
mDecompositionQ.push_back(d);
}
- return true;
+ return MESH_OK;
}
LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
@@ -2829,12 +2869,12 @@ void LLMeshRepoThread::notifyLoadedMeshes()
mMutex->unlock();
break;
}
- LoadedMesh mesh = mLoadedQ.front();
+ LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point
mLoadedQ.pop();
mMutex->unlock();
update_metrics = true;
- if (mesh.mVolume && mesh.mVolume->getNumVolumeFaces() > 0)
+ if (mesh.mVolume->getNumVolumeFaces() > 0)
{
gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume);
}
@@ -3142,15 +3182,21 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
U8 * data, S32 data_size)
{
LLUUID mesh_id = mMeshParams.getSculptID();
- bool success = (! MESH_HEADER_PROCESS_FAILED)
- && ((data != NULL) == (data_size > 0)) // if we have data but no size or have size but no data, something is wrong
- && gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);
+ bool success = (!MESH_HEADER_PROCESS_FAILED)
+ && ((data != NULL) == (data_size > 0)); // if we have data but no size or have size but no data, something is wrong;
llassert(success);
+ EMeshProcessingResult res = MESH_UNKNOWN;
+ if (success)
+ {
+ res = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);
+ success = (res == MESH_OK);
+ }
if (! success)
{
// *TODO: Get real reason for parse failure here. Might we want to retry?
LL_WARNS(LOG_MESH) << "Unable to parse mesh header. ID: " << mesh_id
- << ", Unknown reason. Not retrying."
+ << ", Size: " << data_size
+ << ", Reason: " << res << " Not retrying."
<< LL_ENDL;
// Can't get the header so none of the LODs will be available
@@ -3173,7 +3219,6 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
header = iter->second;
}
- gMeshRepo.mThread->mHeaderMutex->unlock();
if (header_bytes > 0
&& !header.has("404")
@@ -3194,7 +3239,10 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
- S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
+ // Do not unlock mutex untill we are done with LLSD.
+ // LLSD is smart and can work like smart pointer, is not thread safe.
+ gMeshRepo.mThread->mHeaderMutex->unlock();
+
S32 bytes = lod_bytes + header_bytes;
@@ -3230,6 +3278,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
{
LL_WARNS(LOG_MESH) << "Trying to cache nonexistent mesh, mesh id: " << mesh_id << LL_ENDL;
+ gMeshRepo.mThread->mHeaderMutex->unlock();
+
// headerReceived() parsed header, but header's data is invalid so none of the LODs will be available
LLMutexLock lock(gMeshRepo.mThread->mMutex);
for (int i(0); i < 4; ++i)
@@ -3430,7 +3480,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3
{
if ((!MESH_PHYS_SHAPE_PROCESS_FAILED)
&& ((data != NULL) == (data_size > 0)) // if we have data but no size or have size but no data, something is wrong
- && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size))
+ && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size) == MESH_OK)
{
// good fetch from sim, write to VFS for caching
LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
@@ -4099,42 +4149,42 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)
bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
{
- LLSD mesh = mThread->getMeshHeader(mesh_id);
- if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
- {
- return true;
- }
-
- LLModel::Decomposition* decomp = getDecomposition(mesh_id);
- if (decomp && !decomp->mHull.empty())
- {
- return true;
- }
+ if (mesh_id.isNull())
+ {
+ return false;
+ }
- return false;
-}
+ if (mThread->hasPhysicsShapeInHeader(mesh_id))
+ {
+ return true;
+ }
-LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
-{
- LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
+ LLModel::Decomposition* decomp = getDecomposition(mesh_id);
+ if (decomp && !decomp->mHull.empty())
+ {
+ return true;
+ }
- return mThread->getMeshHeader(mesh_id);
+ return false;
}
-LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
+bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id)
{
- static LLSD dummy_ret;
- if (mesh_id.notNull())
- {
- LLMutexLock lock(mHeaderMutex);
- mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
- if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0)
- {
- return iter->second;
- }
- }
+ LLMutexLock lock(mHeaderMutex);
+ if (mMeshHeaderSize[mesh_id] > 0)
+ {
+ mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
+ if (iter != mMeshHeader.end())
+ {
+ LLSD &mesh = iter->second;
+ if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
+ {
+ return true;
+ }
+ }
+ }
- return dummy_ret;
+ return false;
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index bba0c9f2cb..81e49cb1d8 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -57,6 +57,8 @@ typedef enum e_mesh_processing_result_enum
MESH_NO_DATA = 1,
MESH_OUT_OF_MEMORY,
MESH_HTTP_REQUEST_FAILED,
+ MESH_PARSE_FAILURE,
+ MESH_INVALID,
MESH_UNKNOWN
} EMeshProcessingResult;
@@ -336,12 +338,12 @@ public:
bool fetchMeshHeader(const LLVolumeParams& mesh_params, bool can_retry = true);
bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool can_retry = true);
- bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
+ EMeshProcessingResult headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
EMeshProcessingResult lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- LLSD& getMeshHeader(const LLUUID& mesh_id);
+ EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
+ bool hasPhysicsShapeInHeader(const LLUUID& mesh_id);
void notifyLoadedMeshes();
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
@@ -593,9 +595,6 @@ public:
bool meshUploadEnabled();
bool meshRezEnabled();
-
-
- LLSD& getMeshHeader(const LLUUID& mesh_id);
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
new file mode 100644
index 0000000000..a9e80ab5da
--- /dev/null
+++ b/indra/newview/llmodelpreview.cpp
@@ -0,0 +1,3570 @@
+/**
+ * @file llmodelpreview.cpp
+ * @brief LLModelPreview class implementation
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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 "llmodelpreview.h"
+
+#include "llmodelloader.h"
+#include "lldaeloader.h"
+#include "llfloatermodelpreview.h"
+
+#include "llagent.h"
+#include "llanimationstates.h"
+#include "llcallbacklist.h"
+#include "lldatapacker.h"
+#include "lldrawable.h"
+#include "llface.h"
+#include "lliconctrl.h"
+#include "llmatrix4a.h"
+#include "llmeshrepository.h"
+#include "llrender.h"
+#include "llsdutil_math.h"
+#include "llskinningutil.h"
+#include "llstring.h"
+#include "llsdserialize.h"
+#include "lltoolmgr.h"
+#include "llui.h"
+#include "llvector4a.h"
+#include "llviewercamera.h"
+#include "llviewercontrol.h"
+#include "llviewerobjectlist.h"
+#include "llviewernetwork.h"
+#include "llviewershadermgr.h"
+#include "llviewertexteditor.h"
+#include "llviewertexturelist.h"
+#include "llvoavatar.h"
+#include "pipeline.h"
+
+// ui controls (from floater)
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "llspinctrl.h"
+#include "lltabcontainer.h"
+#include "lltextbox.h"
+
+#include "glod/glod.h"
+#include <boost/algorithm/string.hpp>
+
+bool LLModelPreview::sIgnoreLoadedCallback = false;
+
+// Extra configurability, to be exposed later in xml (LLModelPreview probably
+// should become UI control at some point or get split into preview control)
+static const LLColor4 PREVIEW_CANVAS_COL(0.169f, 0.169f, 0.169f, 1.f);
+static const LLColor4 PREVIEW_EDGE_COL(0.4f, 0.4f, 0.4f, 1.0);
+static const LLColor4 PREVIEW_BASE_COL(1.f, 1.f, 1.f, 1.f);
+static const LLColor3 PREVIEW_BRIGHTNESS(0.9f, 0.9f, 0.9f);
+static const F32 PREVIEW_EDGE_WIDTH(1.f);
+static const LLColor4 PREVIEW_PSYH_EDGE_COL(0.f, 0.25f, 0.5f, 0.25f);
+static const LLColor4 PREVIEW_PSYH_FILL_COL(0.f, 0.5f, 1.0f, 0.5f);
+static const F32 PREVIEW_PSYH_EDGE_WIDTH(1.f);
+static const LLColor4 PREVIEW_DEG_EDGE_COL(1.f, 0.f, 0.f, 1.f);
+static const LLColor4 PREVIEW_DEG_FILL_COL(1.f, 0.f, 0.f, 0.5f);
+static const F32 PREVIEW_DEG_EDGE_WIDTH(3.f);
+static const F32 PREVIEW_DEG_POINT_SIZE(8.f);
+static const F32 PREVIEW_ZOOM_LIMIT(10.f);
+
+const F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f;
+
+BOOL stop_gloderror()
+{
+ GLuint error = glodGetError();
+
+ if (error != GLOD_NO_ERROR)
+ {
+ LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)
+{
+ LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW);
+
+ if (texture)
+ {
+ if (texture->getDiscardLevel() > -1)
+ {
+ gGL.getTexUnit(0)->bind(texture, true);
+ return texture;
+ }
+ }
+
+ return NULL;
+}
+
+std::string stripSuffix(std::string name)
+{
+ if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1))
+ {
+ return name.substr(0, name.rfind('_'));
+ }
+ return name;
+}
+
+std::string getLodSuffix(S32 lod)
+{
+ std::string suffix;
+ switch (lod)
+ {
+ case LLModel::LOD_IMPOSTOR: suffix = "_LOD0"; break;
+ case LLModel::LOD_LOW: suffix = "_LOD1"; break;
+ case LLModel::LOD_MEDIUM: suffix = "_LOD2"; break;
+ case LLModel::LOD_PHYSICS: suffix = "_PHYS"; break;
+ case LLModel::LOD_HIGH: break;
+ }
+ return suffix;
+}
+
+void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
+{
+ LLModelLoader::scene::iterator base_iter = scene.begin();
+ bool found = false;
+ while (!found && (base_iter != scene.end()))
+ {
+ matOut = base_iter->first;
+
+ LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin();
+ while (!found && (base_instance_iter != base_iter->second.end()))
+ {
+ LLModelInstance& base_instance = *base_instance_iter++;
+ LLModel* base_model = base_instance.mModel;
+
+ if (base_model && (base_model->mLabel == name_to_match))
+ {
+ baseModelOut = base_model;
+ return;
+ }
+ }
+ base_iter++;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// LLModelPreview
+//-----------------------------------------------------------------------------
+
+LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
+ : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex()
+ , mLodsQuery()
+ , mLodsWithParsingError()
+ , mPelvisZOffset(0.0f)
+ , mLegacyRigFlags(U32_MAX)
+ , mRigValidJointUpload(false)
+ , mPhysicsSearchLOD(LLModel::LOD_PHYSICS)
+ , mResetJoints(false)
+ , mModelNoErrors(true)
+ , mLastJointUpdate(false)
+ , mFirstSkinUpdate(true)
+ , mHasDegenerate(false)
+ , mImporterDebug(LLCachedControl<bool>(gSavedSettings, "ImporterDebug", false))
+{
+ mNeedsUpdate = TRUE;
+ mCameraDistance = 0.f;
+ mCameraYaw = 0.f;
+ mCameraPitch = 0.f;
+ mCameraZoom = 1.f;
+ mTextureName = 0;
+ mPreviewLOD = 0;
+ mModelLoader = NULL;
+ mMaxTriangleLimit = 0;
+ mDirty = false;
+ mGenLOD = false;
+ mLoading = false;
+ mLookUpLodFiles = false;
+ mLoadState = LLModelLoader::STARTING;
+ mGroup = 0;
+ mLODFrozen = false;
+ mBuildShareTolerance = 0.f;
+ mBuildQueueMode = GLOD_QUEUE_GREEDY;
+ mBuildBorderMode = GLOD_BORDER_UNLOCK;
+ mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE;
+
+ for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
+ {
+ mRequestedTriangleCount[i] = 0;
+ mRequestedCreaseAngle[i] = -1.f;
+ mRequestedLoDMode[i] = 0;
+ mRequestedErrorThreshold[i] = 0.f;
+ mRequestedBuildOperator[i] = 0;
+ mRequestedQueueMode[i] = 0;
+ mRequestedBorderMode[i] = 0;
+ mRequestedShareTolerance[i] = 0.f;
+ }
+
+ mViewOption["show_textures"] = false;
+
+ mFMP = fmp;
+
+ mHasPivot = false;
+ mModelPivot = LLVector3(0.0f, 0.0f, 0.0f);
+
+ glodInit();
+
+ createPreviewAvatar();
+}
+
+LLModelPreview::~LLModelPreview()
+{
+ // glod apparently has internal mem alignment issues that are angering
+ // the heap-check code in windows, these should be hunted down in that
+ // TP code, if possible
+ //
+ // kernel32.dll!HeapFree() + 0x14 bytes
+ // msvcr100.dll!free(void * pBlock) Line 51 C
+ // glod.dll!glodGetGroupParameteriv() + 0x119 bytes
+ // glod.dll!glodShutdown() + 0x77 bytes
+ //
+ //glodShutdown();
+ if (mModelLoader)
+ {
+ mModelLoader->shutdown();
+ }
+
+ if (mPreviewAvatar)
+ {
+ mPreviewAvatar->markDead();
+ mPreviewAvatar = NULL;
+ }
+}
+
+U32 LLModelPreview::calcResourceCost()
+{
+ assert_main_thread();
+
+ rebuildUploadData();
+
+ //Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
+ if (mFMP && mFMP->childGetValue("upload_skin").asBoolean())
+ {
+ bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+ if (uploadingJointPositions && !isRigValidForJointPositionUpload())
+ {
+ mFMP->childDisable("ok_btn");
+ }
+ }
+
+ std::set<LLModel*> accounted;
+ U32 num_points = 0;
+ U32 num_hulls = 0;
+
+ F32 debug_scale = mFMP ? mFMP->childGetValue("import_scale").asReal() : 1.f;
+ mPelvisZOffset = mFMP ? mFMP->childGetValue("pelvis_offset").asReal() : 3.0f;
+
+ if (mFMP && mFMP->childGetValue("upload_joints").asBoolean())
+ {
+ // FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail.
+ // see also call to addAttachmentPosOverride.
+ LLUUID fake_mesh_id;
+ fake_mesh_id.generate();
+ getPreviewAvatar()->addPelvisFixup(mPelvisZOffset, fake_mesh_id);
+ }
+
+ F32 streaming_cost = 0.f;
+ F32 physics_cost = 0.f;
+ for (U32 i = 0; i < mUploadData.size(); ++i)
+ {
+ LLModelInstance& instance = mUploadData[i];
+
+ if (accounted.find(instance.mModel) == accounted.end())
+ {
+ accounted.insert(instance.mModel);
+
+ LLModel::Decomposition& decomp =
+ instance.mLOD[LLModel::LOD_PHYSICS] ?
+ instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
+ instance.mModel->mPhysics;
+
+ //update instance skin info for each lods pelvisZoffset
+ for (int j = 0; j<LLModel::NUM_LODS; ++j)
+ {
+ if (instance.mLOD[j])
+ {
+ instance.mLOD[j]->mSkinInfo.mPelvisOffset = mPelvisZOffset;
+ }
+ }
+
+ std::stringstream ostr;
+ LLSD ret = LLModel::writeModel(ostr,
+ instance.mLOD[4],
+ instance.mLOD[3],
+ instance.mLOD[2],
+ instance.mLOD[1],
+ instance.mLOD[0],
+ decomp,
+ mFMP->childGetValue("upload_skin").asBoolean(),
+ mFMP->childGetValue("upload_joints").asBoolean(),
+ mFMP->childGetValue("lock_scale_if_joint_position").asBoolean(),
+ TRUE,
+ FALSE,
+ instance.mModel->mSubmodelID);
+
+ num_hulls += decomp.mHull.size();
+ for (U32 i = 0; i < decomp.mHull.size(); ++i)
+ {
+ num_points += decomp.mHull[i].size();
+ }
+
+ //calculate streaming cost
+ LLMatrix4 transformation = instance.mTransform;
+
+ LLVector3 position = LLVector3(0, 0, 0) * transformation;
+
+ LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position;
+ LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position;
+ LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position;
+ F32 x_length = x_transformed.normalize();
+ F32 y_length = y_transformed.normalize();
+ F32 z_length = z_transformed.normalize();
+ LLVector3 scale = LLVector3(x_length, y_length, z_length);
+
+ F32 radius = scale.length()*0.5f*debug_scale;
+
+ LLMeshCostData costs;
+ if (gMeshRepo.getCostData(ret, costs))
+ {
+ streaming_cost += costs.getRadiusBasedStreamingCost(radius);
+ }
+ }
+ }
+
+ F32 scale = mFMP ? mFMP->childGetValue("import_scale").asReal()*2.f : 2.f;
+
+ mDetailsSignal(mPreviewScale[0] * scale, mPreviewScale[1] * scale, mPreviewScale[2] * scale, streaming_cost, physics_cost);
+
+ updateStatusMessages();
+
+ return (U32)streaming_cost;
+}
+
+void LLModelPreview::rebuildUploadData()
+{
+ assert_main_thread();
+
+ mUploadData.clear();
+ mTextureSet.clear();
+
+ //fill uploaddata instance vectors from scene data
+
+ std::string requested_name = mFMP->getChild<LLUICtrl>("description_form")->getValue().asString();
+
+ LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");
+
+ F32 scale = scale_spinner->getValue().asReal();
+
+ LLMatrix4 scale_mat;
+ scale_mat.initScale(LLVector3(scale, scale, scale));
+
+ F32 max_scale = 0.f;
+
+ BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
+ U32 load_state = 0;
+
+ for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter)
+ { //for each transform in scene
+ LLMatrix4 mat = iter->first;
+
+ // compute position
+ LLVector3 position = LLVector3(0, 0, 0) * mat;
+
+ // compute scale
+ LLVector3 x_transformed = LLVector3(1, 0, 0) * mat - position;
+ LLVector3 y_transformed = LLVector3(0, 1, 0) * mat - position;
+ LLVector3 z_transformed = LLVector3(0, 0, 1) * mat - position;
+ F32 x_length = x_transformed.normalize();
+ F32 y_length = y_transformed.normalize();
+ F32 z_length = z_transformed.normalize();
+
+ max_scale = llmax(llmax(llmax(max_scale, x_length), y_length), z_length);
+
+ mat *= scale_mat;
+
+ for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();)
+ { //for each instance with said transform applied
+ LLModelInstance instance = *model_iter++;
+
+ LLModel* base_model = instance.mModel;
+
+ if (base_model && !requested_name.empty())
+ {
+ base_model->mRequestedLabel = requested_name;
+ }
+
+ for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--)
+ {
+ LLModel* lod_model = NULL;
+ if (!legacyMatching)
+ {
+ // Fill LOD slots by finding matching meshes by label with name extensions
+ // in the appropriate scene for each LOD. This fixes all kinds of issues
+ // where the indexed method below fails in spectacular fashion.
+ // If you don't take the time to name your LOD and PHYS meshes
+ // with the name of their corresponding mesh in the HIGH LOD,
+ // then the indexed method will be attempted below.
+
+ LLMatrix4 transform;
+
+ std::string name_to_match = instance.mLabel;
+ llassert(!name_to_match.empty());
+
+ int extensionLOD;
+ if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty())
+ {
+ extensionLOD = i;
+ }
+ else
+ {
+ //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
+ extensionLOD = mPhysicsSearchLOD;
+ }
+
+ std::string toAdd = getLodSuffix(extensionLOD);
+
+ if (name_to_match.find(toAdd) == -1)
+ {
+ name_to_match += toAdd;
+ }
+
+ FindModel(mScene[i], name_to_match, lod_model, transform);
+
+ if (!lod_model && i != LLModel::LOD_PHYSICS)
+ {
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "Search of" << name_to_match;
+ out << " in LOD" << i;
+ out << " list failed. Searching for alternative among LOD lists.";
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+
+ int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
+ while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
+ {
+ std::string name_to_match = instance.mLabel;
+ llassert(!name_to_match.empty());
+
+ std::string toAdd = getLodSuffix(searchLOD);
+
+ if (name_to_match.find(toAdd) == -1)
+ {
+ name_to_match += toAdd;
+ }
+
+ // See if we can find an appropriately named model in LOD 'searchLOD'
+ //
+ FindModel(mScene[searchLOD], name_to_match, lod_model, transform);
+ searchLOD++;
+ }
+ }
+ }
+ else
+ {
+ // Use old method of index-based association
+ U32 idx = 0;
+ for (idx = 0; idx < mBaseModel.size(); ++idx)
+ {
+ // find reference instance for this model
+ if (mBaseModel[idx] == base_model)
+ {
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "Attempting to use model index " << idx;
+ out << " for LOD" << i;
+ out << " of " << instance.mLabel;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+ break;
+ }
+ }
+
+ // If the model list for the current LOD includes that index...
+ //
+ if (mModel[i].size() > idx)
+ {
+ // Assign that index from the model list for our LOD as the LOD model for this instance
+ //
+ lod_model = mModel[i][idx];
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+ }
+ else if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "List of models does not include index " << idx;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+ }
+
+ if (lod_model)
+ {
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ if (i == LLModel::LOD_PHYSICS)
+ {
+ out << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel;
+ }
+ else
+ {
+ out << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel;
+ }
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+ instance.mLOD[i] = lod_model;
+ }
+ else
+ {
+ if (i < LLModel::LOD_HIGH && !lodsReady())
+ {
+ // assign a placeholder from previous LOD until lod generation is complete.
+ // Note: we might need to assign it regardless of conditions like named search does, to prevent crashes.
+ instance.mLOD[i] = instance.mLOD[i + 1];
+ }
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "List of models does not include " << instance.mLabel;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+ }
+ }
+
+ LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH];
+ if (!high_lod_model)
+ {
+ LLFloaterModelPreview::addStringToLog("Model " + instance.mLabel + " has no High Lod (LOD3).", true);
+ load_state = LLModelLoader::ERROR_MATERIALS;
+ mFMP->childDisable("calculate_btn");
+ }
+ else
+ {
+ for (U32 i = 0; i < LLModel::NUM_LODS - 1; i++)
+ {
+ int refFaceCnt = 0;
+ int modelFaceCnt = 0;
+ llassert(instance.mLOD[i]);
+ if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt))
+ {
+ LLFloaterModelPreview::addStringToLog("Model " + instance.mLabel + " has mismatching materials between lods." , true);
+ load_state = LLModelLoader::ERROR_MATERIALS;
+ mFMP->childDisable("calculate_btn");
+ }
+ }
+ LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)mFMP;
+ bool upload_skinweights = fmp && fmp->childGetValue("upload_skin").asBoolean();
+ if (upload_skinweights && high_lod_model->mSkinInfo.mJointNames.size() > 0)
+ {
+ LLQuaternion bind_rot = LLSkinningUtil::getUnscaledQuaternion(high_lod_model->mSkinInfo.mBindShapeMatrix);
+ LLQuaternion identity;
+ if (!bind_rot.isEqualEps(identity, 0.01))
+ {
+ // Bind shape matrix is not in standard X-forward orientation.
+ // Might be good idea to only show this once. It can be spammy.
+ std::ostringstream out;
+ out << "non-identity bind shape rot. mat is ";
+ out << high_lod_model->mSkinInfo.mBindShapeMatrix;
+ out << " bind_rot ";
+ out << bind_rot;
+ LL_WARNS() << out.str() << LL_ENDL;
+
+ LLFloaterModelPreview::addStringToLog(out, getLoadState() != LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION);
+ load_state = LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION;
+ }
+ }
+ }
+ instance.mTransform = mat;
+ mUploadData.push_back(instance);
+ }
+ }
+
+ for (U32 lod = 0; lod < LLModel::NUM_LODS - 1; lod++)
+ {
+ // Search for models that are not included into upload data
+ // If we found any, that means something we loaded is not a sub-model.
+ for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind)
+ {
+ bool found_model = false;
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+ if (instance.mLOD[lod] == mModel[lod][model_ind])
+ {
+ found_model = true;
+ break;
+ }
+ }
+ if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID)
+ {
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models.";
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, true);
+ }
+ load_state = LLModelLoader::ERROR_MATERIALS;
+ mFMP->childDisable("calculate_btn");
+ }
+ }
+ }
+
+ // Update state for notifications
+ if (load_state > 0)
+ {
+ // encountered issues
+ setLoadState(load_state);
+ }
+ else if (getLoadState() == LLModelLoader::ERROR_MATERIALS
+ || getLoadState() == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION)
+ {
+ // This is only valid for these two error types because they are
+ // only used inside rebuildUploadData() and updateStatusMessages()
+ // updateStatusMessages() is called after rebuildUploadData()
+ setLoadState(LLModelLoader::DONE);
+ }
+
+ F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE - 0.1f) / max_scale;
+
+ F32 max_axis = llmax(mPreviewScale.mV[0], mPreviewScale.mV[1]);
+ max_axis = llmax(max_axis, mPreviewScale.mV[2]);
+ max_axis *= 2.f;
+
+ //clamp scale so that total imported model bounding box is smaller than 240m on a side
+ max_import_scale = llmin(max_import_scale, 240.f / max_axis);
+
+ scale_spinner->setMaxValue(max_import_scale);
+
+ if (max_import_scale < scale)
+ {
+ scale_spinner->setValue(max_import_scale);
+ }
+
+}
+
+void LLModelPreview::saveUploadData(bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position)
+{
+ if (!mLODFile[LLModel::LOD_HIGH].empty())
+ {
+ std::string filename = mLODFile[LLModel::LOD_HIGH];
+ std::string slm_filename;
+
+ if (LLModelLoader::getSLMFilename(filename, slm_filename))
+ {
+ saveUploadData(slm_filename, save_skinweights, save_joint_positions, lock_scale_if_joint_position);
+ }
+ }
+}
+
+void LLModelPreview::saveUploadData(const std::string& filename,
+ bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position)
+{
+
+ std::set<LLPointer<LLModel> > meshes;
+ std::map<LLModel*, std::string> mesh_binary;
+
+ LLModel::hull empty_hull;
+
+ LLSD data;
+
+ data["version"] = SLM_SUPPORTED_VERSION;
+ if (!mBaseModel.empty())
+ {
+ data["name"] = mBaseModel[0]->getName();
+ }
+
+ S32 mesh_id = 0;
+
+ //build list of unique models and initialize local id
+ for (U32 i = 0; i < mUploadData.size(); ++i)
+ {
+ LLModelInstance& instance = mUploadData[i];
+
+ if (meshes.find(instance.mModel) == meshes.end())
+ {
+ instance.mModel->mLocalID = mesh_id++;
+ meshes.insert(instance.mModel);
+
+ std::stringstream str;
+ LLModel::Decomposition& decomp =
+ instance.mLOD[LLModel::LOD_PHYSICS].notNull() ?
+ instance.mLOD[LLModel::LOD_PHYSICS]->mPhysics :
+ instance.mModel->mPhysics;
+
+ LLModel::writeModel(str,
+ instance.mLOD[LLModel::LOD_PHYSICS],
+ instance.mLOD[LLModel::LOD_HIGH],
+ instance.mLOD[LLModel::LOD_MEDIUM],
+ instance.mLOD[LLModel::LOD_LOW],
+ instance.mLOD[LLModel::LOD_IMPOSTOR],
+ decomp,
+ save_skinweights,
+ save_joint_positions,
+ lock_scale_if_joint_position,
+ FALSE, TRUE, instance.mModel->mSubmodelID);
+
+ data["mesh"][instance.mModel->mLocalID] = str.str();
+ }
+
+ data["instance"][i] = instance.asLLSD();
+ }
+
+ llofstream out(filename.c_str(), std::ios_base::out | std::ios_base::binary);
+ LLSDSerialize::toBinary(data, out);
+ out.flush();
+ out.close();
+}
+
+void LLModelPreview::clearModel(S32 lod)
+{
+ if (lod < 0 || lod > LLModel::LOD_PHYSICS)
+ {
+ return;
+ }
+
+ mVertexBuffer[lod].clear();
+ mModel[lod].clear();
+ mScene[lod].clear();
+}
+
+void LLModelPreview::getJointAliases(JointMap& joint_map)
+{
+ // Get all standard skeleton joints from the preview avatar.
+ LLVOAvatar *av = getPreviewAvatar();
+
+ //Joint names and aliases come from avatar_skeleton.xml
+
+ joint_map = av->getJointAliases();
+
+ std::vector<std::string> cv_names, attach_names;
+ av->getSortedJointNames(1, cv_names);
+ av->getSortedJointNames(2, attach_names);
+ for (std::vector<std::string>::iterator it = cv_names.begin(); it != cv_names.end(); ++it)
+ {
+ joint_map[*it] = *it;
+ }
+ for (std::vector<std::string>::iterator it = attach_names.begin(); it != attach_names.end(); ++it)
+ {
+ joint_map[*it] = *it;
+ }
+}
+
+void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable_slm)
+{
+ assert_main_thread();
+
+ LLMutexLock lock(this);
+
+ if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::NUM_LODS - 1)
+ {
+ std::ostringstream out;
+ out << "Invalid level of detail: ";
+ out << lod;
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, true);
+ assert(lod >= LLModel::LOD_IMPOSTOR && lod < LLModel::NUM_LODS);
+ return;
+ }
+
+ // This triggers if you bring up the file picker and then hit CANCEL.
+ // Just use the previous model (if any) and ignore that you brought up
+ // the file picker.
+
+ if (filename.empty())
+ {
+ if (mBaseModel.empty())
+ {
+ // this is the initial file picking. Close the whole floater
+ // if we don't have a base model to show for high LOD.
+ mFMP->closeFloater(false);
+ }
+ mLoading = false;
+ return;
+ }
+
+ if (mModelLoader)
+ {
+ LL_WARNS() << "Incompleted model load operation pending." << LL_ENDL;
+ return;
+ }
+
+ mLODFile[lod] = filename;
+
+ if (lod == LLModel::LOD_HIGH)
+ {
+ clearGLODGroup();
+ }
+
+ std::map<std::string, std::string> joint_alias_map;
+ getJointAliases(joint_alias_map);
+
+ mModelLoader = new LLDAELoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"),
+ gSavedSettings.getBOOL("ImporterPreprocessDAE"));
+
+ if (force_disable_slm)
+ {
+ mModelLoader->mTrySLM = false;
+ }
+ else
+ {
+ // For MAINT-6647, we have set force_disable_slm to true,
+ // which means this code path will never be taken. Trying to
+ // re-use SLM files has never worked properly; in particular,
+ // it tends to force the UI into strange checkbox options
+ // which cannot be altered.
+
+ //only try to load from slm if viewer is configured to do so and this is the
+ //initial model load (not an LoD or physics shape)
+ mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty();
+ }
+ mModelLoader->start();
+
+ mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file"));
+
+ setPreviewLOD(lod);
+
+ if (getLoadState() >= LLModelLoader::ERROR_PARSING)
+ {
+ mFMP->childDisable("ok_btn");
+ mFMP->childDisable("calculate_btn");
+ }
+
+ if (lod == mPreviewLOD)
+ {
+ mFMP->childSetValue("lod_file_" + lod_name[lod], mLODFile[lod]);
+ }
+ else if (lod == LLModel::LOD_PHYSICS)
+ {
+ mFMP->childSetValue("physics_file", mLODFile[lod]);
+ }
+
+ mFMP->openFloater();
+}
+
+void LLModelPreview::setPhysicsFromLOD(S32 lod)
+{
+ assert_main_thread();
+
+ if (lod >= 0 && lod <= 3)
+ {
+ mPhysicsSearchLOD = lod;
+ mModel[LLModel::LOD_PHYSICS] = mModel[lod];
+ mScene[LLModel::LOD_PHYSICS] = mScene[lod];
+ mLODFile[LLModel::LOD_PHYSICS].clear();
+ mFMP->childSetValue("physics_file", mLODFile[LLModel::LOD_PHYSICS]);
+ mVertexBuffer[LLModel::LOD_PHYSICS].clear();
+ rebuildUploadData();
+ refresh();
+ updateStatusMessages();
+ }
+}
+
+void LLModelPreview::clearIncompatible(S32 lod)
+{
+ //Don't discard models if specified model is the physic rep
+ if (lod == LLModel::LOD_PHYSICS)
+ {
+ return;
+ }
+
+ // at this point we don't care about sub-models,
+ // different amount of sub-models means face count mismatch, not incompatibility
+ U32 lod_size = countRootModels(mModel[lod]);
+ for (U32 i = 0; i <= LLModel::LOD_HIGH; i++)
+ { //clear out any entries that aren't compatible with this model
+ if (i != lod)
+ {
+ if (countRootModels(mModel[i]) != lod_size)
+ {
+ mModel[i].clear();
+ mScene[i].clear();
+ mVertexBuffer[i].clear();
+
+ if (i == LLModel::LOD_HIGH)
+ {
+ mBaseModel = mModel[lod];
+ clearGLODGroup();
+ mBaseScene = mScene[lod];
+ mVertexBuffer[5].clear();
+ }
+ }
+ }
+ }
+}
+
+void LLModelPreview::clearGLODGroup()
+{
+ if (mGroup)
+ {
+ for (std::map<LLPointer<LLModel>, U32>::iterator iter = mObject.begin(); iter != mObject.end(); ++iter)
+ {
+ glodDeleteObject(iter->second);
+ stop_gloderror();
+ }
+ mObject.clear();
+
+ glodDeleteGroup(mGroup);
+ stop_gloderror();
+ mGroup = 0;
+ }
+}
+
+void LLModelPreview::loadModelCallback(S32 loaded_lod)
+{
+ assert_main_thread();
+
+ LLMutexLock lock(this);
+ if (!mModelLoader)
+ {
+ mLoading = false;
+ return;
+ }
+ if (getLoadState() >= LLModelLoader::ERROR_PARSING)
+ {
+ mLoading = false;
+ mModelLoader = NULL;
+ mLodsWithParsingError.push_back(loaded_lod);
+ return;
+ }
+
+ mLodsWithParsingError.erase(std::remove(mLodsWithParsingError.begin(), mLodsWithParsingError.end(), loaded_lod), mLodsWithParsingError.end());
+ if (mLodsWithParsingError.empty())
+ {
+ mFMP->childEnable("calculate_btn");
+ }
+
+ // Copy determinations about rig so UI will reflect them
+ //
+ setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
+ setLegacyRigFlags(mModelLoader->getLegacyRigFlags());
+
+ mModelLoader->loadTextures();
+
+ if (loaded_lod == -1)
+ { //populate all LoDs from model loader scene
+ mBaseModel.clear();
+ mBaseScene.clear();
+
+ bool skin_weights = false;
+ bool joint_overrides = false;
+ bool lock_scale_if_joint_position = false;
+
+ for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
+ { //for each LoD
+
+ //clear scene and model info
+ mScene[lod].clear();
+ mModel[lod].clear();
+ mVertexBuffer[lod].clear();
+
+ if (mModelLoader->mScene.begin()->second[0].mLOD[lod].notNull())
+ { //if this LoD exists in the loaded scene
+
+ //copy scene to current LoD
+ mScene[lod] = mModelLoader->mScene;
+
+ //touch up copied scene to look like current LoD
+ for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter)
+ {
+ LLModelLoader::model_instance_list& list = iter->second;
+
+ for (LLModelLoader::model_instance_list::iterator list_iter = list.begin(); list_iter != list.end(); ++list_iter)
+ {
+ //override displayed model with current LoD
+ list_iter->mModel = list_iter->mLOD[lod];
+
+ if (!list_iter->mModel)
+ {
+ continue;
+ }
+
+ //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index)
+ S32 idx = list_iter->mModel->mLocalID;
+
+ if (mModel[lod].size() <= idx)
+ { //stretch model list to fit model at given index
+ mModel[lod].resize(idx + 1);
+ }
+
+ mModel[lod][idx] = list_iter->mModel;
+ if (!list_iter->mModel->mSkinWeights.empty())
+ {
+ skin_weights = true;
+
+ if (!list_iter->mModel->mSkinInfo.mAlternateBindMatrix.empty())
+ {
+ joint_overrides = true;
+ }
+ if (list_iter->mModel->mSkinInfo.mLockScaleIfJointPosition)
+ {
+ lock_scale_if_joint_position = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (mFMP)
+ {
+ LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)mFMP;
+
+ if (skin_weights)
+ { //enable uploading/previewing of skin weights if present in .slm file
+ fmp->enableViewOption("show_skin_weight");
+ mViewOption["show_skin_weight"] = true;
+ fmp->childSetValue("upload_skin", true);
+ }
+
+ if (joint_overrides)
+ {
+ fmp->enableViewOption("show_joint_overrides");
+ mViewOption["show_joint_overrides"] = true;
+ fmp->enableViewOption("show_joint_positions");
+ mViewOption["show_joint_positions"] = true;
+ fmp->childSetValue("upload_joints", true);
+ }
+ else
+ {
+ fmp->clearAvatarTab();
+ }
+
+ if (lock_scale_if_joint_position)
+ {
+ fmp->enableViewOption("lock_scale_if_joint_position");
+ mViewOption["lock_scale_if_joint_position"] = true;
+ fmp->childSetValue("lock_scale_if_joint_position", true);
+ }
+ }
+
+ //copy high lod to base scene for LoD generation
+ mBaseScene = mScene[LLModel::LOD_HIGH];
+ mBaseModel = mModel[LLModel::LOD_HIGH];
+
+ mDirty = true;
+ resetPreviewTarget();
+ }
+ else
+ { //only replace given LoD
+ mModel[loaded_lod] = mModelLoader->mModelList;
+ mScene[loaded_lod] = mModelLoader->mScene;
+ mVertexBuffer[loaded_lod].clear();
+
+ setPreviewLOD(loaded_lod);
+
+ if (loaded_lod == LLModel::LOD_HIGH)
+ { //save a copy of the highest LOD for automatic LOD manipulation
+ if (mBaseModel.empty())
+ { //first time we've loaded a model, auto-gen LoD
+ mGenLOD = true;
+ }
+
+ mBaseModel = mModel[loaded_lod];
+ clearGLODGroup();
+
+ mBaseScene = mScene[loaded_lod];
+ mVertexBuffer[5].clear();
+ }
+ else
+ {
+ BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching");
+ if (!legacyMatching)
+ {
+ if (!mBaseModel.empty())
+ {
+ BOOL name_based = FALSE;
+ BOOL has_submodels = FALSE;
+ for (U32 idx = 0; idx < mBaseModel.size(); ++idx)
+ {
+ if (mBaseModel[idx]->mSubmodelID)
+ { // don't do index-based renaming when the base model has submodels
+ has_submodels = TRUE;
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "High LOD has submodels";
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+ break;
+ }
+ }
+
+ for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx)
+ {
+ std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
+
+ LLModel* found_model = NULL;
+ LLMatrix4 transform;
+ FindModel(mBaseScene, loaded_name, found_model, transform);
+ if (found_model)
+ { // don't rename correctly named models (even if they are placed in a wrong order)
+ name_based = TRUE;
+ }
+
+ if (mModel[loaded_lod][idx]->mSubmodelID)
+ { // don't rename the models when loaded LOD model has submodels
+ has_submodels = TRUE;
+ }
+ }
+
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found";
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+
+ if (!name_based && !has_submodels)
+ { // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601)
+ // this actually works like "ImporterLegacyMatching" for this particular LOD
+ for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx)
+ {
+ std::string name = mBaseModel[idx]->mLabel;
+ std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
+
+ if (loaded_name != name)
+ {
+ name += getLodSuffix(loaded_lod);
+
+ if (mImporterDebug)
+ {
+ std::ostringstream out;
+ out << "Loded model name " << mModel[loaded_lod][idx]->mLabel;
+ out << " for LOD " << loaded_lod;
+ out << " doesn't match the base model. Renaming to " << name;
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ }
+
+ mModel[loaded_lod][idx]->mLabel = name;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ clearIncompatible(loaded_lod);
+
+ mDirty = true;
+
+ if (loaded_lod == LLModel::LOD_HIGH)
+ {
+ resetPreviewTarget();
+ }
+ }
+
+ mLoading = false;
+ if (mFMP)
+ {
+ if (!mBaseModel.empty())
+ {
+ const std::string& model_name = mBaseModel[0]->getName();
+ LLLineEditor* description_form = mFMP->getChild<LLLineEditor>("description_form");
+ if (description_form->getText().empty())
+ {
+ description_form->setText(model_name);
+ }
+ // Add info to log that loading is complete (purpose: separator between loading and other logs)
+ LLSD args;
+ args["MODEL_NAME"] = model_name; // Teoretically shouldn't be empty, but might be better idea to add filename here
+ LLFloaterModelPreview::addStringToLog("ModelLoaded", args, false, loaded_lod);
+ }
+ }
+ refresh();
+
+ mModelLoadedSignal();
+
+ mModelLoader = NULL;
+}
+
+void LLModelPreview::resetPreviewTarget()
+{
+ if (mModelLoader)
+ {
+ mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f;
+ mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f;
+ }
+
+ setPreviewTarget(mPreviewScale.magVec()*10.f);
+}
+
+void LLModelPreview::generateNormals()
+{
+ assert_main_thread();
+
+ S32 which_lod = mPreviewLOD;
+
+ if (which_lod > 4 || which_lod < 0 ||
+ mModel[which_lod].empty())
+ {
+ return;
+ }
+
+ F32 angle_cutoff = mFMP->childGetValue("crease_angle").asReal();
+
+ mRequestedCreaseAngle[which_lod] = angle_cutoff;
+
+ angle_cutoff *= DEG_TO_RAD;
+
+ if (which_lod == 3 && !mBaseModel.empty())
+ {
+ if (mBaseModelFacesCopy.empty())
+ {
+ mBaseModelFacesCopy.reserve(mBaseModel.size());
+ for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it)
+ {
+ v_LLVolumeFace_t faces;
+ (*it)->copyFacesTo(faces);
+ mBaseModelFacesCopy.push_back(faces);
+ }
+ }
+
+ for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it)
+ {
+ (*it)->generateNormals(angle_cutoff);
+ }
+
+ mVertexBuffer[5].clear();
+ }
+
+ bool perform_copy = mModelFacesCopy[which_lod].empty();
+ if (perform_copy) {
+ mModelFacesCopy[which_lod].reserve(mModel[which_lod].size());
+ }
+
+ for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it)
+ {
+ if (perform_copy)
+ {
+ v_LLVolumeFace_t faces;
+ (*it)->copyFacesTo(faces);
+ mModelFacesCopy[which_lod].push_back(faces);
+ }
+
+ (*it)->generateNormals(angle_cutoff);
+ }
+
+ mVertexBuffer[which_lod].clear();
+ refresh();
+ updateStatusMessages();
+}
+
+void LLModelPreview::restoreNormals()
+{
+ S32 which_lod = mPreviewLOD;
+
+ if (which_lod > 4 || which_lod < 0 ||
+ mModel[which_lod].empty())
+ {
+ return;
+ }
+
+ if (!mBaseModelFacesCopy.empty())
+ {
+ llassert(mBaseModelFacesCopy.size() == mBaseModel.size());
+
+ vv_LLVolumeFace_t::const_iterator itF = mBaseModelFacesCopy.begin();
+ for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it, ++itF)
+ {
+ (*it)->copyFacesFrom((*itF));
+ }
+
+ mBaseModelFacesCopy.clear();
+ }
+
+ if (!mModelFacesCopy[which_lod].empty())
+ {
+ vv_LLVolumeFace_t::const_iterator itF = mModelFacesCopy[which_lod].begin();
+ for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it, ++itF)
+ {
+ (*it)->copyFacesFrom((*itF));
+ }
+
+ mModelFacesCopy[which_lod].clear();
+ }
+
+ mVertexBuffer[which_lod].clear();
+ refresh();
+ updateStatusMessages();
+}
+
+void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
+{
+ // Allow LoD from -1 to LLModel::LOD_PHYSICS
+ if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
+ {
+ std::ostringstream out;
+ out << "Invalid level of detail: " << which_lod;
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ assert(which_lod >= -1 && which_lod < LLModel::NUM_LODS);
+ return;
+ }
+
+ if (mBaseModel.empty())
+ {
+ return;
+ }
+
+ LLVertexBuffer::unbind();
+
+ bool no_ff = LLGLSLShader::sNoFixedFunction;
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ LLGLSLShader::sNoFixedFunction = false;
+
+ if (shader)
+ {
+ shader->unbind();
+ }
+
+ stop_gloderror();
+ static U32 cur_name = 1;
+
+ S32 limit = -1;
+
+ U32 triangle_count = 0;
+
+ U32 instanced_triangle_count = 0;
+
+ //get the triangle count for the whole scene
+ for (LLModelLoader::scene::iterator iter = mBaseScene.begin(), endIter = mBaseScene.end(); iter != endIter; ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
+ {
+ LLModel* mdl = instance->mModel;
+ if (mdl)
+ {
+ instanced_triangle_count += mdl->getNumTriangles();
+ }
+ }
+ }
+
+ //get the triangle count for the non-instanced set of models
+ for (U32 i = 0; i < mBaseModel.size(); ++i)
+ {
+ triangle_count += mBaseModel[i]->getNumTriangles();
+ }
+
+ //get ratio of uninstanced triangles to instanced triangles
+ F32 triangle_ratio = (F32)triangle_count / (F32)instanced_triangle_count;
+
+ U32 base_triangle_count = triangle_count;
+
+ U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ U32 lod_mode = 0;
+
+ F32 lod_error_threshold = 0;
+
+ // The LoD should be in range from Lowest to High
+ if (which_lod > -1 && which_lod < NUM_LOD)
+ {
+ LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode_" + lod_name[which_lod]);
+ if (iface)
+ {
+ lod_mode = iface->getFirstSelectedIndex();
+ }
+
+ lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
+ }
+
+ if (which_lod != -1)
+ {
+ mRequestedLoDMode[which_lod] = lod_mode;
+ }
+
+ if (lod_mode == 0)
+ {
+ lod_mode = GLOD_TRIANGLE_BUDGET;
+
+ // The LoD should be in range from Lowest to High
+ if (which_lod > -1 && which_lod < NUM_LOD)
+ {
+ limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger();
+ //convert from "scene wide" to "non-instanced" triangle limit
+ limit = (S32)((F32)limit*triangle_ratio);
+ }
+ }
+ else
+ {
+ lod_mode = GLOD_ERROR_THRESHOLD;
+ }
+
+ bool object_dirty = false;
+
+ if (mGroup == 0)
+ {
+ object_dirty = true;
+ mGroup = cur_name++;
+ glodNewGroup(mGroup);
+ }
+
+ if (object_dirty)
+ {
+ for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter)
+ { //build GLOD objects for each model in base model list
+ LLModel* mdl = *iter;
+
+ if (mObject[mdl] != 0)
+ {
+ glodDeleteObject(mObject[mdl]);
+ }
+
+ mObject[mdl] = cur_name++;
+
+ glodNewObject(mObject[mdl], mGroup, GLOD_DISCRETE);
+ stop_gloderror();
+
+ if (iter == mBaseModel.begin() && !mdl->mSkinWeights.empty())
+ { //regenerate vertex buffer for skinned models to prevent animation feedback during LOD generation
+ mVertexBuffer[5].clear();
+ }
+
+ if (mVertexBuffer[5].empty())
+ {
+ genBuffers(5, false);
+ }
+
+ U32 tri_count = 0;
+ for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i)
+ {
+ LLVertexBuffer* buff = mVertexBuffer[5][mdl][i];
+ buff->setBuffer(type_mask & buff->getTypeMask());
+
+ U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();
+ if (num_indices > 2)
+ {
+ glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*)mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
+ }
+ tri_count += num_indices / 3;
+ stop_gloderror();
+ }
+
+ glodBuildObject(mObject[mdl]);
+ stop_gloderror();
+ }
+ }
+
+
+ S32 start = LLModel::LOD_HIGH;
+ S32 end = 0;
+
+ if (which_lod != -1)
+ {
+ start = end = which_lod;
+ }
+
+ mMaxTriangleLimit = base_triangle_count;
+
+ for (S32 lod = start; lod >= end; --lod)
+ {
+ if (which_lod == -1)
+ {
+ if (lod < start)
+ {
+ triangle_count /= decimation;
+ }
+ }
+ else
+ {
+ if (enforce_tri_limit)
+ {
+ triangle_count = limit;
+ }
+ else
+ {
+ for (S32 j = LLModel::LOD_HIGH; j>which_lod; --j)
+ {
+ triangle_count /= decimation;
+ }
+ }
+ }
+
+ mModel[lod].clear();
+ mModel[lod].resize(mBaseModel.size());
+ mVertexBuffer[lod].clear();
+
+ U32 actual_tris = 0;
+ U32 actual_verts = 0;
+ U32 submeshes = 0;
+
+ mRequestedTriangleCount[lod] = (S32)((F32)triangle_count / triangle_ratio);
+ mRequestedErrorThreshold[lod] = lod_error_threshold;
+
+ glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode);
+ stop_gloderror();
+
+ glodGroupParameteri(mGroup, GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR);
+ stop_gloderror();
+
+ glodGroupParameterf(mGroup, GLOD_OBJECT_SPACE_ERROR_THRESHOLD, lod_error_threshold);
+ stop_gloderror();
+
+ if (lod_mode != GLOD_TRIANGLE_BUDGET)
+ {
+ glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, 0);
+ }
+ else
+ {
+ //SH-632: always add 1 to desired amount to avoid decimating below desired amount
+ glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, triangle_count + 1);
+ }
+
+ stop_gloderror();
+ glodAdaptGroup(mGroup);
+ stop_gloderror();
+
+ for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
+ {
+ LLModel* base = mBaseModel[mdl_idx];
+
+ GLint patch_count = 0;
+ glodGetObjectParameteriv(mObject[base], GLOD_NUM_PATCHES, &patch_count);
+ stop_gloderror();
+
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+ mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
+
+ std::string name = base->mLabel + getLodSuffix(lod);
+
+ mModel[lod][mdl_idx]->mLabel = name;
+ mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
+
+ GLint* sizes = new GLint[patch_count * 2];
+ glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);
+ stop_gloderror();
+
+ GLint* names = new GLint[patch_count];
+ glodGetObjectParameteriv(mObject[base], GLOD_PATCH_NAMES, names);
+ stop_gloderror();
+
+ mModel[lod][mdl_idx]->setNumVolumeFaces(patch_count);
+
+ LLModel* target_model = mModel[lod][mdl_idx];
+
+ for (GLint i = 0; i < patch_count; ++i)
+ {
+ type_mask = mVertexBuffer[5][base][i]->getTypeMask();
+
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
+
+ if (sizes[i * 2 + 1] > 0 && sizes[i * 2] > 0)
+ {
+ if (!buff->allocateBuffer(sizes[i * 2 + 1], sizes[i * 2], true))
+ {
+ // Todo: find a way to stop preview in this case instead of crashing
+ LL_ERRS() << "Failed buffer allocation during preview LOD generation."
+ << " Vertices: " << sizes[i * 2 + 1]
+ << " Indices: " << sizes[i * 2] << LL_ENDL;
+ }
+ buff->setBuffer(type_mask);
+ glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*)buff->getIndicesPointer());
+ stop_gloderror();
+ }
+ else
+ {
+ // This face was eliminated or we failed to allocate buffer,
+ // attempt to create a dummy triangle (one vertex, 3 indices, all 0)
+ buff->allocateBuffer(1, 3, true);
+ memset((U8*)buff->getMappedData(), 0, buff->getSize());
+ memset((U8*)buff->getIndicesPointer(), 0, buff->getIndicesSize());
+ }
+
+ buff->validateRange(0, buff->getNumVerts() - 1, buff->getNumIndices(), 0);
+
+ LLStrider<LLVector3> pos;
+ LLStrider<LLVector3> norm;
+ LLStrider<LLVector2> tc;
+ LLStrider<U16> index;
+
+ buff->getVertexStrider(pos);
+ if (type_mask & LLVertexBuffer::MAP_NORMAL)
+ {
+ buff->getNormalStrider(norm);
+ }
+ if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ buff->getTexCoord0Strider(tc);
+ }
+
+ buff->getIndexStrider(index);
+
+ target_model->setVolumeFaceData(names[i], pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices());
+ actual_tris += buff->getNumIndices() / 3;
+ actual_verts += buff->getNumVerts();
+ ++submeshes;
+
+ if (!validate_face(target_model->getVolumeFace(names[i])))
+ {
+ LL_ERRS() << "Invalid face generated during LOD generation." << LL_ENDL;
+ }
+ }
+
+ //blind copy skin weights and just take closest skin weight to point on
+ //decimated mesh for now (auto-generating LODs with skin weights is still a bit
+ //of an open problem).
+ target_model->mPosition = base->mPosition;
+ target_model->mSkinWeights = base->mSkinWeights;
+ target_model->mSkinInfo = base->mSkinInfo;
+ //copy material list
+ target_model->mMaterialList = base->mMaterialList;
+
+ if (!validate_model(target_model))
+ {
+ LL_ERRS() << "Invalid model generated when creating LODs" << LL_ENDL;
+ }
+
+ delete[] sizes;
+ delete[] names;
+ }
+
+ //rebuild scene based on mBaseScene
+ mScene[lod].clear();
+ mScene[lod] = mBaseScene;
+
+ for (U32 i = 0; i < mBaseModel.size(); ++i)
+ {
+ LLModel* mdl = mBaseModel[i];
+ LLModel* target = mModel[lod][i];
+ if (target)
+ {
+ for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter)
+ {
+ for (U32 j = 0; j < iter->second.size(); ++j)
+ {
+ if (iter->second[j].mModel == mdl)
+ {
+ iter->second[j].mModel = target;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mResourceCost = calcResourceCost();
+
+ LLVertexBuffer::unbind();
+ LLGLSLShader::sNoFixedFunction = no_ff;
+ if (shader)
+ {
+ shader->bind();
+ }
+}
+
+void LLModelPreview::updateStatusMessages()
+{
+ // bit mask values for physics errors. used to prevent overwrite of single line status
+ // TODO: use this to provied multiline status
+ enum PhysicsError
+ {
+ NONE = 0,
+ NOHAVOK = 1,
+ DEGENERATE = 2,
+ TOOMANYHULLS = 4,
+ TOOMANYVERTSINHULL = 8
+ };
+
+ assert_main_thread();
+
+ U32 has_physics_error{ PhysicsError::NONE }; // physics error bitmap
+ //triangle/vertex/submesh count for each mesh asset for each lod
+ std::vector<S32> tris[LLModel::NUM_LODS];
+ std::vector<S32> verts[LLModel::NUM_LODS];
+ std::vector<S32> submeshes[LLModel::NUM_LODS];
+
+ //total triangle/vertex/submesh count for each lod
+ S32 total_tris[LLModel::NUM_LODS];
+ S32 total_verts[LLModel::NUM_LODS];
+ S32 total_submeshes[LLModel::NUM_LODS];
+
+ for (U32 i = 0; i < LLModel::NUM_LODS - 1; i++)
+ {
+ total_tris[i] = 0;
+ total_verts[i] = 0;
+ total_submeshes[i] = 0;
+ }
+
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+
+ LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH];
+ if (!model_high_lod)
+ {
+ setLoadState(LLModelLoader::ERROR_MATERIALS);
+ mFMP->childDisable("calculate_btn");
+ continue;
+ }
+
+ for (U32 i = 0; i < LLModel::NUM_LODS - 1; i++)
+ {
+ LLModel* lod_model = instance.mLOD[i];
+ if (!lod_model)
+ {
+ setLoadState(LLModelLoader::ERROR_MATERIALS);
+ mFMP->childDisable("calculate_btn");
+ }
+ else
+ {
+ //for each model in the lod
+ S32 cur_tris = 0;
+ S32 cur_verts = 0;
+ S32 cur_submeshes = lod_model->getNumVolumeFaces();
+
+ for (S32 j = 0; j < cur_submeshes; ++j)
+ { //for each submesh (face), add triangles and vertices to current total
+ const LLVolumeFace& face = lod_model->getVolumeFace(j);
+ cur_tris += face.mNumIndices / 3;
+ cur_verts += face.mNumVertices;
+ }
+
+ std::string instance_name = instance.mLabel;
+
+ if (mImporterDebug)
+ {
+ // Useful for debugging generalized complaints below about total submeshes which don't have enough
+ // context to address exactly what needs to be fixed to move towards compliance with the rules.
+ //
+ std::ostringstream out;
+ out << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+
+ out.str("");
+ out << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+
+ out.str("");
+ out << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes;
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+
+ out.str("");
+ LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin();
+ while (mat_iter != lod_model->mMaterialList.end())
+ {
+ out << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter);
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ out.str("");
+ mat_iter++;
+ }
+ }
+
+ //add this model to the lod total
+ total_tris[i] += cur_tris;
+ total_verts[i] += cur_verts;
+ total_submeshes[i] += cur_submeshes;
+
+ //store this model's counts to asset data
+ tris[i].push_back(cur_tris);
+ verts[i].push_back(cur_verts);
+ submeshes[i].push_back(cur_submeshes);
+ }
+ }
+ }
+
+ if (mMaxTriangleLimit == 0)
+ {
+ mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
+ }
+
+ mHasDegenerate = false;
+ {//check for degenerate triangles in physics mesh
+ U32 lod = LLModel::LOD_PHYSICS;
+ const LLVector4a scale(0.5f);
+ for (U32 i = 0; i < mModel[lod].size() && !mHasDegenerate; ++i)
+ { //for each model in the lod
+ if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty())
+ { //no decomp exists
+ S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces();
+ for (S32 j = 0; j < cur_submeshes && !mHasDegenerate; ++j)
+ { //for each submesh (face), add triangles and vertices to current total
+ LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
+ for (S32 k = 0; (k < face.mNumIndices) && !mHasDegenerate;)
+ {
+ U16 index_a = face.mIndices[k + 0];
+ U16 index_b = face.mIndices[k + 1];
+ U16 index_c = face.mIndices[k + 2];
+
+ if (index_c == 0 && index_b == 0 && index_a == 0) // test in reverse as 3rd index is less likely to be 0 in a normal case
+ {
+ LL_DEBUGS("MeshValidation") << "Empty placeholder triangle (3 identical index 0 verts) ignored" << LL_ENDL;
+ }
+ else
+ {
+ LLVector4a v1; v1.setMul(face.mPositions[index_a], scale);
+ LLVector4a v2; v2.setMul(face.mPositions[index_b], scale);
+ LLVector4a v3; v3.setMul(face.mPositions[index_c], scale);
+ if (ll_is_degenerate(v1, v2, v3))
+ {
+ mHasDegenerate = true;
+ }
+ }
+ k += 3;
+ }
+ }
+ }
+ }
+ }
+
+ // flag degenerates here rather than deferring to a MAV error later
+ mFMP->childSetVisible("physics_status_message_text", mHasDegenerate); //display or clear
+ auto degenerateIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon");
+ degenerateIcon->setVisible(mHasDegenerate);
+ if (mHasDegenerate)
+ {
+ has_physics_error |= PhysicsError::DEGENERATE;
+ mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_degenerate_triangles"));
+ LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Error");
+ degenerateIcon->setImage(img);
+ }
+
+ mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
+
+ std::string mesh_status_na = mFMP->getString("mesh_status_na");
+
+ S32 upload_status[LLModel::LOD_HIGH + 1];
+
+ mModelNoErrors = true;
+
+ const U32 lod_high = LLModel::LOD_HIGH;
+ U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]);
+
+ for (S32 lod = 0; lod <= lod_high; ++lod)
+ {
+ upload_status[lod] = 0;
+
+ std::string message = "mesh_status_good";
+
+ if (total_tris[lod] > 0)
+ {
+ mFMP->childSetValue(lod_triangles_name[lod], llformat("%d", total_tris[lod]));
+ mFMP->childSetValue(lod_vertices_name[lod], llformat("%d", total_verts[lod]));
+ }
+ else
+ {
+ if (lod == lod_high)
+ {
+ upload_status[lod] = 2;
+ message = "mesh_status_missing_lod";
+ }
+ else
+ {
+ for (S32 i = lod - 1; i >= 0; --i)
+ {
+ if (total_tris[i] > 0)
+ {
+ upload_status[lod] = 2;
+ message = "mesh_status_missing_lod";
+ }
+ }
+ }
+
+ mFMP->childSetValue(lod_triangles_name[lod], mesh_status_na);
+ mFMP->childSetValue(lod_vertices_name[lod], mesh_status_na);
+ }
+
+ if (lod != lod_high)
+ {
+ if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high])
+ { //number of submeshes is different
+ message = "mesh_status_submesh_mismatch";
+ upload_status[lod] = 2;
+ }
+ else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count)
+ {//number of submodels is different, not all faces are matched correctly.
+ message = "mesh_status_submesh_mismatch";
+ upload_status[lod] = 2;
+ // Note: Submodels in instance were loaded from higher LOD and as result face count
+ // returns same value and total_submeshes[lod] is identical to high_lod one.
+ }
+ else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size())
+ { //number of meshes is different
+ message = "mesh_status_mesh_mismatch";
+ upload_status[lod] = 2;
+ }
+ else if (!verts[lod].empty())
+ {
+ S32 sum_verts_higher_lod = 0;
+ S32 sum_verts_this_lod = 0;
+ for (U32 i = 0; i < verts[lod].size(); ++i)
+ {
+ sum_verts_higher_lod += ((i < verts[lod + 1].size()) ? verts[lod + 1][i] : 0);
+ sum_verts_this_lod += verts[lod][i];
+ }
+
+ if ((sum_verts_higher_lod > 0) &&
+ (sum_verts_this_lod > sum_verts_higher_lod))
+ {
+ //too many vertices in this lod
+ message = "mesh_status_too_many_vertices";
+ upload_status[lod] = 1;
+ }
+ }
+ }
+
+ LLIconCtrl* icon = mFMP->getChild<LLIconCtrl>(lod_icon_name[lod]);
+ LLUIImagePtr img = LLUI::getUIImage(lod_status_image[upload_status[lod]]);
+ icon->setVisible(true);
+ icon->setImage(img);
+
+ if (upload_status[lod] >= 2)
+ {
+ mModelNoErrors = false;
+ }
+
+ if (lod == mPreviewLOD)
+ {
+ mFMP->childSetValue("lod_status_message_text", mFMP->getString(message));
+ icon = mFMP->getChild<LLIconCtrl>("lod_status_message_icon");
+ icon->setImage(img);
+ }
+
+ updateLodControls(lod);
+ }
+
+
+ //warn if hulls have more than 256 points in them
+ BOOL physExceededVertexLimit = FALSE;
+ for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
+ {
+ LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i];
+
+ if (mdl)
+ {
+ for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j)
+ {
+ if (mdl->mPhysics.mHull[j].size() > 256)
+ {
+ physExceededVertexLimit = TRUE;
+ LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL;
+ break;
+ }
+ }
+ }
+ }
+
+ if (physExceededVertexLimit)
+ {
+ has_physics_error |= PhysicsError::TOOMANYVERTSINHULL;
+ }
+
+ if (!(has_physics_error & PhysicsError::DEGENERATE)){ // only update this field (incluides clearing it) if it is not already in use.
+ mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit);
+ LLIconCtrl* physStatusIcon = mFMP->getChild<LLIconCtrl>("physics_status_message_icon");
+ physStatusIcon->setVisible(physExceededVertexLimit);
+ if (physExceededVertexLimit)
+ {
+ mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded"));
+ LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning");
+ physStatusIcon->setImage(img);
+ }
+ }
+
+ if (getLoadState() >= LLModelLoader::ERROR_PARSING)
+ {
+ mModelNoErrors = false;
+ LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL;
+ }
+
+ bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
+ bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+
+ if (uploadingSkin)
+ {
+ if (uploadingJointPositions && !isRigValidForJointPositionUpload())
+ {
+ mModelNoErrors = false;
+ LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL;
+ }
+ }
+
+ if (mModelNoErrors && mModelLoader)
+ {
+ if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
+ {
+ // Some textures are still loading, prevent upload until they are done
+ mModelNoErrors = false;
+ }
+ }
+
+ if (!mModelNoErrors || mHasDegenerate)
+ {
+ mFMP->childDisable("ok_btn");
+ mFMP->childDisable("calculate_btn");
+ }
+ else
+ {
+ mFMP->childEnable("ok_btn");
+ mFMP->childEnable("calculate_btn");
+ }
+
+ if (mModelNoErrors && mLodsWithParsingError.empty())
+ {
+ mFMP->childEnable("calculate_btn");
+ }
+ else
+ {
+ mFMP->childDisable("calculate_btn");
+ }
+
+ //add up physics triangles etc
+ S32 phys_tris = 0;
+ S32 phys_hulls = 0;
+ S32 phys_points = 0;
+
+ //get the triangle count for the whole scene
+ for (LLModelLoader::scene::iterator iter = mScene[LLModel::LOD_PHYSICS].begin(), endIter = mScene[LLModel::LOD_PHYSICS].end(); iter != endIter; ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
+ {
+ LLModel* model = instance->mModel;
+ if (model)
+ {
+ S32 cur_submeshes = model->getNumVolumeFaces();
+
+ LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull;
+
+ if (!decomp.empty())
+ {
+ phys_hulls += decomp.size();
+ for (U32 i = 0; i < decomp.size(); ++i)
+ {
+ phys_points += decomp[i].size();
+ }
+ }
+ else
+ { //choose physics shape OR decomposition, can't use both
+ for (S32 j = 0; j < cur_submeshes; ++j)
+ { //for each submesh (face), add triangles and vertices to current total
+ const LLVolumeFace& face = model->getVolumeFace(j);
+ phys_tris += face.mNumIndices / 3;
+ }
+ }
+ }
+ }
+ }
+
+ if (phys_tris > 0)
+ {
+ mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]", llformat("%d", phys_tris));
+ }
+ else
+ {
+ mFMP->childSetTextArg("physics_triangles", "[TRIANGLES]", mesh_status_na);
+ }
+
+ if (phys_hulls > 0)
+ {
+ mFMP->childSetTextArg("physics_hulls", "[HULLS]", llformat("%d", phys_hulls));
+ mFMP->childSetTextArg("physics_points", "[POINTS]", llformat("%d", phys_points));
+ }
+ else
+ {
+ mFMP->childSetTextArg("physics_hulls", "[HULLS]", mesh_status_na);
+ mFMP->childSetTextArg("physics_points", "[POINTS]", mesh_status_na);
+ }
+
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+ if (fmp)
+ {
+ if (phys_tris > 0 || phys_hulls > 0)
+ {
+ if (!fmp->isViewOptionEnabled("show_physics"))
+ {
+ fmp->enableViewOption("show_physics");
+ mViewOption["show_physics"] = true;
+ fmp->childSetValue("show_physics", true);
+ }
+ }
+ else
+ {
+ fmp->disableViewOption("show_physics");
+ mViewOption["show_physics"] = false;
+ fmp->childSetValue("show_physics", false);
+
+ }
+
+ //bool use_hull = fmp->childGetValue("physics_use_hull").asBoolean();
+
+ //fmp->childSetEnabled("physics_optimize", !use_hull);
+
+ bool enable = (phys_tris > 0 || phys_hulls > 0) && fmp->mCurRequest.empty();
+ //enable = enable && !use_hull && fmp->childGetValue("physics_optimize").asBoolean();
+
+ //enable/disable "analysis" UI
+ LLPanel* panel = fmp->getChild<LLPanel>("physics analysis");
+ LLView* child = panel->getFirstChild();
+ while (child)
+ {
+ child->setEnabled(enable);
+ child = panel->findNextSibling(child);
+ }
+
+ enable = phys_hulls > 0 && fmp->mCurRequest.empty();
+ //enable/disable "simplification" UI
+ panel = fmp->getChild<LLPanel>("physics simplification");
+ child = panel->getFirstChild();
+ while (child)
+ {
+ child->setEnabled(enable);
+ child = panel->findNextSibling(child);
+ }
+
+ if (fmp->mCurRequest.empty())
+ {
+ fmp->childSetVisible("Simplify", true);
+ fmp->childSetVisible("simplify_cancel", false);
+ fmp->childSetVisible("Decompose", true);
+ fmp->childSetVisible("decompose_cancel", false);
+
+ if (phys_hulls > 0)
+ {
+ fmp->childEnable("Simplify");
+ }
+
+ if (phys_tris || phys_hulls > 0)
+ {
+ fmp->childEnable("Decompose");
+ }
+ }
+ else
+ {
+ fmp->childEnable("simplify_cancel");
+ fmp->childEnable("decompose_cancel");
+ }
+ }
+
+
+ LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo");
+ S32 which_mode = 0;
+ S32 file_mode = 1;
+ if (iface)
+ {
+ which_mode = iface->getFirstSelectedIndex();
+ file_mode = iface->getItemCount() - 1;
+ }
+
+ if (which_mode == file_mode)
+ {
+ mFMP->childEnable("physics_file");
+ mFMP->childEnable("physics_browse");
+ }
+ else
+ {
+ mFMP->childDisable("physics_file");
+ mFMP->childDisable("physics_browse");
+ }
+
+ LLSpinCtrl* crease = mFMP->getChild<LLSpinCtrl>("crease_angle");
+
+ if (mRequestedCreaseAngle[mPreviewLOD] == -1.f)
+ {
+ mFMP->childSetColor("crease_label", LLColor4::grey);
+ crease->forceSetValue(75.f);
+ }
+ else
+ {
+ mFMP->childSetColor("crease_label", LLColor4::white);
+ crease->forceSetValue(mRequestedCreaseAngle[mPreviewLOD]);
+ }
+
+ mModelUpdatedSignal(true);
+
+}
+
+void LLModelPreview::updateLodControls(S32 lod)
+{
+ if (lod < LLModel::LOD_IMPOSTOR || lod > LLModel::LOD_HIGH)
+ {
+ std::ostringstream out;
+ out << "Invalid level of detail: " << lod;
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ assert(lod >= LLModel::LOD_IMPOSTOR && lod <= LLModel::LOD_HIGH);
+ return;
+ }
+
+ const char* lod_controls[] =
+ {
+ "lod_mode_",
+ "lod_triangle_limit_",
+ "lod_error_threshold_"
+ };
+ const U32 num_lod_controls = sizeof(lod_controls) / sizeof(char*);
+
+ const char* file_controls[] =
+ {
+ "lod_browse_",
+ "lod_file_",
+ };
+ const U32 num_file_controls = sizeof(file_controls) / sizeof(char*);
+
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+ if (!fmp) return;
+
+ LLComboBox* lod_combo = mFMP->findChild<LLComboBox>("lod_source_" + lod_name[lod]);
+ if (!lod_combo) return;
+
+ S32 lod_mode = lod_combo->getCurrentIndex();
+ if (lod_mode == LOD_FROM_FILE) // LoD from file
+ {
+ fmp->mLODMode[lod] = 0;
+ for (U32 i = 0; i < num_file_controls; ++i)
+ {
+ mFMP->childSetVisible(file_controls[i] + lod_name[lod], true);
+ }
+
+ for (U32 i = 0; i < num_lod_controls; ++i)
+ {
+ mFMP->childSetVisible(lod_controls[i] + lod_name[lod], false);
+ }
+ }
+ else if (lod_mode == USE_LOD_ABOVE) // use LoD above
+ {
+ fmp->mLODMode[lod] = 2;
+ for (U32 i = 0; i < num_file_controls; ++i)
+ {
+ mFMP->childSetVisible(file_controls[i] + lod_name[lod], false);
+ }
+
+ for (U32 i = 0; i < num_lod_controls; ++i)
+ {
+ mFMP->childSetVisible(lod_controls[i] + lod_name[lod], false);
+ }
+
+ if (lod < LLModel::LOD_HIGH)
+ {
+ mModel[lod] = mModel[lod + 1];
+ mScene[lod] = mScene[lod + 1];
+ mVertexBuffer[lod].clear();
+
+ // Also update lower LoD
+ if (lod > LLModel::LOD_IMPOSTOR)
+ {
+ updateLodControls(lod - 1);
+ }
+ }
+ }
+ else // auto generate, the default case for all LoDs except High
+ {
+ fmp->mLODMode[lod] = 1;
+
+ //don't actually regenerate lod when refreshing UI
+ mLODFrozen = true;
+
+ for (U32 i = 0; i < num_file_controls; ++i)
+ {
+ mFMP->getChildView(file_controls[i] + lod_name[lod])->setVisible(false);
+ }
+
+ for (U32 i = 0; i < num_lod_controls; ++i)
+ {
+ mFMP->getChildView(lod_controls[i] + lod_name[lod])->setVisible(true);
+ }
+
+
+ LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>("lod_error_threshold_" + lod_name[lod]);
+ LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod]);
+
+ limit->setMaxValue(mMaxTriangleLimit);
+ limit->forceSetValue(mRequestedTriangleCount[lod]);
+
+ threshold->forceSetValue(mRequestedErrorThreshold[lod]);
+
+ mFMP->getChild<LLComboBox>("lod_mode_" + lod_name[lod])->selectNthItem(mRequestedLoDMode[lod]);
+
+ if (mRequestedLoDMode[lod] == 0)
+ {
+ limit->setVisible(true);
+ threshold->setVisible(false);
+
+ limit->setMaxValue(mMaxTriangleLimit);
+ limit->setIncrement(mMaxTriangleLimit / 32);
+ }
+ else
+ {
+ limit->setVisible(false);
+ threshold->setVisible(true);
+ }
+
+ mLODFrozen = false;
+ }
+}
+
+void LLModelPreview::setPreviewTarget(F32 distance)
+{
+ mCameraDistance = distance;
+ mCameraZoom = 1.f;
+ mCameraPitch = 0.f;
+ mCameraYaw = 0.f;
+ mCameraOffset.clearVec();
+}
+
+void LLModelPreview::clearBuffers()
+{
+ for (U32 i = 0; i < 6; i++)
+ {
+ mVertexBuffer[i].clear();
+ }
+}
+
+void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
+{
+ U32 tri_count = 0;
+ U32 vertex_count = 0;
+ U32 mesh_count = 0;
+
+
+ LLModelLoader::model_list* model = NULL;
+
+ if (lod < 0 || lod > 4)
+ {
+ model = &mBaseModel;
+ lod = 5;
+ }
+ else
+ {
+ model = &(mModel[lod]);
+ }
+
+ if (!mVertexBuffer[lod].empty())
+ {
+ mVertexBuffer[lod].clear();
+ }
+
+ mVertexBuffer[lod].clear();
+
+ LLModelLoader::model_list::iterator base_iter = mBaseModel.begin();
+
+ for (LLModelLoader::model_list::iterator iter = model->begin(); iter != model->end(); ++iter)
+ {
+ LLModel* mdl = *iter;
+ if (!mdl)
+ {
+ continue;
+ }
+
+ LLModel* base_mdl = *base_iter;
+ base_iter++;
+
+ S32 num_faces = mdl->getNumVolumeFaces();
+ for (S32 i = 0; i < num_faces; ++i)
+ {
+ const LLVolumeFace &vf = mdl->getVolumeFace(i);
+ U32 num_vertices = vf.mNumVertices;
+ U32 num_indices = vf.mNumIndices;
+
+ if (!num_vertices || !num_indices)
+ {
+ continue;
+ }
+
+ LLVertexBuffer* vb = NULL;
+
+ bool skinned = include_skin_weights && !mdl->mSkinWeights.empty();
+
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ if (skinned)
+ {
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
+ }
+
+ vb = new LLVertexBuffer(mask, 0);
+
+ if (!vb->allocateBuffer(num_vertices, num_indices, TRUE))
+ {
+ // We are likely to crash due this failure, if this happens, find a way to gracefully stop preview
+ std::ostringstream out;
+ out << "Failed to allocate Vertex Buffer for model preview ";
+ out << num_vertices << " vertices and ";
+ out << num_indices << " indices";
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, true);
+ }
+
+ LLStrider<LLVector3> vertex_strider;
+ LLStrider<LLVector3> normal_strider;
+ LLStrider<LLVector2> tc_strider;
+ LLStrider<U16> index_strider;
+ LLStrider<LLVector4> weights_strider;
+
+ vb->getVertexStrider(vertex_strider);
+ vb->getIndexStrider(index_strider);
+
+ if (skinned)
+ {
+ vb->getWeight4Strider(weights_strider);
+ }
+
+ LLVector4a::memcpyNonAliased16((F32*)vertex_strider.get(), (F32*)vf.mPositions, num_vertices * 4 * sizeof(F32));
+
+ if (vf.mTexCoords)
+ {
+ vb->getTexCoord0Strider(tc_strider);
+ S32 tex_size = (num_vertices * 2 * sizeof(F32) + 0xF) & ~0xF;
+ LLVector4a::memcpyNonAliased16((F32*)tc_strider.get(), (F32*)vf.mTexCoords, tex_size);
+ }
+
+ if (vf.mNormals)
+ {
+ vb->getNormalStrider(normal_strider);
+ LLVector4a::memcpyNonAliased16((F32*)normal_strider.get(), (F32*)vf.mNormals, num_vertices * 4 * sizeof(F32));
+ }
+
+ if (skinned)
+ {
+ for (U32 i = 0; i < num_vertices; i++)
+ {
+ //find closest weight to vf.mVertices[i].mPosition
+ LLVector3 pos(vf.mPositions[i].getF32ptr());
+
+ const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos);
+ llassert(weight_list.size()>0 && weight_list.size() <= 4); // LLModel::loadModel() should guarantee this
+
+ LLVector4 w(0, 0, 0, 0);
+
+ for (U32 i = 0; i < weight_list.size(); ++i)
+ {
+ F32 wght = llclamp(weight_list[i].mWeight, 0.001f, 0.999f);
+ F32 joint = (F32)weight_list[i].mJointIdx;
+ w.mV[i] = joint + wght;
+ llassert(w.mV[i] - (S32)w.mV[i]>0.0f); // because weights are non-zero, and range of wt values
+ //should not cause floating point precision issues.
+ }
+
+ *(weights_strider++) = w;
+ }
+ }
+
+ // build indices
+ for (U32 i = 0; i < num_indices; i++)
+ {
+ *(index_strider++) = vf.mIndices[i];
+ }
+
+ mVertexBuffer[lod][mdl].push_back(vb);
+
+ vertex_count += num_vertices;
+ tri_count += num_indices / 3;
+ ++mesh_count;
+
+ }
+ }
+}
+
+void LLModelPreview::update()
+{
+ if (mGenLOD)
+ {
+ bool subscribe_for_generation = mLodsQuery.empty();
+ mGenLOD = false;
+ mDirty = true;
+ mLodsQuery.clear();
+
+ for (S32 lod = LLModel::LOD_HIGH; lod >= 0; --lod)
+ {
+ // adding all lods into query for generation
+ mLodsQuery.push_back(lod);
+ }
+
+ if (subscribe_for_generation)
+ {
+ doOnIdleRepeating(lodQueryCallback);
+ }
+ }
+
+ if (mDirty && mLodsQuery.empty())
+ {
+ mDirty = false;
+ mResourceCost = calcResourceCost();
+ refresh();
+ updateStatusMessages();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// createPreviewAvatar
+//-----------------------------------------------------------------------------
+void LLModelPreview::createPreviewAvatar(void)
+{
+ mPreviewAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR);
+ if (mPreviewAvatar)
+ {
+ mPreviewAvatar->createDrawable(&gPipeline);
+ mPreviewAvatar->mSpecialRenderMode = 1;
+ mPreviewAvatar->startMotion(ANIM_AGENT_STAND);
+ mPreviewAvatar->hideSkirt();
+ }
+ else
+ {
+ LL_INFOS() << "Failed to create preview avatar for upload model window" << LL_ENDL;
+ }
+}
+
+//static
+U32 LLModelPreview::countRootModels(LLModelLoader::model_list models)
+{
+ U32 root_models = 0;
+ model_list::iterator model_iter = models.begin();
+ while (model_iter != models.end())
+ {
+ LLModel* mdl = *model_iter;
+ if (mdl && mdl->mSubmodelID == 0)
+ {
+ root_models++;
+ }
+ model_iter++;
+ }
+ return root_models;
+}
+
+void LLModelPreview::loadedCallback(
+ LLModelLoader::scene& scene,
+ LLModelLoader::model_list& model_list,
+ S32 lod,
+ void* opaque)
+{
+ LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+ if (pPreview && !LLModelPreview::sIgnoreLoadedCallback)
+ {
+ // Load loader's warnings into floater's log tab
+ const LLSD out = pPreview->mModelLoader->logOut();
+ LLSD::array_const_iterator iter_out = out.beginArray();
+ LLSD::array_const_iterator end_out = out.endArray();
+ for (; iter_out != end_out; ++iter_out)
+ {
+ if (iter_out->has("Message"))
+ {
+ LLFloaterModelPreview::addStringToLog(iter_out->get("Message"), *iter_out, true, pPreview->mModelLoader->mLod);
+ }
+ }
+ pPreview->mModelLoader->clearLog();
+ pPreview->loadModelCallback(lod); // removes mModelLoader in some cases
+ if (pPreview->mLookUpLodFiles && (lod != LLModel::LOD_HIGH))
+ {
+ pPreview->lookupLODModelFiles(lod);
+ }
+ }
+
+}
+
+void LLModelPreview::lookupLODModelFiles(S32 lod)
+{
+ if (lod == LLModel::LOD_PHYSICS)
+ {
+ mLookUpLodFiles = false;
+ return;
+ }
+ S32 next_lod = (lod - 1 >= LLModel::LOD_IMPOSTOR) ? lod - 1 : LLModel::LOD_PHYSICS;
+
+ std::string lod_filename = mLODFile[LLModel::LOD_HIGH];
+ std::string ext = ".dae";
+ std::string::size_type i = lod_filename.rfind(ext);
+ if (i != std::string::npos)
+ {
+ lod_filename.replace(i, lod_filename.size() - ext.size(), getLodSuffix(next_lod) + ext);
+ }
+ if (gDirUtilp->fileExists(lod_filename))
+ {
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+ if (fmp)
+ {
+ fmp->setCtrlLoadFromFile(next_lod);
+ }
+ loadModel(lod_filename, next_lod);
+ }
+ else
+ {
+ lookupLODModelFiles(next_lod);
+ }
+}
+
+void LLModelPreview::stateChangedCallback(U32 state, void* opaque)
+{
+ LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+ if (pPreview)
+ {
+ pPreview->setLoadState(state);
+ }
+}
+
+LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque)
+{
+ LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque);
+ if (pPreview)
+ {
+ return pPreview->getPreviewAvatar()->getJoint(str);
+ }
+ return NULL;
+}
+
+U32 LLModelPreview::loadTextures(LLImportMaterial& material, void* opaque)
+{
+ (void)opaque;
+
+ if (material.mDiffuseMapFilename.size())
+ {
+ material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >;
+ LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData));
+
+ tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + LLURI::unescape(material.mDiffuseMapFilename), FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW);
+ tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE);
+ tex->forceToSaveRawImage(0, F32_MAX);
+ material.setDiffuseMap(tex->getID()); // record tex ID
+ return 1;
+ }
+
+ material.mOpaqueData = NULL;
+ return 0;
+}
+
+void LLModelPreview::addEmptyFace(LLModel* pTarget)
+{
+ U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
+
+ buff->allocateBuffer(1, 3, true);
+ memset((U8*)buff->getMappedData(), 0, buff->getSize());
+ memset((U8*)buff->getIndicesPointer(), 0, buff->getIndicesSize());
+
+ buff->validateRange(0, buff->getNumVerts() - 1, buff->getNumIndices(), 0);
+
+ LLStrider<LLVector3> pos;
+ LLStrider<LLVector3> norm;
+ LLStrider<LLVector2> tc;
+ LLStrider<U16> index;
+
+ buff->getVertexStrider(pos);
+
+ if (type_mask & LLVertexBuffer::MAP_NORMAL)
+ {
+ buff->getNormalStrider(norm);
+ }
+ if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
+ {
+ buff->getTexCoord0Strider(tc);
+ }
+
+ buff->getIndexStrider(index);
+
+ //resize face array
+ int faceCnt = pTarget->getNumVolumeFaces();
+ pTarget->setNumVolumeFaces(faceCnt + 1);
+ pTarget->setVolumeFaceData(faceCnt + 1, pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices());
+
+}
+
+//-----------------------------------------------------------------------------
+// render()
+//-----------------------------------------------------------------------------
+// Todo: we shouldn't be setting all those UI elements on render.
+// Note: Render happens each frame with skinned avatars
+BOOL LLModelPreview::render()
+{
+ assert_main_thread();
+
+ LLMutexLock lock(this);
+ mNeedsUpdate = FALSE;
+
+ bool use_shaders = LLGLSLShader::sNoFixedFunction;
+
+ bool edges = mViewOption["show_edges"];
+ bool joint_overrides = mViewOption["show_joint_overrides"];
+ bool joint_positions = mViewOption["show_joint_positions"];
+ bool skin_weight = mViewOption["show_skin_weight"];
+ bool textures = mViewOption["show_textures"];
+ bool physics = mViewOption["show_physics"];
+
+ S32 width = getWidth();
+ S32 height = getHeight();
+
+ LLGLSUIDefault def; // GL_BLEND, GL_ALPHA_TEST, GL_CULL_FACE, depth test
+ LLGLDisable no_blend(GL_BLEND);
+ LLGLEnable cull(GL_CULL_FACE);
+ LLGLDepthTest depth(GL_FALSE); // SL-12781 disable z-buffer to render background color
+ LLGLDisable fog(GL_FOG);
+
+ {
+ if (use_shaders)
+ {
+ gUIProgram.bind();
+ }
+ //clear background to grey
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.ortho(0.0f, width, 0.0f, height, -1.0f, 1.0f);
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.color4fv(PREVIEW_CANVAS_COL.mV);
+ gl_rect_2d_simple(width, height);
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ if (use_shaders)
+ {
+ gUIProgram.unbind();
+ }
+ }
+
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+
+ bool has_skin_weights = false;
+ bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();
+ bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean();
+
+ if (upload_joints != mLastJointUpdate)
+ {
+ mLastJointUpdate = upload_joints;
+ if (fmp)
+ {
+ fmp->clearAvatarTab();
+ }
+ }
+
+ for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
+ {
+ LLModelInstance& instance = *model_iter;
+ LLModel* model = instance.mModel;
+ model->mPelvisOffset = mPelvisZOffset;
+ if (!model->mSkinWeights.empty())
+ {
+ has_skin_weights = true;
+ }
+ }
+ }
+
+ if (has_skin_weights && lodsReady())
+ { //model has skin weights, enable view options for skin weights and joint positions
+ U32 flags = getLegacyRigFlags();
+ if (fmp)
+ {
+ if (flags == LEGACY_RIG_OK)
+ {
+ if (mFirstSkinUpdate)
+ {
+ // auto enable weight upload if weights are present
+ // (note: all these UI updates need to be somewhere that is not render)
+ mViewOption["show_skin_weight"] = true;
+ skin_weight = true;
+ fmp->childSetValue("upload_skin", true);
+ mFirstSkinUpdate = false;
+ }
+
+ fmp->enableViewOption("show_skin_weight");
+ fmp->setViewOptionEnabled("show_joint_overrides", skin_weight);
+ fmp->setViewOptionEnabled("show_joint_positions", skin_weight);
+ mFMP->childEnable("upload_skin");
+ mFMP->childSetValue("show_skin_weight", skin_weight);
+
+ }
+ else if ((flags & LEGACY_RIG_FLAG_TOO_MANY_JOINTS) > 0)
+ {
+ mFMP->childSetVisible("skin_too_many_joints", true);
+ }
+ else if ((flags & LEGACY_RIG_FLAG_UNKNOWN_JOINT) > 0)
+ {
+ mFMP->childSetVisible("skin_unknown_joint", true);
+ }
+ }
+ }
+ else
+ {
+ mFMP->childDisable("upload_skin");
+ if (fmp)
+ {
+ mViewOption["show_skin_weight"] = false;
+ fmp->disableViewOption("show_skin_weight");
+ fmp->disableViewOption("show_joint_overrides");
+ fmp->disableViewOption("show_joint_positions");
+
+ skin_weight = false;
+ mFMP->childSetValue("show_skin_weight", false);
+ fmp->setViewOptionEnabled("show_skin_weight", skin_weight);
+ }
+ }
+
+ if (upload_skin && !has_skin_weights)
+ { //can't upload skin weights if model has no skin weights
+ mFMP->childSetValue("upload_skin", false);
+ upload_skin = false;
+ }
+
+ if (!upload_skin && upload_joints)
+ { //can't upload joints if not uploading skin weights
+ mFMP->childSetValue("upload_joints", false);
+ upload_joints = false;
+ }
+
+ if (fmp)
+ {
+ if (upload_skin)
+ {
+ // will populate list of joints
+ fmp->updateAvatarTab(upload_joints);
+ }
+ else
+ {
+ fmp->clearAvatarTab();
+ }
+ }
+
+ if (upload_skin && upload_joints)
+ {
+ mFMP->childEnable("lock_scale_if_joint_position");
+ }
+ else
+ {
+ mFMP->childDisable("lock_scale_if_joint_position");
+ mFMP->childSetValue("lock_scale_if_joint_position", false);
+ }
+
+ //Only enable joint offsets if it passed the earlier critiquing
+ if (isRigValidForJointPositionUpload())
+ {
+ mFMP->childSetEnabled("upload_joints", upload_skin);
+ }
+
+ F32 explode = mFMP->childGetValue("physics_explode").asReal();
+
+ LLGLDepthTest gls_depth(GL_TRUE); // SL-12781 re-enable z-buffer for 3D model preview
+
+ LLRect preview_rect;
+
+ preview_rect = mFMP->getChildView("preview_panel")->getRect();
+
+ F32 aspect = (F32)preview_rect.getWidth() / preview_rect.getHeight();
+
+ LLViewerCamera::getInstance()->setAspect(aspect);
+
+ LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
+
+ LLVector3 offset = mCameraOffset;
+ LLVector3 target_pos = mPreviewTarget + offset;
+
+ F32 z_near = 0.001f;
+ F32 z_far = mCameraDistance*10.0f + mPreviewScale.magVec() + mCameraOffset.magVec();
+
+ if (skin_weight)
+ {
+ target_pos = getPreviewAvatar()->getPositionAgent() + offset;
+ z_near = 0.01f;
+ z_far = 1024.f;
+
+ //render avatar previews every frame
+ refresh();
+ }
+
+ if (use_shaders)
+ {
+ gObjectPreviewProgram.bind();
+ }
+
+ gGL.loadIdentity();
+ gPipeline.enableLightsPreview();
+
+ LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) *
+ LLQuaternion(mCameraYaw, LLVector3::z_axis);
+
+ LLQuaternion av_rot = camera_rot;
+ F32 camera_distance = skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance;
+ LLViewerCamera::getInstance()->setOriginAndLookAt(
+ target_pos + ((LLVector3(camera_distance, 0.f, 0.f) + offset) * av_rot), // camera
+ LLVector3::z_axis, // up
+ target_pos); // point of interest
+
+
+ z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f);
+
+ LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, width, height, FALSE, z_near, z_far);
+
+ stop_glerror();
+
+ gGL.pushMatrix();
+ gGL.color4fv(PREVIEW_EDGE_COL.mV);
+
+ const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
+
+ LLGLEnable normalize(GL_NORMALIZE);
+
+ if (!mBaseModel.empty() && mVertexBuffer[5].empty())
+ {
+ genBuffers(-1, skin_weight);
+ //genBuffers(3);
+ //genLODs();
+ }
+
+ if (!mModel[mPreviewLOD].empty())
+ {
+ mFMP->childEnable("reset_btn");
+
+ bool regen = mVertexBuffer[mPreviewLOD].empty();
+ if (!regen)
+ {
+ const std::vector<LLPointer<LLVertexBuffer> >& vb_vec = mVertexBuffer[mPreviewLOD].begin()->second;
+ if (!vb_vec.empty())
+ {
+ const LLVertexBuffer* buff = vb_vec[0];
+ regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight;
+ }
+ else
+ {
+ LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL;
+ regen = TRUE;
+ }
+ }
+
+ if (regen)
+ {
+ genBuffers(mPreviewLOD, skin_weight);
+ }
+
+ if (!skin_weight)
+ {
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+
+ LLModel* model = instance.mLOD[mPreviewLOD];
+
+ if (!model)
+ {
+ continue;
+ }
+
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
+
+ gGL.multMatrix((GLfloat*)mat.mMatrix);
+
+
+ U32 num_models = mVertexBuffer[mPreviewLOD][model].size();
+ for (U32 i = 0; i < num_models; ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+
+ if (textures)
+ {
+ int materialCnt = instance.mModel->mMaterialList.size();
+ if (i < materialCnt)
+ {
+ const std::string& binding = instance.mModel->mMaterialList[i];
+ const LLImportMaterial& material = instance.mMaterial[binding];
+
+ gGL.diffuseColor4fv(material.mDiffuseColor.mV);
+
+ // Find the tex for this material, bind it, and add it to our set
+ //
+ LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+ if (tex)
+ {
+ mTextureSet.insert(tex);
+ }
+ }
+ }
+ else
+ {
+ gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV);
+ }
+
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
+ if (edges)
+ {
+ glLineWidth(PREVIEW_EDGE_WIDTH);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
+ }
+ gGL.popMatrix();
+ }
+
+ if (physics)
+ {
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ for (U32 pass = 0; pass < 2; pass++)
+ {
+ if (pass == 0)
+ { //depth only pass
+ gGL.setColorMask(false, false);
+ }
+ else
+ {
+ gGL.setColorMask(true, true);
+ }
+
+ //enable alpha blending on second pass but not first pass
+ LLGLState blend(GL_BLEND, pass);
+
+ gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
+
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+
+ if (!model)
+ {
+ continue;
+ }
+
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
+
+ gGL.multMatrix((GLfloat*)mat.mMatrix);
+
+
+ bool render_mesh = true;
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
+ {
+ LLMutexLock(decomp->mMutex);
+
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (!physics.mHull.empty())
+ {
+ render_mesh = false;
+
+ if (physics.mMesh.empty())
+ { //build vertex buffer for physics mesh
+ gMeshRepo.buildPhysicsMesh(physics);
+ }
+
+ if (!physics.mMesh.empty())
+ { //render hull instead of mesh
+ for (U32 i = 0; i < physics.mMesh.size(); ++i)
+ {
+ if (explode > 0.f)
+ {
+ gGL.pushMatrix();
+
+ LLVector3 offset = model->mHullCenter[i] - model->mCenterOfHullCenters;
+ offset *= explode;
+
+ gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+ }
+
+ static std::vector<LLColor4U> hull_colors;
+
+ if (i + 1 >= hull_colors.size())
+ {
+ hull_colors.push_back(LLColor4U(rand() % 128 + 127, rand() % 128 + 127, rand() % 128 + 127, 128));
+ }
+
+ gGL.diffuseColor4ubv(hull_colors[i].mV);
+ LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+
+ if (explode > 0.f)
+ {
+ gGL.popMatrix();
+ }
+ }
+ }
+ }
+ }
+
+ if (render_mesh)
+ {
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
+
+ U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
+ if (pass > 0){
+ for (U32 i = 0; i < num_models; ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i];
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.diffuseColor4fv(PREVIEW_PSYH_FILL_COL.mV);
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
+
+ gGL.diffuseColor4fv(PREVIEW_PSYH_EDGE_COL.mV);
+ glLineWidth(PREVIEW_PSYH_EDGE_WIDTH);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
+ }
+ }
+ gGL.popMatrix();
+ }
+
+ // only do this if mDegenerate was set in the preceding mesh checks [Check this if the ordering ever breaks]
+ if (mHasDegenerate)
+ {
+ glLineWidth(PREVIEW_DEG_EDGE_WIDTH);
+ glPointSize(PREVIEW_DEG_POINT_SIZE);
+ gPipeline.enableLightsFullbright();
+ //show degenerate triangles
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ LLGLDisable cull(GL_CULL_FACE);
+ gGL.diffuseColor4f(1.f, 0.f, 0.f, 1.f);
+ const LLVector4a scale(0.5f);
+
+ for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
+ {
+ LLModelInstance& instance = *iter;
+
+ LLModel* model = instance.mLOD[LLModel::LOD_PHYSICS];
+
+ if (!model)
+ {
+ continue;
+ }
+
+ gGL.pushMatrix();
+ LLMatrix4 mat = instance.mTransform;
+
+ gGL.multMatrix((GLfloat*)mat.mMatrix);
+
+
+ LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread;
+ if (decomp)
+ {
+ LLMutexLock(decomp->mMutex);
+
+ LLModel::Decomposition& physics = model->mPhysics;
+
+ if (physics.mHull.empty())
+ {
+ if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
+ {
+ genBuffers(LLModel::LOD_PHYSICS, false);
+ }
+
+ U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
+ for (U32 v = 0; v < num_models; ++v)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][v];
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+
+ LLStrider<LLVector3> pos_strider;
+ buffer->getVertexStrider(pos_strider, 0);
+ LLVector4a* pos = (LLVector4a*)pos_strider.get();
+
+ LLStrider<U16> idx;
+ buffer->getIndexStrider(idx, 0);
+
+ for (U32 i = 0; i < buffer->getNumIndices(); i += 3)
+ {
+ LLVector4a v1; v1.setMul(pos[*idx++], scale);
+ LLVector4a v2; v2.setMul(pos[*idx++], scale);
+ LLVector4a v3; v3.setMul(pos[*idx++], scale);
+
+ if (ll_is_degenerate(v1, v2, v3))
+ {
+ buffer->draw(LLRender::LINE_LOOP, 3, i);
+ buffer->draw(LLRender::POINTS, 3, i);
+ }
+ }
+ }
+ }
+ }
+
+ gGL.popMatrix();
+ }
+ glLineWidth(1.f);
+ glPointSize(1.f);
+ gPipeline.enableLightsPreview();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+ }
+ }
+ }
+ else
+ {
+ target_pos = getPreviewAvatar()->getPositionAgent();
+ getPreviewAvatar()->clearAttachmentOverrides(); // removes pelvis fixup
+ LLUUID fake_mesh_id;
+ fake_mesh_id.generate();
+ getPreviewAvatar()->addPelvisFixup(mPelvisZOffset, fake_mesh_id);
+ bool pelvis_recalc = false;
+
+ LLViewerCamera::getInstance()->setOriginAndLookAt(
+ target_pos + ((LLVector3(camera_distance, 0.f, 0.f) + offset) * av_rot), // camera
+ LLVector3::z_axis, // up
+ target_pos); // point of interest
+
+ for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
+ {
+ LLModelInstance& instance = *model_iter;
+ LLModel* model = instance.mModel;
+
+ if (!model->mSkinWeights.empty())
+ {
+ const LLMeshSkinInfo *skin = &model->mSkinInfo;
+ LLSkinningUtil::initJointNums(&model->mSkinInfo, getPreviewAvatar());// inits skin->mJointNums if nessesary
+ U32 joint_count = LLSkinningUtil::getMeshJointCount(skin);
+ U32 bind_count = skin->mAlternateBindMatrix.size();
+
+ if (joint_overrides
+ && bind_count > 0
+ && joint_count == bind_count)
+ {
+ // mesh_id is used to determine which mesh gets to
+ // set the joint offset, in the event of a conflict. Since
+ // we don't know the mesh id yet, we can't guarantee that
+ // joint offsets will be applied with the same priority as
+ // in the uploaded model. If the file contains multiple
+ // meshes with conflicting joint offsets, preview may be
+ // incorrect.
+ LLUUID fake_mesh_id;
+ fake_mesh_id.generate();
+ for (U32 j = 0; j < joint_count; ++j)
+ {
+ LLJoint *joint = getPreviewAvatar()->getJoint(skin->mJointNums[j]);
+ if (joint)
+ {
+ const LLVector3& jointPos = skin->mAlternateBindMatrix[j].getTranslation();
+ if (joint->aboveJointPosThreshold(jointPos))
+ {
+ bool override_changed;
+ joint->addAttachmentPosOverride(jointPos, fake_mesh_id, "model", override_changed);
+
+ if (override_changed)
+ {
+ //If joint is a pelvis then handle old/new pelvis to foot values
+ if (joint->getName() == "mPelvis")// or skin->mJointNames[j]
+ {
+ pelvis_recalc = true;
+ }
+ }
+ if (skin->mLockScaleIfJointPosition)
+ {
+ // Note that unlike positions, there's no threshold check here,
+ // just a lock at the default value.
+ joint->addAttachmentScaleOverride(joint->getDefaultScale(), fake_mesh_id, "model");
+ }
+ }
+ }
+ }
+ }
+
+ for (U32 i = 0, e = mVertexBuffer[mPreviewLOD][model].size(); i < e; ++i)
+ {
+ LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
+
+ const LLVolumeFace& face = model->getVolumeFace(i);
+
+ LLStrider<LLVector3> position;
+ buffer->getVertexStrider(position);
+
+ LLStrider<LLVector4> weight;
+ buffer->getWeight4Strider(weight);
+
+ //quick 'n dirty software vertex skinning
+
+ //build matrix palette
+
+ LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
+ LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, joint_count,
+ skin, getPreviewAvatar());
+
+ LLMatrix4a bind_shape_matrix;
+ bind_shape_matrix.loadu(skin->mBindShapeMatrix);
+ U32 max_joints = LLSkinningUtil::getMaxJointCount();
+ for (U32 j = 0; j < buffer->getNumVerts(); ++j)
+ {
+ LLMatrix4a final_mat;
+ F32 *wptr = weight[j].mV;
+ LLSkinningUtil::getPerVertexSkinMatrix(wptr, mat, true, final_mat, max_joints);
+
+ //VECTORIZE THIS
+ LLVector4a& v = face.mPositions[j];
+
+ LLVector4a t;
+ LLVector4a dst;
+ bind_shape_matrix.affineTransform(v, t);
+ final_mat.affineTransform(t, dst);
+
+ position[j][0] = dst[0];
+ position[j][1] = dst[1];
+ position[j][2] = dst[2];
+ }
+
+ llassert(model->mMaterialList.size() > i);
+ const std::string& binding = instance.mModel->mMaterialList[i];
+ const LLImportMaterial& material = instance.mMaterial[binding];
+
+ buffer->setBuffer(type_mask & buffer->getTypeMask());
+ gGL.diffuseColor4fv(material.mDiffuseColor.mV);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // Find the tex for this material, bind it, and add it to our set
+ //
+ LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+ if (tex)
+ {
+ mTextureSet.insert(tex);
+ }
+
+ buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
+
+ if (edges)
+ {
+ gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
+ glLineWidth(PREVIEW_EDGE_WIDTH);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glLineWidth(1.f);
+ }
+ }
+ }
+ }
+ }
+
+ if (joint_positions)
+ {
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ if (shader)
+ {
+ gDebugProgram.bind();
+ }
+ getPreviewAvatar()->renderCollisionVolumes();
+ if (fmp->mTabContainer->getCurrentPanelIndex() == fmp->mAvatarTabIndex)
+ {
+ getPreviewAvatar()->renderBones(fmp->mSelectedJointName);
+ }
+ else
+ {
+ getPreviewAvatar()->renderBones();
+ }
+ if (shader)
+ {
+ shader->bind();
+ }
+ }
+
+ if (pelvis_recalc)
+ {
+ // size/scale recalculation
+ getPreviewAvatar()->postPelvisSetRecalc();
+ }
+ }
+ }
+
+ if (use_shaders)
+ {
+ gObjectPreviewProgram.unbind();
+ }
+
+ gGL.popMatrix();
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// refresh()
+//-----------------------------------------------------------------------------
+void LLModelPreview::refresh()
+{
+ mNeedsUpdate = TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// rotate()
+//-----------------------------------------------------------------------------
+void LLModelPreview::rotate(F32 yaw_radians, F32 pitch_radians)
+{
+ mCameraYaw = mCameraYaw + yaw_radians;
+
+ mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f);
+}
+
+//-----------------------------------------------------------------------------
+// zoom()
+//-----------------------------------------------------------------------------
+void LLModelPreview::zoom(F32 zoom_amt)
+{
+ F32 new_zoom = mCameraZoom + zoom_amt;
+ // TODO: stop clamping in render
+ mCameraZoom = llclamp(new_zoom, 1.f, PREVIEW_ZOOM_LIMIT);
+}
+
+void LLModelPreview::pan(F32 right, F32 up)
+{
+ bool skin_weight = mViewOption["show_skin_weight"];
+ F32 camera_distance = skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance;
+ mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * camera_distance / mCameraZoom, -1.f, 1.f);
+ mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * camera_distance / mCameraZoom, -1.f, 1.f);
+}
+
+void LLModelPreview::setPreviewLOD(S32 lod)
+{
+ lod = llclamp(lod, 0, (S32)LLModel::LOD_HIGH);
+
+ if (lod != mPreviewLOD)
+ {
+ mPreviewLOD = lod;
+
+ LLComboBox* combo_box = mFMP->getChild<LLComboBox>("preview_lod_combo");
+ combo_box->setCurrentByIndex((NUM_LOD - 1) - mPreviewLOD); // combo box list of lods is in reverse order
+ mFMP->childSetValue("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]);
+
+ LLColor4 highlight_color = LLUIColorTable::instance().getColor("MeshImportTableHighlightColor");
+ LLColor4 normal_color = LLUIColorTable::instance().getColor("MeshImportTableNormalColor");
+
+ for (S32 i = 0; i <= LLModel::LOD_HIGH; ++i)
+ {
+ const LLColor4& color = (i == lod) ? highlight_color : normal_color;
+
+ mFMP->childSetColor(lod_status_name[i], color);
+ mFMP->childSetColor(lod_label_name[i], color);
+ mFMP->childSetColor(lod_triangles_name[i], color);
+ mFMP->childSetColor(lod_vertices_name[i], color);
+ }
+
+ LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)mFMP;
+ if (fmp)
+ {
+ // make preview repopulate tab
+ fmp->clearAvatarTab();
+ }
+ }
+ refresh();
+ updateStatusMessages();
+}
+
+//static
+void LLModelPreview::textureLoadedCallback(
+ BOOL success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* src_aux,
+ S32 discard_level,
+ BOOL final,
+ void* userdata)
+{
+ LLModelPreview* preview = (LLModelPreview*)userdata;
+ preview->refresh();
+
+ if (final && preview->mModelLoader)
+ {
+ if (preview->mModelLoader->mNumOfFetchingTextures > 0)
+ {
+ preview->mModelLoader->mNumOfFetchingTextures--;
+ }
+ }
+}
+
+// static
+bool LLModelPreview::lodQueryCallback()
+{
+ // not the best solution, but model preview belongs to floater
+ // so it is an easy way to check that preview still exists.
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+ if (fmp && fmp->mModelPreview)
+ {
+ LLModelPreview* preview = fmp->mModelPreview;
+ if (preview->mLodsQuery.size() > 0)
+ {
+ S32 lod = preview->mLodsQuery.back();
+ preview->mLodsQuery.pop_back();
+ preview->genLODs(lod);
+
+ if (preview->mLookUpLodFiles && (lod == LLModel::LOD_HIGH))
+ {
+ preview->lookupLODModelFiles(LLModel::LOD_HIGH);
+ }
+
+ // return false to continue cycle
+ return false;
+ }
+ }
+ // nothing to process
+ return true;
+}
+
+void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
+{
+ if (!mLODFrozen)
+ {
+ genLODs(lod, 3, enforce_tri_limit);
+ refresh();
+ }
+}
+
diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h
new file mode 100644
index 0000000000..3664a27a72
--- /dev/null
+++ b/indra/newview/llmodelpreview.h
@@ -0,0 +1,313 @@
+/**
+ * @file llmodelpreview.h
+ * @brief LLModelPreview class definition, class
+ * responsible for model preview inside LLFloaterModelPreview
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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_LLMODELPREVIEW_H
+#define LL_LLMODELPREVIEW_H
+
+#include "lldynamictexture.h"
+#include "llfloatermodelpreview.h"
+#include "llmeshrepository.h"
+#include "llmodelloader.h" //NUM_LOD
+#include "llmodel.h"
+
+class LLJoint;
+class LLVOAvatar;
+class LLTextBox;
+class LLVertexBuffer;
+class DAE;
+class daeElement;
+class domProfile_COMMON;
+class domInstance_geometry;
+class domNode;
+class domTranslate;
+class domController;
+class domSkin;
+class domMesh;
+
+// const strings needed by classes that use model preivew
+static const std::string lod_name[NUM_LOD + 1] =
+{
+ "lowest",
+ "low",
+ "medium",
+ "high",
+ "I went off the end of the lod_name array. Me so smart."
+};
+
+static const std::string lod_triangles_name[NUM_LOD + 1] =
+{
+ "lowest_triangles",
+ "low_triangles",
+ "medium_triangles",
+ "high_triangles",
+ "I went off the end of the lod_triangles_name array. Me so smart."
+};
+
+static const std::string lod_vertices_name[NUM_LOD + 1] =
+{
+ "lowest_vertices",
+ "low_vertices",
+ "medium_vertices",
+ "high_vertices",
+ "I went off the end of the lod_vertices_name array. Me so smart."
+};
+
+static const std::string lod_status_name[NUM_LOD + 1] =
+{
+ "lowest_status",
+ "low_status",
+ "medium_status",
+ "high_status",
+ "I went off the end of the lod_status_name array. Me so smart."
+};
+
+static const std::string lod_icon_name[NUM_LOD + 1] =
+{
+ "status_icon_lowest",
+ "status_icon_low",
+ "status_icon_medium",
+ "status_icon_high",
+ "I went off the end of the lod_status_name array. Me so smart."
+};
+
+static const std::string lod_status_image[NUM_LOD + 1] =
+{
+ "ModelImport_Status_Good",
+ "ModelImport_Status_Warning",
+ "ModelImport_Status_Error",
+ "I went off the end of the lod_status_image array. Me so smart."
+};
+
+static const std::string lod_label_name[NUM_LOD + 1] =
+{
+ "lowest_label",
+ "low_label",
+ "medium_label",
+ "high_label",
+ "I went off the end of the lod_label_name array. Me so smart."
+};
+
+class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
+{
+ LOG_CLASS(LLModelPreview);
+
+ typedef boost::signals2::signal<void(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)> details_signal_t;
+ typedef boost::signals2::signal<void(void)> model_loaded_signal_t;
+ typedef boost::signals2::signal<void(bool)> model_updated_signal_t;
+
+public:
+
+ typedef enum
+ {
+ LOD_FROM_FILE = 0,
+ GENERATE,
+ USE_LOD_ABOVE,
+ } eLoDMode;
+
+public:
+ // Todo: model preview shouldn't need floater dependency, it
+ // should just expose data to floater, not control flaoter like it does
+ LLModelPreview(S32 width, S32 height, LLFloater* fmp);
+ virtual ~LLModelPreview();
+
+ void resetPreviewTarget();
+ void setPreviewTarget(F32 distance);
+ void setTexture(U32 name) { mTextureName = name; }
+
+ void setPhysicsFromLOD(S32 lod);
+ BOOL render();
+ void update();
+ void genBuffers(S32 lod, bool skinned);
+ void clearBuffers();
+ void refresh();
+ void rotate(F32 yaw_radians, F32 pitch_radians);
+ void zoom(F32 zoom_amt);
+ void pan(F32 right, F32 up);
+ virtual BOOL needsRender() { return mNeedsUpdate; }
+ void setPreviewLOD(S32 lod);
+ void clearModel(S32 lod);
+ void getJointAliases(JointMap& joint_map);
+ void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
+ void loadModelCallback(S32 lod);
+ bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
+ void queryLODs() { mGenLOD = true; };
+ void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
+ void generateNormals();
+ void restoreNormals();
+ U32 calcResourceCost();
+ void rebuildUploadData();
+ void saveUploadData(bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position);
+ void saveUploadData(const std::string& filename, bool save_skinweights, bool save_joint_positions, bool lock_scale_if_joint_position);
+ void clearIncompatible(S32 lod);
+ void updateStatusMessages();
+ void updateLodControls(S32 lod);
+ void clearGLODGroup();
+ void onLODParamCommit(S32 lod, bool enforce_tri_limit);
+ void addEmptyFace(LLModel* pTarget);
+
+ const bool getModelPivot(void) const { return mHasPivot; }
+ void setHasPivot(bool val) { mHasPivot = val; }
+ void setModelPivot(const LLVector3& pivot) { mModelPivot = pivot; }
+
+ //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
+ //Accessors for joint position upload friendly rigs
+ const bool isRigValidForJointPositionUpload(void) const { return mRigValidJointUpload; }
+ void setRigValidForJointPositionUpload(bool rigValid) { mRigValidJointUpload = rigValid; }
+
+ //Accessors for the legacy rigs
+ const bool isLegacyRigValid(void) const { return mLegacyRigFlags == 0; }
+ U32 getLegacyRigFlags() const { return mLegacyRigFlags; }
+ void setLegacyRigFlags(U32 rigFlags) { mLegacyRigFlags = rigFlags; }
+
+ static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata);
+ static bool lodQueryCallback();
+
+ boost::signals2::connection setDetailsCallback(const details_signal_t::slot_type& cb){ return mDetailsSignal.connect(cb); }
+ boost::signals2::connection setModelLoadedCallback(const model_loaded_signal_t::slot_type& cb){ return mModelLoadedSignal.connect(cb); }
+ boost::signals2::connection setModelUpdatedCallback(const model_updated_signal_t::slot_type& cb){ return mModelUpdatedSignal.connect(cb); }
+
+ void setLoadState(U32 state) { mLoadState = state; }
+ U32 getLoadState() { return mLoadState; }
+
+ static bool sIgnoreLoadedCallback;
+ std::vector<S32> mLodsQuery;
+ std::vector<S32> mLodsWithParsingError;
+ bool mHasDegenerate;
+
+protected:
+
+ static void loadedCallback(LLModelLoader::scene& scene, LLModelLoader::model_list& model_list, S32 lod, void* opaque);
+ static void stateChangedCallback(U32 state, void* opaque);
+
+ static LLJoint* lookupJointByName(const std::string&, void* opaque);
+ static U32 loadTextures(LLImportMaterial& material, void* opaque);
+
+ void lookupLODModelFiles(S32 lod);
+
+private:
+ //Utility function for controller vertex compare
+ bool verifyCount(int expected, int result);
+ //Creates the dummy avatar for the preview window
+ void createPreviewAvatar(void);
+ //Accessor for the dummy avatar
+ LLVOAvatar* getPreviewAvatar(void) { return mPreviewAvatar; }
+ // Count amount of original models, excluding sub-models
+ static U32 countRootModels(LLModelLoader::model_list models);
+
+protected:
+ friend class LLModelLoader;
+ friend class LLFloaterModelPreview;
+ friend class LLFloaterModelPreview::DecompRequest;
+ friend class LLPhysicsDecomp;
+
+ LLFloater* mFMP;
+
+ BOOL mNeedsUpdate;
+ bool mDirty;
+ bool mGenLOD;
+ U32 mTextureName;
+ F32 mCameraDistance;
+ F32 mCameraYaw;
+ F32 mCameraPitch;
+ F32 mCameraZoom;
+ LLVector3 mCameraOffset;
+ LLVector3 mPreviewTarget;
+ LLVector3 mPreviewScale;
+ S32 mPreviewLOD;
+ S32 mPhysicsSearchLOD;
+ U32 mResourceCost;
+ std::string mLODFile[LLModel::NUM_LODS];
+ bool mLoading;
+ U32 mLoadState;
+ bool mResetJoints;
+ bool mModelNoErrors;
+ bool mLookUpLodFiles;
+
+ std::map<std::string, bool> mViewOption;
+
+ //GLOD object parameters (must rebuild object if these change)
+ bool mLODFrozen;
+ F32 mBuildShareTolerance;
+ U32 mBuildQueueMode;
+ U32 mBuildOperator;
+ U32 mBuildBorderMode;
+ U32 mRequestedLoDMode[LLModel::NUM_LODS];
+ S32 mRequestedTriangleCount[LLModel::NUM_LODS];
+ F32 mRequestedErrorThreshold[LLModel::NUM_LODS];
+ U32 mRequestedBuildOperator[LLModel::NUM_LODS];
+ U32 mRequestedQueueMode[LLModel::NUM_LODS];
+ U32 mRequestedBorderMode[LLModel::NUM_LODS];
+ F32 mRequestedShareTolerance[LLModel::NUM_LODS];
+ F32 mRequestedCreaseAngle[LLModel::NUM_LODS];
+
+ LLModelLoader* mModelLoader;
+
+ LLModelLoader::scene mScene[LLModel::NUM_LODS];
+ LLModelLoader::scene mBaseScene;
+
+ LLModelLoader::model_list mModel[LLModel::NUM_LODS];
+ LLModelLoader::model_list mBaseModel;
+
+ typedef std::vector<LLVolumeFace> v_LLVolumeFace_t;
+ typedef std::vector<v_LLVolumeFace_t> vv_LLVolumeFace_t;
+
+ vv_LLVolumeFace_t mModelFacesCopy[LLModel::NUM_LODS];
+ vv_LLVolumeFace_t mBaseModelFacesCopy;
+
+ U32 mGroup;
+ std::map<LLPointer<LLModel>, U32> mObject;
+ U32 mMaxTriangleLimit;
+
+ LLMeshUploadThread::instance_list mUploadData;
+ std::set<LLViewerFetchedTexture * > mTextureSet;
+
+ //map of vertex buffers to models (one vertex buffer in vector per face in model
+ std::map<LLModel*, std::vector<LLPointer<LLVertexBuffer> > > mVertexBuffer[LLModel::NUM_LODS + 1];
+
+ details_signal_t mDetailsSignal;
+ model_loaded_signal_t mModelLoadedSignal;
+ model_updated_signal_t mModelUpdatedSignal;
+
+ LLVector3 mModelPivot;
+ bool mHasPivot;
+
+ float mPelvisZOffset;
+
+ bool mRigValidJointUpload;
+ U32 mLegacyRigFlags;
+
+ bool mLastJointUpdate;
+ bool mFirstSkinUpdate;
+
+ JointNameSet mJointsFromNode;
+ JointTransformMap mJointTransformMap;
+
+ LLPointer<LLVOAvatar> mPreviewAvatar;
+ LLCachedControl<bool> mImporterDebug;
+};
+
+#endif // LL_LLMODELPREVIEW_H
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 852ba846ff..272e7ae351 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1047,6 +1047,7 @@ void LLOutfitGallery::updateSnapshotFolderObserver()
void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
{
LLViewerInventoryCategory* category = gInventory.getCategory(category_id);
+ if (category)
{
bool photo_loaded = false;
LLInventoryModel::cat_array_t sub_cat_array;
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 5d1b582d1f..37ed4bc74c 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -44,6 +44,7 @@
#include "llavatariconctrl.h"
#include "llfloaterreg.h"
#include "llnotificationsutil.h"
+#include "llviewermenu.h" // is_agent_mappable
#include "llvoiceclient.h"
#include "lltextbox.h"
#include "lltrans.h"
diff --git a/indra/newview/llpanelexperiences.cpp b/indra/newview/llpanelexperiences.cpp
index 37981b36a9..91d3b523fb 100644
--- a/indra/newview/llpanelexperiences.cpp
+++ b/indra/newview/llpanelexperiences.cpp
@@ -93,9 +93,20 @@ void LLPanelExperiences::setExperienceList( const LLSD& experiences )
item->init(public_key);
mExperiencesList->addItem(item, public_key);
+
+ const LLSD& experience_details = LLExperienceCache::instance().get(public_key);
+ if (experience_details.isUndefined())
+ {
+ LLExperienceCache::instance().get(public_key, boost::bind(&LLPanelExperiences::sortExperiencesList, this));
+ }
}
- mExperiencesList->sort();
+ sortExperiencesList();
+}
+
+void LLPanelExperiences::sortExperiencesList()
+{
+ mExperiencesList->sort();
}
void LLPanelExperiences::getExperienceIdsList(std::vector<LLUUID>& result)
diff --git a/indra/newview/llpanelexperiences.h b/indra/newview/llpanelexperiences.h
index f29fdfdecb..9d5afd1a6a 100644
--- a/indra/newview/llpanelexperiences.h
+++ b/indra/newview/llpanelexperiences.h
@@ -60,6 +60,8 @@ public:
void setExperienceList(const LLSD& experiences);
void getExperienceIdsList(std::vector<LLUUID>& result);
+ void sortExperiencesList();
+
LLExperienceItem* getSelectedExperienceItem();
void removeExperiences( const LLSD& ids );
void removeExperience( const LLUUID& id);
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 5742b5ad1a..23394b26f2 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1027,21 +1027,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChildView("maskcutoff")->setEnabled(editable && mIsAlpha);
getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha);
- bool allAttachments = true;
- for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
- iter != LLSelectMgr::getInstance()->getSelection()->end();iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if (!object->isAttachment())
- {
- allAttachments = false;
- break;
- }
- }
-
- texture_ctrl->setBakeTextureEnabled(allAttachments);
-
+ texture_ctrl->setBakeTextureEnabled(TRUE);
}
else if (id.isNull())
{
@@ -1066,21 +1052,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
getChildView("label alphamode")->setEnabled(editable && mIsAlpha);
getChildView("maskcutoff")->setEnabled(editable && mIsAlpha);
getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha);
-
- bool allAttachments = true;
- for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
- iter != LLSelectMgr::getInstance()->getSelection()->end();iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* object = node->getObject();
- if (!object->isAttachment())
- {
- allAttachments = false;
- break;
- }
- }
-
- texture_ctrl->setBakeTextureEnabled(allAttachments);
+
+ texture_ctrl->setBakeTextureEnabled(TRUE);
}
}
@@ -1109,6 +1082,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
bool enabled = (editable && isIdenticalPlanarTexgen());
childSetValue("checkbox planar align", align_planar && enabled);
+ childSetVisible("checkbox planar align", enabled);
childSetEnabled("checkbox planar align", enabled);
childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1);
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index 06bb886ae8..6751c25fb9 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -39,6 +39,7 @@
#include "llagent.h"
#include "llagentui.h"
#include "lllandmarkactions.h"
+#include "llparcel.h"
#include "llslurl.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
@@ -77,7 +78,7 @@ BOOL LLPanelLandmarkInfo::postBuild()
mCreator = getChild<LLTextBox>("creator");
mCreated = getChild<LLTextBox>("created");
- mLandmarkTitle = getChild<LLTextBox>("title_value");
+ mLandmarkTitle = getChild<LLLineEditor>("title_value");
mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor");
mNotesEditor = getChild<LLTextEditor>("notes_editor");
mFolderCombo = getChild<LLComboBox>("folder_combo");
@@ -113,6 +114,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
landmark_info_panel->setVisible(type == LANDMARK);
getChild<LLTextBox>("folder_label")->setVisible(is_info_type_create_landmark);
+ getChild<LLButton>("edit_btn")->setVisible(!is_info_type_create_landmark);
mFolderCombo->setVisible(is_info_type_create_landmark);
switch(type)
@@ -126,13 +128,10 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
mNotesEditor->setEnabled(TRUE);
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
- std::string name = parcel_mgr->getAgentParcelName();
+ LLParcel* parcel = parcel_mgr->getAgentParcel();
+ std::string name = parcel->getName();
LLVector3 agent_pos = gAgent.getPositionAgent();
- std::string desc;
- LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, agent_pos);
- mNotesEditor->setText(desc);
-
if (name.empty())
{
S32 region_x = ll_round(agent_pos.mV[VX]);
@@ -147,6 +146,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
}
else
{
+ std::string desc;
LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos);
region_name = desc;
}
@@ -159,6 +159,25 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
mLandmarkTitleEditor->setText(name);
}
+ LLUUID owner_id = parcel->getOwnerID();
+ if (owner_id.notNull())
+ {
+ if (parcel->getIsGroupOwned())
+ {
+ std::string owner_name = LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString();
+ mParcelOwner->setText(owner_name);
+ }
+ else
+ {
+ std::string owner_name = LLSLURL("agent", owner_id, "inspect").getSLURLString();
+ mParcelOwner->setText(owner_name);
+ }
+ }
+ else
+ {
+ mParcelOwner->setText(getString("public"));
+ }
+
// Moved landmark creation here from LLPanelLandmarkInfo::processParcelInfo()
// because we use only agent's current coordinates instead of waiting for
// remote parcel request to complete.
@@ -210,6 +229,24 @@ void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data)
mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG));
}
+ if (parcel_data.owner_id.notNull())
+ {
+ if (parcel_data.flags & 0x4) // depends onto DRTSIM-453
+ {
+ std::string owner_name = LLSLURL("group", parcel_data.owner_id, "inspect").getSLURLString();
+ mParcelOwner->setText(owner_name);
+ }
+ else
+ {
+ std::string owner_name = LLSLURL("agent", parcel_data.owner_id, "inspect").getSLURLString();
+ mParcelOwner->setText(owner_name);
+ }
+ }
+ else
+ {
+ mParcelOwner->setText(getString("public"));
+ }
+
LLSD info;
info["update_verbs"] = true;
info["global_x"] = parcel_data.global_x;
@@ -264,7 +301,8 @@ void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem)
}
else
{
- mOwner->setText(getString("public"));
+ std::string public_str = getString("public");
+ mOwner->setText(public_str);
}
//////////////////
@@ -311,6 +349,7 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)
mNotesEditor->setReadOnly(!enabled);
mFolderCombo->setVisible(enabled);
getChild<LLTextBox>("folder_label")->setVisible(enabled);
+ getChild<LLButton>("edit_btn")->setVisible(!enabled);
// HACK: To change the text color in a text editor
// when it was enabled/disabled we set the text once again.
@@ -357,7 +396,7 @@ void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)
// If no parcel exists use the region name instead.
if (name.empty())
{
- name = mRegionName->getText();
+ name = mRegionTitle;
}
}
diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h
index 01a6fd6b3d..9712736182 100644
--- a/indra/newview/llpanellandmarkinfo.h
+++ b/indra/newview/llpanellandmarkinfo.h
@@ -71,7 +71,7 @@ private:
LLTextBox* mOwner;
LLTextBox* mCreator;
LLTextBox* mCreated;
- LLTextBox* mLandmarkTitle;
+ LLLineEditor* mLandmarkTitle;
LLLineEditor* mLandmarkTitleEditor;
LLTextEditor* mNotesEditor;
LLComboBox* mFolderCombo;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index cd1dc0f070..ccd8497484 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -227,6 +227,12 @@ BOOL LLLandmarksPanel::postBuild()
initMyInventoryPanel();
initLibraryInventoryPanel();
+ LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+ if (accordion)
+ {
+ accordion->setSkipScrollToChild(true);
+ }
+
return TRUE;
}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index da21d5e69a..a19182b01e 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -563,7 +563,7 @@ void LLPanelLogin::populateFields(LLPointer<LLCredential> credential, bool remem
{
sInstance->getChild<LLUICtrl>("remember_name")->setValue(remember_user);
LLUICtrl* remember_password = sInstance->getChild<LLUICtrl>("remember_password");
- remember_password->setValue(remember_psswrd);
+ remember_password->setValue(remember_user && remember_psswrd);
remember_password->setEnabled(remember_user);
sInstance->populateUserList(credential);
}
@@ -687,7 +687,6 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
if (LLPanelLogin::sInstance->mPasswordModified)
{
- authenticator = LLSD::emptyMap();
// password is plaintext
authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
authenticator["secret"] = password;
@@ -698,6 +697,15 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
if (credential.notNull())
{
authenticator = credential->getAuthenticator();
+ if (authenticator.emptyMap())
+ {
+ // Likely caused by user trying to log in to non-system grid
+ // with unsupported name format, just retry
+ LL_WARNS() << "Authenticator failed to load for: " << username << LL_ENDL;
+ // password is plaintext
+ authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
+ authenticator["secret"] = password;
+ }
}
}
}
@@ -1137,7 +1145,11 @@ void LLPanelLogin::onRememberUserCheck(void*)
remember_name->setValue(true);
LLNotificationsUtil::add("LoginCantRemoveUsername");
}
- remember_psswrd->setEnabled(remember);
+ if (!remember)
+ {
+ remember_psswrd->setValue(false);
+ }
+ remember_psswrd->setEnabled(remember);
}
}
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp
index cea7054d6a..7a6631448b 100644
--- a/indra/newview/llpanelmarketplaceinboxinventory.cpp
+++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp
@@ -36,12 +36,15 @@
#include "llpanellandmarks.h"
#include "llplacesinventorybridge.h"
#include "llviewerfoldertype.h"
+#include "llsdserialize.h"
#define DEBUGGING_FRESHNESS 0
const LLColor4U DEFAULT_WHITE(255, 255, 255);
+const std::string NEW_INBOX_FILENAME("inbox_new_items.xml");
+
//
// statics
//
@@ -57,7 +60,9 @@ static LLDefaultChildRegistry::Register<LLInboxFolderViewItem> r3("inbox_folder_
LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p)
: LLInventoryPanel(p)
-{}
+{
+ LLInboxNewItemsStorage::getInstance()->load();
+}
LLInboxInventoryPanel::~LLInboxInventoryPanel()
{}
@@ -127,7 +132,7 @@ void LLInboxFolderViewFolder::addItem(LLFolderViewItem* item)
}
// Compute freshness if our parent is the root folder for the inbox
- if (mParentFolder == mRoot)
+ if ((mParentFolder == mRoot) && !mFresh)
{
computeFreshness();
}
@@ -145,6 +150,12 @@ void LLInboxFolderViewFolder::draw()
setBadgeVisibility(mFresh);
LLFolderViewFolder::draw();
+
+ if (mFresh)
+ {
+ reshapeBadge(getRect());
+ }
+
}
BOOL LLInboxFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask )
@@ -167,11 +178,12 @@ void LLInboxFolderViewFolder::selectItem()
void LLInboxFolderViewFolder::computeFreshness()
{
+ LLFolderViewModelItemInventory* view_model = static_cast<LLFolderViewModelItemInventory*>(getViewModelItem());
const U32 last_expansion_utc = gSavedPerAccountSettings.getU32("LastInventoryInboxActivity");
if (last_expansion_utc > 0)
{
- mFresh = (static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getCreationDate() > last_expansion_utc);
+ mFresh = (view_model->getCreationDate() > last_expansion_utc) || LLInboxNewItemsStorage::getInstance()->isItemFresh(view_model->getUUID());
#if DEBUGGING_FRESHNESS
if (mFresh)
@@ -184,6 +196,11 @@ void LLInboxFolderViewFolder::computeFreshness()
{
mFresh = true;
}
+
+ if (mFresh)
+ {
+ LLInboxNewItemsStorage::getInstance()->addFreshItem(view_model->getUUID());
+ }
}
void LLInboxFolderViewFolder::deFreshify()
@@ -191,6 +208,7 @@ void LLInboxFolderViewFolder::deFreshify()
mFresh = false;
gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());
+ LLInboxNewItemsStorage::getInstance()->removeItem(static_cast<LLFolderViewModelItemInventory*>(getViewModelItem())->getUUID());
}
//
@@ -271,5 +289,55 @@ void LLInboxFolderViewItem::deFreshify()
gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected());
}
+LLInboxNewItemsStorage::LLInboxNewItemsStorage()
+{
+}
+
+// static
+void LLInboxNewItemsStorage::destroyClass()
+{
+ LLInboxNewItemsStorage::getInstance()->saveNewItemsIds();
+}
+
+void LLInboxNewItemsStorage::saveNewItemsIds()
+{
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, NEW_INBOX_FILENAME);
+ if (!filename.empty())
+ {
+ LLSD uuids_data;
+ for (std::set<LLUUID>::const_iterator it = mNewItemsIDs.begin(); it != mNewItemsIDs.end(); it++)
+ {
+ uuids_data.append((*it));
+ }
+ llofstream file;
+ file.open(filename.c_str());
+ if ( file.is_open() )
+ {
+ LLSDSerialize::toPrettyXML(uuids_data, file);
+ file.close();
+ }
+ }
+}
+
+void LLInboxNewItemsStorage::load()
+{
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, NEW_INBOX_FILENAME);
+ if (!filename.empty())
+ {
+ llifstream in_file;
+ in_file.open(filename.c_str());
+
+ LLSD uuids_data;
+ if (in_file.is_open())
+ {
+ LLSDSerialize::fromXML(uuids_data, in_file);
+ in_file.close();
+ for (LLSD::array_iterator i = uuids_data.beginArray(); i != uuids_data.endArray(); ++i)
+ {
+ mNewItemsIDs.insert((*i).asUUID());
+ }
+ }
+ }
+}
// eof
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h
index 0b27818c95..3e508e801b 100644
--- a/indra/newview/llpanelmarketplaceinboxinventory.h
+++ b/indra/newview/llpanelmarketplaceinboxinventory.h
@@ -113,4 +113,23 @@ protected:
bool mFresh;
};
+class LLInboxNewItemsStorage : public LLSingleton<LLInboxNewItemsStorage>
+ , public LLDestroyClass<LLInboxNewItemsStorage>
+{
+ LLSINGLETON(LLInboxNewItemsStorage);
+ LOG_CLASS(LLInboxNewItemsStorage);
+public:
+ static void destroyClass();
+ void saveNewItemsIds();
+
+ void load();
+
+ void addFreshItem(const LLUUID& id) { mNewItemsIDs.insert(id); }
+ void removeItem(const LLUUID& id) { mNewItemsIDs.erase(id); }
+ bool isItemFresh(const LLUUID& id) { return (mNewItemsIDs.find(id) != mNewItemsIDs.end()); }
+
+private:
+ std::set<LLUUID> mNewItemsIDs;
+};
+
#endif //LL_INBOXINVENTORYPANEL_H
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index 8019335f97..8fff52ca4e 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -55,6 +55,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() :
mMyOutfitsPanel(NULL),
mCurrentOutfitPanel(NULL),
mActivePanel(NULL),
+ mAppearanceTabs(NULL),
mInitialized(false)
{
gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this));
@@ -312,6 +313,7 @@ void LLPanelOutfitsInventory::initTabPanels()
void LLPanelOutfitsInventory::onTabChange()
{
+ if (!mAppearanceTabs) return;
mActivePanel = dynamic_cast<LLPanelAppearanceTab*>(mAppearanceTabs->getCurrentPanel());
if (!mActivePanel) return;
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 0c70aa87c2..9157df789f 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -43,6 +43,7 @@
#include "llagent.h"
#include "llexpandabletextbox.h"
#include "llpanelpick.h"
+#include "llslurl.h"
#include "lltexturectrl.h"
#include "llviewerregion.h"
#include "llhttpconstants.h"
@@ -78,6 +79,7 @@ BOOL LLPanelPlaceInfo::postBuild()
mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
mRegionName = getChild<LLTextBox>("region_title");
mParcelName = getChild<LLTextBox>("parcel_title");
+ mParcelOwner = getChild<LLTextBox>("parcel_owner");
mDescEditor = getChild<LLExpandableTextBox>("description");
mMaturityRatingIcon = getChild<LLIconCtrl>("maturity_icon");
@@ -98,11 +100,13 @@ void LLPanelPlaceInfo::resetLocation()
mParcelID.setNull();
mRequestedID.setNull();
mPosRegion.clearVec();
+ mRegionTitle.clear();
std::string loading = LLTrans::getString("LoadingData");
mMaturityRatingText->setValue(loading);
- mRegionName->setText(loading);
+ mRegionName->setTextArg("[REGIONAMEPOS]", loading);
mParcelName->setText(loading);
+ mParcelOwner->setText(loading);
mDescEditor->setText(loading);
mMaturityRatingIcon->setValue(LLUUID::null);
@@ -182,9 +186,11 @@ void LLPanelPlaceInfo::setErrorStatus(S32 status, const std::string& reason)
std::string not_available = getString("not_available");
mMaturityRatingText->setValue(not_available);
- mRegionName->setText(not_available);
+ mRegionName->setTextArg("[REGIONAMEPOS]", not_available);
mParcelName->setText(not_available);
+ mParcelOwner->setText(not_available);
mMaturityRatingIcon->setValue(LLUUID::null);
+ mRegionTitle.clear();
// Enable "Back" button that was disabled when parcel request was sent.
getChild<LLButton>("back_btn")->setEnabled(TRUE);
@@ -198,12 +204,34 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
}
- if(!parcel_data.sim_name.empty())
- {
- mRegionName->setText(parcel_data.sim_name);
+ S32 region_x;
+ S32 region_y;
+ S32 region_z;
+
+ // If the region position is zero, grab position from the global
+ if (mPosRegion.isExactlyZero())
+ {
+ region_x = ll_round(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ region_y = ll_round(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ region_z = ll_round(parcel_data.global_z);
+ }
+ else
+ {
+ region_x = ll_round(mPosRegion.mV[VX]);
+ region_y = ll_round(mPosRegion.mV[VY]);
+ region_z = ll_round(mPosRegion.mV[VZ]);
+ }
+
+ if (!parcel_data.sim_name.empty())
+ {
+ mRegionTitle = parcel_data.sim_name;
+ std::string name_and_pos = llformat("%s (%d, %d, %d)",
+ mRegionTitle.c_str(), region_x, region_y, region_z);
+ mRegionName->setTextArg("[REGIONAMEPOS]", name_and_pos);
}
else
{
+ mRegionTitle.clear();
mRegionName->setText(LLStringUtil::null);
}
@@ -216,30 +244,11 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mDescEditor->setText(getString("not_available"));
}
- S32 region_x;
- S32 region_y;
- S32 region_z;
-
- // If the region position is zero, grab position from the global
- if(mPosRegion.isExactlyZero())
- {
- region_x = ll_round(parcel_data.global_x) % REGION_WIDTH_UNITS;
- region_y = ll_round(parcel_data.global_y) % REGION_WIDTH_UNITS;
- region_z = ll_round(parcel_data.global_z);
- }
- else
- {
- region_x = ll_round(mPosRegion.mV[VX]);
- region_y = ll_round(mPosRegion.mV[VY]);
- region_z = ll_round(mPosRegion.mV[VZ]);
- }
-
if (!parcel_data.name.empty())
{
mParcelTitle = parcel_data.name;
- mParcelName->setText(llformat("%s (%d, %d, %d)",
- mParcelTitle.c_str(), region_x, region_y, region_z));
+ mParcelName->setText(mParcelTitle);
}
else
{
@@ -280,12 +289,10 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)
{
- std::string region_name = mRegionName->getText();
-
LLPickData data;
data.pos_global = pos_global;
- data.name = mParcelTitle.empty() ? region_name : mParcelTitle;
- data.sim_name = region_name;
+ data.name = mParcelTitle.empty() ? mRegionTitle : mParcelTitle;
+ data.sim_name = mRegionTitle;
data.desc = mDescEditor->getText();
data.snapshot_id = mSnapshotCtrl->getImageAssetID();
data.parcel_id = mParcelID;
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 30327378ef..8bf67cfe7d 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -109,6 +109,7 @@ protected:
LLUUID mRequestedID;
LLVector3 mPosRegion;
std::string mParcelTitle; // used for pick title without coordinates
+ std::string mRegionTitle;
std::string mCurrentTitle;
S32 mScrollingPanelMinHeight;
S32 mScrollingPanelWidth;
@@ -120,6 +121,7 @@ protected:
LLTextureCtrl* mSnapshotCtrl;
LLTextBox* mRegionName;
LLTextBox* mParcelName;
+ LLTextBox* mParcelOwner;
LLExpandableTextBox* mDescEditor;
LLIconCtrl* mMaturityRatingIcon;
LLTextBox* mMaturityRatingText;
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 104316e253..9283dfa218 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -104,8 +104,6 @@ BOOL LLPanelPlaceProfile::postBuild()
mForSalePanel->getChild<LLIconCtrl>("icon_for_sale")->
setMouseDownCallback(boost::bind(&LLPanelPlaceProfile::onForSaleBannerClick, this));
- mParcelOwner = getChild<LLTextBox>("owner_value");
-
mParcelRatingIcon = getChild<LLIconCtrl>("rating_icon");
mParcelRatingText = getChild<LLTextBox>("rating_value");
mVoiceIcon = getChild<LLIconCtrl>("voice_icon");
@@ -183,7 +181,6 @@ void LLPanelPlaceProfile::resetLocation()
mYouAreHerePanel->setVisible(FALSE);
std::string loading = LLTrans::getString("LoadingData");
- mParcelOwner->setValue(loading);
mParcelRatingIcon->setValue(loading);
mParcelRatingText->setText(loading);
@@ -248,14 +245,14 @@ void LLPanelPlaceProfile::setInfoType(EInfoType type)
const S32 SEARCH_DESC_HEIGHT = 150;
// Remember original geometry (once).
- static const S32 sOrigDescVPad = getChildView("parcel_title")->getRect().mBottom - mDescEditor->getRect().mTop;
+ static const S32 sOrigDescVPad = getChildView("owner_label")->getRect().mBottom - mDescEditor->getRect().mTop;
static const S32 sOrigDescHeight = mDescEditor->getRect().getHeight();
static const S32 sOrigMRIconVPad = mDescEditor->getRect().mBottom - mMaturityRatingIcon->getRect().mTop;
static const S32 sOrigMRTextVPad = mDescEditor->getRect().mBottom - mMaturityRatingText->getRect().mTop;
// Resize the description.
const S32 desc_height = is_info_type_agent ? sOrigDescHeight : SEARCH_DESC_HEIGHT;
- const S32 desc_top = getChildView("parcel_title")->getRect().mBottom - sOrigDescVPad;
+ const S32 desc_top = getChildView("owner_label")->getRect().mBottom - sOrigDescVPad;
LLRect desc_rect = mDescEditor->getRect();
desc_rect.setOriginAndSize(desc_rect.mLeft, desc_top - desc_height, desc_rect.getWidth(), desc_height);
mDescEditor->reshape(desc_rect.getWidth(), desc_rect.getHeight());
@@ -401,6 +398,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
parcel_data.global_x = pos_global.mdV[VX];
parcel_data.global_y = pos_global.mdV[VY];
parcel_data.global_z = pos_global.mdV[VZ];
+ parcel_data.owner_id = parcel->getOwnerID();
std::string on = getString("on");
std::string off = getString("off");
diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h
index 3d2654fc12..16478bc179 100644
--- a/indra/newview/llpanelplaceprofile.h
+++ b/indra/newview/llpanelplaceprofile.h
@@ -76,8 +76,6 @@ private:
LLPanel* mForSalePanel;
LLPanel* mYouAreHerePanel;
- LLTextBox* mParcelOwner;
-
LLIconCtrl* mParcelRatingIcon;
LLTextBox* mParcelRatingText;
LLIconCtrl* mVoiceIcon;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 2ef82d0cf9..53870fb5c7 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -59,6 +59,7 @@
#include "llinventorymodel.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
+#include "lllayoutstack.h"
#include "llpanellandmarkinfo.h"
#include "llpanellandmarks.h"
#include "llpanelpick.h"
@@ -280,9 +281,6 @@ BOOL LLPanelPlaces::postBuild()
mShowOnMapBtn = getChild<LLButton>("map_btn");
mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this));
- mEditBtn = getChild<LLButton>("edit_btn");
- mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
-
mSaveBtn = getChild<LLButton>("save_btn");
mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this));
@@ -355,6 +353,9 @@ BOOL LLPanelPlaces::postBuild()
LLComboBox* folder_combo = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
folder_combo->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+ LLButton* edit_btn = mLandmarkInfo->getChild<LLButton>("edit_btn");
+ edit_btn->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
createTabs();
updateVerbs();
@@ -532,7 +533,6 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
BOOL is_landmark_editable = gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) &&
mItem->getPermissions().allowModifyBy(gAgent.getID());
- mEditBtn->setEnabled(is_landmark_editable);
mSaveBtn->setEnabled(is_landmark_editable);
if (is_landmark_editable)
@@ -1216,13 +1216,16 @@ void LLPanelPlaces::updateVerbs()
mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
- mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
- mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
mSaveBtn->setVisible(isLandmarkEditModeOn);
mCancelBtn->setVisible(isLandmarkEditModeOn);
mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
+ bool show_options_btn = is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn;
+ mOverflowBtn->setVisible(show_options_btn);
+ getChild<LLLayoutPanel>("lp_options")->setVisible(show_options_btn);
+ getChild<LLLayoutPanel>("lp2")->setVisible(!show_options_btn);
+
mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);
if (is_place_info_visible)
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 27f991c202..978b030b2e 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -121,7 +121,6 @@ private:
LLButton* mPlaceProfileBackBtn;
LLButton* mTeleportBtn;
LLButton* mShowOnMapBtn;
- LLButton* mEditBtn;
LLButton* mSaveBtn;
LLButton* mCancelBtn;
LLButton* mCloseBtn;
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 55c84815aa..2bd78f40ba 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -73,6 +73,7 @@ bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model);
const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM };
const int LLPanelPrimMediaControls::kNumZoomLevels = 2;
+const F32 EXCEEDING_ZOOM_DISTANCE = 0.5f;
//
// LLPanelPrimMediaControls
//
@@ -93,6 +94,7 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mZoomObjectID(LLUUID::null),
mZoomObjectFace(0),
mVolumeSliderVisible(0),
+ mZoomedCameraPos(),
mWindowShade(NULL),
mHideImmediately(false),
mSecureURL(false),
@@ -256,7 +258,7 @@ void LLPanelPrimMediaControls::focusOnTarget()
LLViewerMediaImpl* media_impl = getTargetMediaImpl();
if(media_impl)
{
- if(!media_impl->hasFocus())
+ if (!media_impl->hasFocus())
{
// The current target doesn't have media focus -- focus on it.
LLViewerObject* objectp = getTargetObject();
@@ -307,7 +309,8 @@ void LLPanelPrimMediaControls::updateShape()
bool can_navigate = parcel->getMediaAllowNavigate();
bool enabled = false;
- bool is_zoomed = (mCurrentZoom != ZOOM_NONE) && (mTargetObjectID == mZoomObjectID) && (mTargetObjectFace == mZoomObjectFace);
+ bool is_zoomed = (mCurrentZoom != ZOOM_NONE) && (mTargetObjectID == mZoomObjectID) && (mTargetObjectFace == mZoomObjectFace) && !isZoomDistExceeding();
+
// There is no such thing as "has_focus" being different from normal controls set
// anymore (as of user feedback from bri 10/09). So we cheat here and force 'has_focus'
// to 'true' (or, actually, we use a setting)
@@ -1141,7 +1144,7 @@ void LLPanelPrimMediaControls::updateZoom()
if (zoom_padding > 0.0f)
{
// since we only zoom into medium for now, always set zoom_in constraint to true
- LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding, true);
+ mZoomedCameraPos = LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding, true);
}
// Remember the object ID/face we zoomed into, so we can update the zoom icon appropriately
@@ -1401,6 +1404,10 @@ bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible()
return mVolumeSliderVisible > 0;
}
+bool LLPanelPrimMediaControls::isZoomDistExceeding()
+{
+ return (gAgentCamera.getCameraPositionGlobal() - mZoomedCameraPos).normalize() >= EXCEEDING_ZOOM_DISTANCE;
+}
void LLPanelPrimMediaControls::clearFaceOnFade()
{
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index d4301aaf7c..86fc036553 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -119,6 +119,8 @@ private:
void showVolumeSlider();
void hideVolumeSlider();
bool shouldVolumeSliderBeVisible();
+
+ bool isZoomDistExceeding();
static void onScrollUp(void* user_data);
static void onScrollUpHeld(void* user_data);
@@ -183,6 +185,8 @@ private:
F32 mZoomMediumPadding;
F32 mZoomFarPadding;
S32 mTopWorldViewAvoidZone;
+
+ LLVector3d mZoomedCameraPos;
LLUICtrl *mMediaPanelScroll;
LLButton *mScrollUpCtrl;
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index 89cb495db9..3347c40687 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -64,7 +64,9 @@ public:
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
- registrar.add("Gear.Edit", boost::bind(&edit_outfit));
+ registrar.add("Gear.TouchAttach", boost::bind(&LLWearingGearMenu::handleMultiple, this, handle_attachment_touch));
+ registrar.add("Gear.EditItem", boost::bind(&LLWearingGearMenu::handleMultiple, this, handle_item_edit));
+ registrar.add("Gear.EditOutfit", boost::bind(&edit_outfit));
registrar.add("Gear.TakeOff", boost::bind(&LLPanelWearing::onRemoveItem, mPanelWearing));
registrar.add("Gear.Copy", boost::bind(&LLPanelWearing::copyToClipboard, mPanelWearing));
@@ -78,6 +80,16 @@ public:
LLToggleableMenu* getMenu() { return mMenu; }
private:
+ void handleMultiple(std::function<void(const LLUUID& id)> functor)
+ {
+ uuid_vec_t selected_item_ids;
+ mPanelWearing->getSelectedItemsUUIDs(selected_item_ids);
+
+ for (const LLUUID& item_id : selected_item_ids)
+ {
+ functor(item_id);
+ }
+ }
LLToggleableMenu* mMenu;
LLPanelWearing* mPanelWearing;
@@ -92,7 +104,9 @@ protected:
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- registrar.add("Wearing.Edit", boost::bind(&edit_outfit));
+ registrar.add("Wearing.TouchAttach", boost::bind(handleMultiple, handle_attachment_touch, mUUIDs));
+ registrar.add("Wearing.EditItem", boost::bind(handleMultiple, handle_item_edit, mUUIDs));
+ registrar.add("Wearing.EditOutfit", boost::bind(&edit_outfit));
registrar.add("Wearing.ShowOriginal", boost::bind(show_item_original, mUUIDs.front()));
registrar.add("Wearing.TakeOff",
boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
@@ -138,14 +152,19 @@ protected:
}
// Enable/disable some menu items depending on the selection.
+ bool show_touch = !bp_selected && !clothes_selected && attachments_selected;
+ bool show_edit = bp_selected || clothes_selected || attachments_selected;
bool allow_detach = !bp_selected && !clothes_selected && attachments_selected;
bool allow_take_off = !bp_selected && clothes_selected && !attachments_selected;
+ menu->setItemVisible("touch_attach", show_touch);
+ menu->setItemEnabled("touch_attach", 1 == mUUIDs.size() && enable_attachment_touch(mUUIDs.front()));
+ menu->setItemVisible("edit_item", show_edit);
+ menu->setItemEnabled("edit_item", 1 == mUUIDs.size() && get_is_item_editable(mUUIDs.front()));
menu->setItemVisible("take_off", allow_take_off);
menu->setItemVisible("detach", allow_detach);
- menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach);
+ menu->setItemVisible("edit_outfit_separator", show_touch | show_edit | allow_take_off || allow_detach);
menu->setItemVisible("show_original", mUUIDs.size() == 1);
- menu->setItemVisible("edit_item", FALSE);
}
};
@@ -173,12 +192,15 @@ protected:
void updateMenuItemsVisibility(LLContextMenu* menu)
{
+ menu->setItemVisible("touch_attach", TRUE);
+ menu->setItemEnabled("touch_attach", 1 == mUUIDs.size());
+ menu->setItemVisible("edit_item", TRUE);
+ menu->setItemEnabled("edit_item", 1 == mUUIDs.size());
menu->setItemVisible("take_off", FALSE);
menu->setItemVisible("detach", TRUE);
- menu->setItemVisible("edit_outfit_separator", TRUE);
+ menu->setItemVisible("edit_outfit_separator", FALSE);
menu->setItemVisible("show_original", FALSE);
- menu->setItemVisible("edit_item", TRUE);
- menu->setItemVisible("edit", FALSE);
+ menu->setItemVisible("edit_outfit", FALSE);
}
LLPanelWearing* mPanelWearing;
@@ -350,6 +372,18 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
}
}
+ uuid_vec_t selected_uuids;
+ getSelectedItemsUUIDs(selected_uuids);
+
+ if (command_name == "touch_attach")
+ {
+ return (1 == selected_uuids.size()) && (enable_attachment_touch(selected_uuids.front()));
+ }
+ else if (command_name == "edit_item")
+ {
+ return (1 == selected_uuids.size()) && (get_is_item_editable(selected_uuids.front()));
+ }
+
return false;
}
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
index a23830e8e1..1c14acd843 100644
--- a/indra/newview/llplacesinventorypanel.cpp
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -43,9 +43,8 @@ static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_invent
static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER;
LLPlacesInventoryPanel::LLPlacesInventoryPanel(const Params& p) :
- LLInventoryPanel(p),
+ LLAssetFilteredInventoryPanel(p),
mSavedFolderState(NULL)
-
{
mInvFVBridgeBuilder = &PLACES_INVENTORY_BUILDER;
mSavedFolderState = new LLSaveFolderState();
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
index 27d9b83bd1..5629438415 100644
--- a/indra/newview/llplacesinventorypanel.h
+++ b/indra/newview/llplacesinventorypanel.h
@@ -32,14 +32,16 @@
class LLLandmarksPanel;
class LLFolderView;
-class LLPlacesInventoryPanel : public LLInventoryPanel
+class LLPlacesInventoryPanel : public LLAssetFilteredInventoryPanel
{
public:
struct Params
- : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ : public LLInitParam::Block<Params, LLAssetFilteredInventoryPanel::Params>
{
Params()
- {}
+ {
+ filter_asset_type = "landmark";
+ }
};
LLPlacesInventoryPanel(const Params& p);
diff --git a/indra/newview/llpresetsmanager.h b/indra/newview/llpresetsmanager.h
index d5b384ceb9..0de30e9e01 100644
--- a/indra/newview/llpresetsmanager.h
+++ b/indra/newview/llpresetsmanager.h
@@ -33,6 +33,7 @@
#include <map>
static const std::string PRESETS_DEFAULT = "Default";
+static const std::string PRESETS_DEFAULT_UPPER = "DEFAULT";
static const std::string PRESETS_DIR = "presets";
static const std::string PRESETS_GRAPHIC = "graphic";
static const std::string PRESETS_CAMERA = "camera";
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 7ef0ef0e8b..1b60610668 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -307,6 +307,7 @@ void LLPreviewNotecard::loadAsset()
{
editor->setEnabled(FALSE);
getChildView("lock")->setVisible( TRUE);
+ getChildView("Edit")->setEnabled(FALSE);
}
if((allow_modify || is_owner) && !source_library)
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index e9feae3457..3e3ab3a676 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -404,28 +404,30 @@ void LLProgressView::initLogos()
// with no internal paddings so it gets additional padding
icon_width = 77;
icon_height = 21;
- S32 pad_y = 4;
+ S32 pad_fmod_y = 4;
texture_start_x++;
loadLogo(temp_str + "fmod_logo.png",
image_codec,
- LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y),
+ LLRect(texture_start_x, texture_start_y + pad_fmod_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_fmod_y),
default_clip,
default_clip);
texture_start_x += icon_width + default_pad + 1;
-#endif
+#endif //LL_FMODSTUDIO
+#ifdef LL_HAVOK
// original image size is 342x113, central element is on a larger side
// plus internal padding, so it gets slightly more height than desired 32
icon_width = 88;
icon_height = 29;
- pad_y = -1;
+ S32 pad_havok_y = -1;
loadLogo(temp_str + "havok_logo.png",
image_codec,
- LLRect(texture_start_x, texture_start_y + pad_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_y),
+ LLRect(texture_start_x, texture_start_y + pad_havok_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_havok_y),
default_clip,
default_clip);
texture_start_x += icon_width + default_pad;
+#endif //LL_HAVOK
// 108x41
icon_width = 74;
@@ -545,6 +547,7 @@ void LLProgressView::onCancelButtonClicked(void*)
// cancel is pressed while teleporting inside region (EXT-4911)
if (LLStartUp::getStartupState() < STATE_STARTED)
{
+ LL_INFOS() << "User requesting quit during login" << LL_ENDL;
LLAppViewer::instance()->requestQuit();
}
else
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index 5b0d189137..70c117be44 100644
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -45,7 +45,7 @@ struct LLParcelData
std::string desc;
S32 actual_area;
S32 billable_area;
- U8 flags;
+ U8 flags; // group owned, maturity
F32 global_x;
F32 global_y;
F32 global_z;
diff --git a/indra/newview/llsearchableui.cpp b/indra/newview/llsearchableui.cpp
index 93143eb33f..1119e80005 100644
--- a/indra/newview/llsearchableui.cpp
+++ b/indra/newview/llsearchableui.cpp
@@ -68,7 +68,10 @@ ll::prefs::PanelData::~PanelData()
bool ll::prefs::PanelData::hightlightAndHide( LLWString const &aFilter )
{
for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
- (*itr)->setNotHighlighted( );
+ (*itr)->setNotHighlighted();
+
+ for (tPanelDataList::iterator itr = mChildPanel.begin(); itr != mChildPanel.end(); ++itr)
+ (*itr)->setNotHighlighted();
if (aFilter.empty())
{
@@ -85,6 +88,15 @@ bool ll::prefs::PanelData::hightlightAndHide( LLWString const &aFilter )
return bVisible;
}
+void ll::prefs::PanelData::setNotHighlighted()
+{
+ for (tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr)
+ (*itr)->setNotHighlighted();
+
+ for (tPanelDataList::iterator itr = mChildPanel.begin(); itr != mChildPanel.end(); ++itr)
+ (*itr)->setNotHighlighted();
+}
+
bool ll::prefs::TabContainerData::hightlightAndHide( LLWString const &aFilter )
{
for( tSearchableItemList::iterator itr = mChildren.begin(); itr != mChildren.end(); ++itr )
diff --git a/indra/newview/llsearchableui.h b/indra/newview/llsearchableui.h
index 9741557e49..e033cae3ab 100644
--- a/indra/newview/llsearchableui.h
+++ b/indra/newview/llsearchableui.h
@@ -73,6 +73,7 @@ namespace ll
virtual ~PanelData();
+ void setNotHighlighted();
virtual bool hightlightAndHide( LLWString const &aFilter );
};
diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp
index 10e510b842..b9259cb18d 100644
--- a/indra/newview/llsecapi.cpp
+++ b/indra/newview/llsecapi.cpp
@@ -117,7 +117,7 @@ LLSD LLCredential::getLoginParams()
else if (mIdentifier["type"].asString() == "account")
{
result["username"] = mIdentifier["account_name"];
- result["passwd"] = mAuthenticator["secret"];
+ result["passwd"] = mAuthenticator["secret"].asString();
username = result["username"].asString();
}
}
@@ -154,3 +154,10 @@ void LLCredential::authenticatorType(std::string &idType)
}
}
+
+LLCertException::LLCertException(const LLSD& cert_data, const std::string& msg)
+ : LLException(msg),
+ mCertData(cert_data)
+{
+ LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
+}
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index 69b6b32923..14059f828a 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -75,6 +75,7 @@
#define CERT_EXTENDED_KEY_USAGE "extendedKeyUsage"
#define CERT_EKU_SERVER_AUTH SN_server_auth
+#define CERT_EKU_TLS_SERVER_AUTH LN_server_auth
#define CERT_SUBJECT_KEY_IDENTFIER "subjectKeyIdentifier"
#define CERT_AUTHORITY_KEY_IDENTIFIER "authorityKeyIdentifier"
@@ -334,17 +335,23 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
class LLCertException: public LLException
{
public:
- LLCertException(const LLSD& cert_data, const std::string& msg): LLException(msg),
- mCertData(cert_data)
- {
- LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
- }
+ LLCertException(const LLSD& cert_data, const std::string& msg);
virtual ~LLCertException() throw() {}
LLSD getCertData() const { return mCertData; }
protected:
LLSD mCertData;
};
+class LLAllocationCertException : public LLCertException
+{
+public:
+ LLAllocationCertException(const LLSD& cert_data) : LLCertException(cert_data, "CertAllocationFailure")
+ {
+ }
+ virtual ~LLAllocationCertException() throw() {}
+protected:
+};
+
class LLInvalidCertificate : public LLCertException
{
public:
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 55e49100c3..737ef30ada 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -78,16 +78,16 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert,
BIO * pem_bio = BIO_new_mem_buf((void*)pem_cert.c_str(), pem_cert.length());
if(pem_bio == NULL)
{
- LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
- LLTHROW(LLInvalidCertificate(LLSD::emptyMap()));
+ LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
+ LLTHROW(LLAllocationCertException(LLSD::emptyMap()));
}
mCert = NULL;
PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
BIO_free(pem_bio);
if (!mCert)
{
- LL_WARNS("SECAPI") << "Could not decode certificate to x509." << LL_ENDL;
- LLTHROW(LLInvalidCertificate(LLSD::emptyMap()));
+ LL_WARNS("SECAPI") << "Could not decode certificate to x509." << LL_ENDL;
+ LLTHROW(LLInvalidCertificate(LLSD::emptyMap()));
}
}
@@ -924,9 +924,13 @@ void _validateCert(int validation_policy,
LLTHROW(LLCertKeyUsageValidationException(current_cert_info));
}
// only validate EKU if the cert has it
- if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&
- (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
- LLSD((std::string)CERT_EKU_SERVER_AUTH))))
+ if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE)
+ && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray()
+ && (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
+ LLSD((std::string)CERT_EKU_TLS_SERVER_AUTH)))
+ && (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
+ LLSD((std::string)CERT_EKU_SERVER_AUTH)))
+ )
{
LLTHROW(LLCertKeyUsageValidationException(current_cert_info));
}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 56068b3bbb..50884762a8 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -303,6 +303,27 @@ void LLSelectMgr::updateEffects()
}
}
+void LLSelectMgr::resetObjectOverrides()
+{
+ resetObjectOverrides(getSelection());
+}
+
+void LLSelectMgr::resetObjectOverrides(LLObjectSelectionHandle selected_handle)
+{
+ struct f : public LLSelectedNodeFunctor
+ {
+ virtual bool apply(LLSelectNode* node)
+ {
+ node->mLastPositionLocal.setVec(0, 0, 0);
+ node->mLastRotation = LLQuaternion();
+ node->mLastScale.setVec(0, 0, 0);
+ return true;
+ }
+ } func;
+
+ selected_handle->applyToNodes(&func);
+}
+
void LLSelectMgr::overrideObjectUpdates()
{
//override any position updates from simulator on objects being edited
@@ -3910,11 +3931,11 @@ BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& r
return TRUE;
}
-BOOL LLSelectMgr::isSelfAvatarSelected()
+BOOL LLSelectMgr::isMovableAvatarSelected()
{
if (mAllowSelectAvatar)
{
- return (getSelection()->getObjectCount() == 1) && (getSelection()->getFirstRootObject() == gAgentAvatarp);
+ return (getSelection()->getObjectCount() == 1) && (getSelection()->getFirstRootObject()->isAvatar()) && getSelection()->getFirstMoveableNode(TRUE);
}
return FALSE;
}
@@ -5130,18 +5151,27 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
bool link_operation = message_name == "ObjectLink";
- //clear update override data (allow next update through)
- struct f : public LLSelectedNodeFunctor
- {
- virtual bool apply(LLSelectNode* node)
- {
- node->mLastPositionLocal.setVec(0,0,0);
- node->mLastRotation = LLQuaternion();
- node->mLastScale.setVec(0,0,0);
- return true;
- }
- } func;
- selected_handle->applyToNodes(&func);
+ if (mAllowSelectAvatar)
+ {
+ if (selected_handle->getObjectCount() == 1
+ && selected_handle->getFirstObject() != NULL
+ && selected_handle->getFirstObject()->isAvatar())
+ {
+ // Server doesn't move avatars at the moment, it is a local debug feature,
+ // but server does update position regularly, so do not drop mLastPositionLocal
+ // Position override for avatar gets reset in LLAgentCamera::resetView().
+ }
+ else
+ {
+ // drop mLastPositionLocal (allow next update through)
+ resetObjectOverrides(selected_handle);
+ }
+ }
+ else
+ {
+ //clear update override data (allow next update through)
+ resetObjectOverrides(selected_handle);
+ }
std::queue<LLSelectNode*> nodes_to_send;
@@ -6851,51 +6881,26 @@ void LLSelectMgr::pauseAssociatedAvatars()
mSelectedObjects->mSelectType = getSelectTypeForObject(object);
- bool is_attached = false;
- if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT &&
- isAgentAvatarValid())
+ LLVOAvatar* parent_av = NULL;
+ if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT)
{
// Selection can be obsolete, confirm that this is an attachment
- LLViewerObject* parent = (LLViewerObject*)object->getParent();
- while (parent != NULL)
- {
- if (parent->isAvatar())
- {
- is_attached = true;
- break;
- }
- else
- {
- parent = (LLViewerObject*)parent->getParent();
- }
- }
+ // and find parent avatar
+ parent_av = object->getAvatarAncestor();
}
-
- if (is_attached)
+ // Can be both an attachment and animated object
+ if (parent_av)
{
- if (object->isAnimatedObject())
- {
- // Is an animated object attachment.
- // Pause both the control avatar and the avatar it's attached to.
- if (object->getControlAvatar())
- {
- mPauseRequests.push_back(object->getControlAvatar()->requestPause());
- }
- mPauseRequests.push_back(gAgentAvatarp->requestPause());
- }
- else
- {
- // Is a regular attachment. Pause the avatar it's attached to.
- mPauseRequests.push_back(gAgentAvatarp->requestPause());
- }
+ // It's an attachment. Pause the avatar it's attached to.
+ mPauseRequests.push_back(parent_av->requestPause());
}
- else if (object && object->isAnimatedObject() && object->getControlAvatar())
+
+ if (object->isAnimatedObject() && object->getControlAvatar())
{
- // Is a non-attached animated object. Pause the control avatar.
+ // It's an animated object. Pause the control avatar.
mPauseRequests.push_back(object->getControlAvatar()->requestPause());
}
-
}
}
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 3bed484b58..57fdfce152 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -458,6 +458,13 @@ public:
void clearSelections();
void update();
void updateEffects(); // Update HUD effects
+
+ // When we edit object's position/rotation/scale we set local
+ // overrides and ignore any updates (override received valeus).
+ // When we send data to server, we send local values and reset
+ // overrides
+ void resetObjectOverrides();
+ void resetObjectOverrides(LLObjectSelectionHandle selected_handle);
void overrideObjectUpdates();
// Returns the previous value of mForceSelection
@@ -725,7 +732,7 @@ public:
LLPermissions* findObjectPermissions(const LLViewerObject* object);
- BOOL isSelfAvatarSelected();
+ BOOL isMovableAvatarSelected();
void selectDelete(); // Delete on simulator
void selectForceDelete(); // just delete, no into trash
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 97b5b2a57d..1e5b893cbc 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -678,8 +678,17 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
{
shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);
+ // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate")
LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]);
- vect_c_p_d1 += LLVector4(LLEnvironment::instance().getCloudScrollDelta());
+ LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() );
+
+ // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
+ // Keep in Sync!
+ // * indra\newview\llsettingsvo.cpp
+ // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl
+ // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+ cloud_scroll[0] = -cloud_scroll[0];
+ vect_c_p_d1 += cloud_scroll;
shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV);
LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index f3439daee9..8369def968 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -155,7 +155,7 @@ F32 LLSnapshotLivePreview::getImageAspect()
void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
{
- LL_DEBUGS() << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL;
// Update snapshot if requested.
if (new_snapshot)
@@ -343,7 +343,7 @@ void LLSnapshotLivePreview::draw()
}
else if (mShineAnimTimer.getStarted())
{
- LL_DEBUGS() << "Drawing shining animation" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "Drawing shining animation" << LL_ENDL;
F32 shine_interp = llmin(1.f, mShineAnimTimer.getElapsedTimeF32() / SHINE_TIME);
// draw "shine" effect
@@ -391,7 +391,7 @@ void LLSnapshotLivePreview::draw()
S32 old_image_index = (mCurImageIndex + 1) % 2;
if (mViewerImage[old_image_index].notNull() && mFallAnimTimer.getElapsedTimeF32() < FALL_TIME)
{
- LL_DEBUGS() << "Drawing fall animation" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "Drawing fall animation" << LL_ENDL;
F32 fall_interp = mFallAnimTimer.getElapsedTimeF32() / FALL_TIME;
F32 alpha = clamp_rescale(fall_interp, 0.f, 1.f, 0.8f, 0.4f);
LLColor4 image_color(1.f, 1.f, 1.f, alpha);
@@ -435,7 +435,7 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare
LLView::reshape(width, height, called_from_parent);
if (old_rect.getWidth() != width || old_rect.getHeight() != height)
{
- LL_DEBUGS() << "window reshaped, updating thumbnail" << LL_ENDL;
+ LL_DEBUGS("Window", "Snapshot") << "window reshaped, updating thumbnail" << LL_ENDL;
if (mViewContainer && mViewContainer->isInVisibleChain())
{
// We usually resize only on window reshape, so give it a chance to redraw, assign delay
@@ -580,7 +580,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
}
else
{
- LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
+ LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
}
}
// Scale to a power of 2 so it can be mapped to a texture
@@ -628,7 +628,7 @@ LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage()
}
else
{
- LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
+ LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
}
}
// Scale to a power of 2 so it can be mapped to a texture
@@ -648,7 +648,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview;
if (previewp->getWidth() == 0 || previewp->getHeight() == 0)
{
- LL_WARNS() << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << LL_ENDL;
+ LL_WARNS("Snapshot") << "Incorrect dimensions: " << previewp->getWidth() << "x" << previewp->getHeight() << LL_ENDL;
return FALSE;
}
@@ -679,7 +679,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->mCameraRot = new_camera_rot;
// request a new snapshot whenever the camera moves, with a time delay
BOOL new_snapshot = gSavedSettings.getBOOL("AutoSnapshot") || previewp->mForceUpdateSnapshot;
- LL_DEBUGS() << "camera moved, updating thumbnail" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "camera moved, updating thumbnail" << LL_ENDL;
previewp->updateSnapshot(
new_snapshot, // whether a new snapshot is needed or merely invalidate the existing one
FALSE, // or if 1st arg is false, whether to produce a new thumbnail image.
@@ -695,7 +695,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
// time to produce a snapshot
if(!previewp->getSnapshotUpToDate())
{
- LL_DEBUGS() << "producing snapshot" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "producing snapshot" << LL_ENDL;
if (!previewp->mPreviewImage)
{
previewp->mPreviewImage = new LLImageRaw;
@@ -745,7 +745,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->getWindow()->decBusyCount();
previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode
previewp->mSnapshotActive = FALSE;
- LL_DEBUGS() << "done creating snapshot" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "done creating snapshot" << LL_ENDL;
}
if (!previewp->getThumbnailUpToDate())
@@ -836,7 +836,7 @@ LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
if (getSnapshotType() == LLSnapshotModel::SNAPSHOT_TEXTURE)
{
// We don't store the intermediate formatted image in mFormattedImage in the J2C case
- LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "Encoding new image of format J2C" << LL_ENDL;
LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
// Copy the preview
LLPointer<LLImageRaw> scaled = new LLImageRaw(
@@ -921,13 +921,13 @@ LLPointer<LLImageFormatted> LLSnapshotLivePreview::getFormattedImage()
}
else
{
- LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
+ LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
}
}
// Create the new formatted image of the appropriate format.
LLSnapshotModel::ESnapshotFormat format = getSnapshotFormat();
- LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "Encoding new image of format " << format << LL_ENDL;
switch (format)
{
@@ -952,7 +952,7 @@ LLPointer<LLImageFormatted> LLSnapshotLivePreview::getFormattedImage()
void LLSnapshotLivePreview::setSize(S32 w, S32 h)
{
- LL_DEBUGS() << "setSize(" << w << ", " << h << ")" << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "setSize(" << w << ", " << h << ")" << LL_ENDL;
setWidth(w);
setHeight(h);
}
@@ -974,7 +974,7 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
{
- LL_DEBUGS() << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << LL_ENDL;
// gen a new uuid for this asset
LLTransactionID tid;
tid.generate();
@@ -997,12 +997,12 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
}
else
{
- LL_WARNS() << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
+ LL_WARNS("Snapshot") << "Couldn't find a path to the following filter : " << getFilter() << LL_ENDL;
}
}
scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
- LL_DEBUGS() << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << LL_ENDL;
+ LL_DEBUGS("Snapshot") << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << LL_ENDL;
if (formatted->encode(scaled, 0.0f))
{
@@ -1030,7 +1030,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
else
{
LLNotificationsUtil::add("ErrorEncodingSnapshot");
- LL_WARNS() << "Error encoding snapshot" << LL_ENDL;
+ LL_WARNS("Snapshot") << "Error encoding snapshot" << LL_ENDL;
}
add(LLStatViewer::SNAPSHOT, 1);
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 77bbcdada6..8fc2405f0a 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -556,7 +556,9 @@ void LLSpatialGroup::shift(const LLVector4a &offset)
if (!getSpatialPartition()->mRenderByGroup &&
getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE &&
getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN &&
- getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE)
+ getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE &&
+ getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_AVATAR &&
+ getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_CONTROL_AV)
{
setState(GEOM_DIRTY);
gPipeline.markRebuild(this, TRUE);
@@ -3123,13 +3125,13 @@ void renderRaycast(LLDrawable* drawablep)
LLGLEnable blend(GL_BLEND);
gGL.diffuseColor4f(0,1,1,0.5f);
- if (drawablep->getVOVolume())
+ LLVOVolume* vobj = drawablep->getVOVolume();
+ if (vobj && !vobj->isDead())
{
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- LLVOVolume* vobj = drawablep->getVOVolume();
LLVolume* volume = vobj->getVolume();
bool transform = true;
@@ -3358,7 +3360,7 @@ public:
for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i)
{
LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable();
- if(!drawable)
+ if(!drawable || drawable->isDead())
{
continue;
}
@@ -3448,7 +3450,7 @@ public:
U8 index = facep->getTextureIndex();
if (facep->mDrawInfo)
{
- if (index < 255)
+ if (index < FACE_DO_NOT_BATCH_TEXTURES)
{
if (facep->mDrawInfo->mTextureList.size() <= index)
{
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 7e65da42f7..919f386d29 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -685,6 +685,18 @@ public:
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); }
};
+class LLAvatarBridge : public LLVolumeBridge
+{
+public:
+ LLAvatarBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
+};
+
+class LLControlAVBridge : public LLVolumeBridge
+{
+public:
+ LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
+};
+
class LLHUDBridge : public LLVolumeBridge
{
public:
@@ -702,6 +714,18 @@ public:
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
};
+class LLAvatarPartition : public LLBridgePartition
+{
+public:
+ LLAvatarPartition(LLViewerRegion* regionp);
+};
+
+class LLControlAVPartition : public LLBridgePartition
+{
+public:
+ LLControlAVPartition(LLViewerRegion* regionp);
+};
+
class LLHUDPartition : public LLBridgePartition
{
public:
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 6d20dcf188..17777c3ceb 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -917,9 +917,9 @@ bool idle_startup()
}
// Set PerAccountSettingsFile to the default value.
- gSavedSettings.setString("PerAccountSettingsFile",
- gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,
- LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")));
+ std::string settings_per_account = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"));
+ gSavedSettings.setString("PerAccountSettingsFile", settings_per_account);
+ gDebugInfo["PerAccountSettingsFilename"] = settings_per_account;
// Note: can't store warnings files per account because some come up before login
@@ -1105,6 +1105,8 @@ bool idle_startup()
// Its either downloading or declined.
// If optional was skipped this case shouldn't
// be reached.
+
+ LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL;
LLLoginInstance::getInstance()->disconnect();
LLAppViewer::instance()->forceQuit();
}
@@ -1125,7 +1127,24 @@ bool idle_startup()
{
// This was a certificate error, so grab the certificate
// and throw up the appropriate dialog.
- LLPointer<LLCertificate> certificate = gSecAPIHandler->getCertificate(response["certificate"]);
+ LLPointer<LLCertificate> certificate;
+ try
+ {
+ certificate = gSecAPIHandler->getCertificate(response["certificate"]);
+ }
+ catch (LLCertException &cert_exception)
+ {
+ LL_WARNS("LLStartup", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate("<< response["certificate"] << ")" << LL_ENDL;
+ LLSD args;
+ args["REASON"] = LLTrans::getString(cert_exception.what());
+
+ LLNotificationsUtil::add("GeneralCertificateErrorShort", args, response,
+ general_cert_done);
+
+ reset_login();
+ gSavedSettings.setBOOL("AutoLogin", FALSE);
+ show_connect_box = true;
+ }
if(certificate)
{
LLSD args = transform_cert_args(certificate);
@@ -1211,7 +1230,6 @@ bool idle_startup()
display_startup();
gAgentCamera.init();
display_startup();
- set_underclothes_menu_options();
display_startup();
// Since we connected, save off the settings so the user doesn't have to
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 2e52414d71..6211d0ce3b 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -616,6 +616,9 @@ bool LLTextureCacheRemoteWorker::doWrite()
if(idx >= 0)
{
// write to the fast cache.
+ // mRawImage is not entirely safe here since it is a pointer to one owned by cache worker,
+ // it could have been retrieved via getRequestFinished() and then modified.
+ // If writeToFastCache crashes, something is wrong around fetch worker.
if(!mCache->writeToFastCache(mID, idx, mRawImage, mRawDiscardLevel))
{
LL_WARNS() << "writeToFastCache failed" << LL_ENDL;
@@ -2155,8 +2158,8 @@ bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer<LLImage
h >>= i;
if(w * h *c > 0) //valid
{
- //make a duplicate to keep the original raw image untouched.
-
+ // Make a duplicate to keep the original raw image untouched.
+ // Might be good idea to do a copy during writeToCache() call instead of here
try
{
#if LL_WINDOWS
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 6a0464c657..6ccb2f68e5 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -139,17 +139,17 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti
if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
{
- if ( mBakeTextureEnabled && mModeSelector->getSelectedIndex() != 2)
+ if ( mBakeTextureEnabled && mModeSelector->getValue().asInteger() != 2)
{
- mModeSelector->setSelectedIndex(2, 0);
+ mModeSelector->selectByValue(2);
onModeSelect(0,this);
}
}
else
{
- if (mModeSelector->getSelectedIndex() == 2)
+ if (mModeSelector->getValue().asInteger() == 2)
{
- mModeSelector->setSelectedIndex(0, 0);
+ mModeSelector->selectByValue(0);
onModeSelect(0,this);
}
@@ -346,7 +346,7 @@ BOOL LLFloaterTexturePicker::postBuild()
}
mTentativeLabel = getChild<LLTextBox>("Multiple");
- mResolutionLabel = getChild<LLTextBox>("unknown");
+ mResolutionLabel = getChild<LLTextBox>("size_lbl");
childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this);
@@ -362,9 +362,9 @@ BOOL LLFloaterTexturePicker::postBuild()
mInventoryPanel = getChild<LLInventoryPanel>("inventory panel");
- mModeSelector = getChild<LLRadioGroup>("mode_selection");
+ mModeSelector = getChild<LLComboBox>("mode_selection");
mModeSelector->setCommitCallback(onModeSelect, this);
- mModeSelector->setSelectedIndex(0, 0);
+ mModeSelector->selectByValue(0);
if(mInventoryPanel)
{
@@ -431,7 +431,7 @@ BOOL LLFloaterTexturePicker::postBuild()
getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setCommitCallback(onHideBaseMeshRegionCheck, this);
- setBakeTextureEnabled(FALSE);
+ setBakeTextureEnabled(TRUE);
return TRUE;
}
@@ -755,7 +755,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem
void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
{
LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
- int index = self->mModeSelector->getSelectedIndex();
+ int index = self->mModeSelector->getValue().asInteger();
self->getChild<LLButton>("Default")->setVisible(index == 0 ? TRUE : FALSE);
self->getChild<LLButton>("Blank")->setVisible(index == 0 ? TRUE : FALSE);
@@ -1082,7 +1082,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )
void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled)
{
- mModeSelector->setIndexEnabled(1,enabled);
+ mModeSelector->setEnabledByValue(1, enabled);
}
void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled)
@@ -1090,18 +1090,18 @@ void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled)
BOOL changed = (enabled != mBakeTextureEnabled);
mBakeTextureEnabled = enabled;
- mModeSelector->setIndexEnabled(2, enabled);
+ mModeSelector->setEnabledByValue(2, enabled);
- if (!mBakeTextureEnabled && (mModeSelector->getSelectedIndex() == 2))
+ if (!mBakeTextureEnabled && (mModeSelector->getValue().asInteger() == 2))
{
- mModeSelector->setSelectedIndex(0, 0);
+ mModeSelector->selectByValue(0);
}
if (changed && mBakeTextureEnabled && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID))
{
- if (mModeSelector->getSelectedIndex() != 2)
+ if (mModeSelector->getValue().asInteger() != 2)
{
- mModeSelector->setSelectedIndex(2, 0);
+ mModeSelector->selectByValue(2);
}
}
onModeSelect(0, this);
@@ -1156,8 +1156,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
mImageAssetID(p.image_id),
mDefaultImageAssetID(p.default_image_id),
mDefaultImageName(p.default_image_name),
- mFallbackImage(p.fallback_image),
- mBakeTextureEnabled(FALSE)
+ mFallbackImage(p.fallback_image)
{
// Default of defaults is white image for diff tex
@@ -1350,7 +1349,7 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
}
if (texture_floaterp)
{
- texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled);
+ texture_floaterp->setBakeTextureEnabled(TRUE);
}
LLFloater* root_floater = gFloaterView->getParentFloater(this);
@@ -1529,7 +1528,6 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
void LLTextureCtrl::setBakeTextureEnabled(BOOL enabled)
{
- mBakeTextureEnabled = enabled;
LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
if (floaterp)
{
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index b2a34a37c4..92f6f89af6 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -36,7 +36,6 @@
#include "llstring.h"
#include "lluictrl.h"
#include "llpermissionsflags.h"
-#include "llradiogroup.h"
#include "lltextbox.h" // for params
#include "llviewerinventory.h"
#include "llviewborder.h" // for params
@@ -44,7 +43,7 @@
#include "llviewertexture.h"
#include "llwindow.h"
-class LLButton;
+class LLComboBox;
class LLFloaterTexturePicker;
class LLInventoryItem;
class LLViewerFetchedTexture;
@@ -239,7 +238,6 @@ private:
BOOL mShowLoadingPlaceholder;
std::string mLoadingPlaceholderString;
S32 mLabelWidth;
- BOOL mBakeTextureEnabled;
};
//////////////////////////////////////////////////////////////////////////////////////////
@@ -367,7 +365,7 @@ protected:
LLSaveFolderState mSavedFolderState;
BOOL mSelectedItemPinned;
- LLRadioGroup* mModeSelector;
+ LLComboBox* mModeSelector;
LLScrollListCtrl* mLocalScrollCtrl;
private:
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index fe058024f6..f64db7beb5 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1977,6 +1977,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
setState(WAIT_ON_WRITE);
++mCacheWriteCount;
CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID);
+ // This call might be under work mutex, but mRawImage is not nessesary safe here.
+ // If something retrieves it via getRequestFinished() and modifies, image won't
+ // be protected by work mutex and won't be safe to use here nor in cache worker.
+ // So make sure users of getRequestFinished() does not attempt to modify image while
+ // fetcher is working
mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
mFormattedImage->getData(), datasize,
mFileSize, mRawImage, mDecodedDiscard, responder);
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index cdf8868597..2aa194e141 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -92,6 +92,7 @@ public:
void deleteAllRequests();
// Threads: T*
+ // keep in mind that if fetcher isn't done, it still might need original raw image
bool getRequestFinished(const LLUUID& id, S32& discard_level,
LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux,
LLCore::HttpStatus& last_http_get_status);
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 0d2edc0268..1c4187d30f 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -549,7 +549,7 @@ void LLGLTexMemBar::draw()
U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
- text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
+ text = llformat("GL Tot: %d/%d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
total_mem.value(),
max_total_mem.value(),
bound_mem.value(),
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index a4806ceaf6..f01b374db1 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -142,8 +142,9 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)
// call the base class to propogate info to sim
LLTool::handleMouseDown(x, y, mask);
-
- if (!gAgent.leftButtonGrabbed())
+
+ // leftButtonGrabbed() checks if controls are reserved by scripts, but does not take masks into account
+ if (!gAgent.leftButtonGrabbed() || ((mask & DEFAULT_GRAB_MASK) != 0 && !gAgentCamera.cameraMouselook()))
{
// can grab transparent objects (how touch event propagates, scripters rely on this)
gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE);
diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h
index 02ed5c26d7..ce0de0f946 100644
--- a/indra/newview/lltoolgrab.h
+++ b/indra/newview/lltoolgrab.h
@@ -44,6 +44,7 @@ class LLPickInfo;
void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, const LLVector3 &grab_offset);
void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick);
+const MASK DEFAULT_GRAB_MASK = MASK_CONTROL;
/**
* LLToolGrabBase contains most of the semantics of LLToolGrab. It's just that
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index f499c34ca4..864ce09430 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -671,7 +671,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
else
{
// perform a separate pick that detects transparent objects since they respond to 1-click actions
- LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged);
+ LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, FALSE, pick_rigged);
LLViewerObject* click_action_object = click_action_pick.getObject();
@@ -1449,7 +1449,7 @@ LLTool* LLToolPie::getOverrideTool(MASK mask)
{
if (gSavedSettings.getBOOL("EnableGrab"))
{
- if (mask == MASK_CONTROL)
+ if (mask == DEFAULT_GRAB_MASK)
{
return LLToolGrab::getInstance();
}
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index cacdee7e83..54f80a2995 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -49,6 +49,7 @@
/// LLViewerAssetRequest
///----------------------------------------------------------------------------
+ // There is also PoolSizeVAssetStorage value in setting that should mirror this name
static const std::string VIEWER_ASSET_STORAGE_CORO_POOL = "VAssetStorage";
/**
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index c65431d6f6..8aa5b07561 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -187,6 +187,16 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue)
bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
{
+ LLRenderTarget::sUseFBO = newvalue.asBoolean();
+ if (gPipeline.isInit())
+ {
+ gPipeline.updateRenderTransparentWater();
+ gPipeline.updateRenderDeferred();
+ gPipeline.releaseGLBuffers();
+ gPipeline.createGLBuffers();
+ gPipeline.resetVertexBuffers();
+ LLViewerShaderMgr::instance()->setShaders();
+ }
LLWorld::getInstance()->updateWaterObjects();
return true;
}
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index f025863072..caf79edfe4 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -710,9 +710,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
- BOOL to_texture = gPipeline.canUseVertexShaders() &&
- LLPipeline::sRenderGlow;
-
LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
{
@@ -919,31 +916,28 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
stop_glerror();
- if (to_texture)
- {
- gGL.setColorMask(true, true);
-
- if (LLPipeline::sRenderDeferred)
- {
- gPipeline.mDeferredScreen.bindTarget();
- glClearColor(1,0,1,1);
- gPipeline.mDeferredScreen.clear();
- }
- else
- {
- gPipeline.mScreen.bindTarget();
- if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
- {
- const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
- glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
- }
- gPipeline.mScreen.clear();
- }
-
- gGL.setColorMask(true, false);
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
+ gGL.setColorMask(true, true);
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ gPipeline.mDeferredScreen.bindTarget();
+ glClearColor(1, 0, 1, 1);
+ gPipeline.mDeferredScreen.clear();
+ }
+ else
+ {
+ gPipeline.mScreen.bindTarget();
+ if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
+ {
+ const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
+ glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+ }
+ gPipeline.mScreen.clear();
+ }
+
+ gGL.setColorMask(true, false);
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
&& !gRestoreGL)
@@ -1005,38 +999,20 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
}
}
- LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
-
- if (to_texture)
- {
- if (LLPipeline::sRenderDeferred)
- {
- gPipeline.mDeferredScreen.flush();
- if(LLRenderTarget::sUseFBO)
- {
- LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(),
- gPipeline.mDeferredScreen.getHeight(), 0, 0,
- gPipeline.mDeferredScreen.getWidth(),
- gPipeline.mDeferredScreen.getHeight(),
- GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
- }
- }
- else
- {
- gPipeline.mScreen.flush();
- if(LLRenderTarget::sUseFBO)
- {
- LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(),
- gPipeline.mScreen.getHeight(), 0, 0,
- gPipeline.mScreen.getWidth(),
- gPipeline.mScreen.getHeight(),
- GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
- }
- }
- }
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
- if (LLPipeline::sRenderDeferred)
- {
+ LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mDeferredScreen : gPipeline.mScreen);
+ rt.flush();
+
+ if (rt.sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(rt, 0, 0, rt.getWidth(), rt.getHeight(), 0, 0, rt.getWidth(),
+ rt.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_NEAREST);
+ }
+
+ if (LLPipeline::sRenderDeferred)
+ {
gPipeline.renderDeferredLighting(&gPipeline.mScreen);
}
@@ -1300,19 +1276,12 @@ void render_ui(F32 zoom_factor, int subfield)
gGL.popMatrix();
}
- {
- BOOL to_texture = gPipeline.canUseVertexShaders() &&
- LLPipeline::sRenderGlow;
+ // Finalize scene
+ gPipeline.renderFinalize();
- if (to_texture)
- {
- gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
- }
-
- LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
- render_hud_elements();
- render_hud_attachments();
- }
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
+ render_hud_elements();
+ render_hud_attachments();
LLGLSDefault gls_default;
LLGLSUIDefault gls_ui;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d0cbd1181b..bbed741a33 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -81,6 +81,9 @@ static const char * const LOG_INV("Inventory");
static const char * const LOG_LOCAL("InventoryLocalize");
static const char * const LOG_NOTECARD("copy_inventory_from_notecard");
+static const std::string INV_OWNER_ID("owner_id");
+static const std::string INV_VERSION("version");
+
#if 1
// *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model.
// temp code in transition
@@ -519,14 +522,6 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
}
// virtual
-BOOL LLViewerInventoryItem::importFile(LLFILE* fp)
-{
- BOOL rv = LLInventoryItem::importFile(fp);
- mIsComplete = TRUE;
- return rv;
-}
-
-// virtual
BOOL LLViewerInventoryItem::importLegacyStream(std::istream& input_stream)
{
BOOL rv = LLInventoryItem::importLegacyStream(input_stream);
@@ -534,32 +529,6 @@ BOOL LLViewerInventoryItem::importLegacyStream(std::istream& input_stream)
return rv;
}
-bool LLViewerInventoryItem::importFileLocal(LLFILE* fp)
-{
- // TODO: convert all functions that return BOOL to return bool
- bool rv = (LLInventoryItem::importFile(fp) ? true : false);
- mIsComplete = false;
- return rv;
-}
-
-bool LLViewerInventoryItem::exportFileLocal(LLFILE* fp) const
-{
- std::string uuid_str;
- fprintf(fp, "\tinv_item\t0\n\t{\n");
- mUUID.toString(uuid_str);
- fprintf(fp, "\t\titem_id\t%s\n", uuid_str.c_str());
- mParentUUID.toString(uuid_str);
- fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
- mPermissions.exportFile(fp);
- fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
- fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
- fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate);
- fprintf(fp,"\t}\n");
- return true;
-}
-
void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const
{
LLMessageSystem* msg = gMessageSystem;
@@ -720,90 +689,26 @@ S32 LLViewerInventoryCategory::getViewerDescendentCount() const
return descendents_actual;
}
-bool LLViewerInventoryCategory::importFileLocal(LLFILE* fp)
+LLSD LLViewerInventoryCategory::exportLLSD() const
{
- // *NOTE: This buffer size is hard coded into scanf() below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
+ LLSD cat_data = LLInventoryCategory::exportLLSD();
+ cat_data[INV_OWNER_ID] = mOwnerID;
+ cat_data[INV_VERSION] = mVersion;
- keyword[0] = '\0';
- valuestr[0] = '\0';
- while(!feof(fp))
- {
- if (fgets(buffer, MAX_STRING, fp) == NULL)
- {
- buffer[0] = '\0';
- }
-
- sscanf( /* Flawfinder: ignore */
- buffer, " %254s %254s", keyword, valuestr);
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("cat_id", keyword))
- {
- mUUID.set(valuestr);
- }
- else if(0 == strcmp("parent_id", keyword))
- {
- mParentUUID.set(valuestr);
- }
- else if(0 == strcmp("type", keyword))
- {
- mType = LLAssetType::lookup(valuestr);
- }
- else if(0 == strcmp("pref_type", keyword))
- {
- mPreferredType = LLFolderType::lookup(valuestr);
- }
- else if(0 == strcmp("name", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer, " %254s %254[^|]", keyword, valuestr);
- mName.assign(valuestr);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
- else if(0 == strcmp("owner_id", keyword))
- {
- mOwnerID.set(valuestr);
- }
- else if(0 == strcmp("version", keyword))
- {
- sscanf(valuestr, "%d", &mVersion);
- }
- else
- {
- LL_WARNS(LOG_INV) << "unknown keyword '" << keyword
- << "' in inventory import category " << mUUID << LL_ENDL;
- }
- }
- return true;
+ return cat_data;
}
-bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const
-{
- std::string uuid_str;
- fprintf(fp, "\tinv_category\t0\n\t{\n");
- mUUID.toString(uuid_str);
- fprintf(fp, "\t\tcat_id\t%s\n", uuid_str.c_str());
- mParentUUID.toString(uuid_str);
- fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str());
- fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- fprintf(fp, "\t\tpref_type\t%s\n", LLFolderType::lookup(mPreferredType).c_str());
- fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
- mOwnerID.toString(uuid_str);
- fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str());
- fprintf(fp, "\t\tversion\t%d\n", mVersion);
- fprintf(fp,"\t}\n");
+bool LLViewerInventoryCategory::importLLSD(const LLSD& cat_data)
+{
+ LLInventoryCategory::importLLSD(cat_data);
+ if (cat_data.has(INV_OWNER_ID))
+ {
+ mOwnerID = cat_data[INV_OWNER_ID].asUUID();
+ }
+ if (cat_data.has(INV_VERSION))
+ {
+ setVersion(cat_data[INV_VERSION].asInteger());
+ }
return true;
}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index d537b28682..24b632632b 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -131,14 +131,8 @@ public:
virtual void packMessage(LLMessageSystem* msg) const;
virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
virtual BOOL unpackMessage(const LLSD& item);
- virtual BOOL importFile(LLFILE* fp);
virtual BOOL importLegacyStream(std::istream& input_stream);
- // file handling on the viewer. These are not meant for anything
- // other than cacheing.
- bool exportFileLocal(LLFILE* fp) const;
- bool importFileLocal(LLFILE* fp);
-
// new methods
BOOL isFinished() const { return mIsComplete; }
void setComplete(BOOL complete) { mIsComplete = complete; }
@@ -226,10 +220,9 @@ public:
// How many descendents do we currently have information for in the InventoryModel?
S32 getViewerDescendentCount() const;
- // file handling on the viewer. These are not meant for anything
- // other than caching.
- bool exportFileLocal(LLFILE* fp) const;
- bool importFileLocal(LLFILE* fp);
+ LLSD exportLLSD() const;
+ bool importLLSD(const LLSD& cat_data);
+
void determineFolderType();
void changeType(LLFolderType::EType new_folder_type);
virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 6990f56a08..fdfd22c117 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -253,7 +253,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
//----------------------------------------------------------------
llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive
- LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP;
LLViewerTexLayerSet *layerset = dynamic_cast<LLViewerTexLayerSet*>(mLayerSet);
if (mTestImageName)
{
@@ -280,22 +279,15 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
}
- else
- if ( !is_dummy && mTexture.notNull() )
+ else if ( !is_dummy && mTexture.notNull() )
{
- if(mTexture->hasGLTexture())
- {
- old_mode = mTexture->getAddressMode();
- }
gGL.getTexUnit(diffuse_channel)->bind(mTexture);
- gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
else
{
gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
-
U32 mask = sRenderMask;
U32 start = mMesh->mFaceVertexOffset;
@@ -341,12 +333,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT);
}
- if (mTexture.notNull() && !is_dummy)
- {
- gGL.getTexUnit(diffuse_channel)->bind(mTexture);
- gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(old_mode);
- }
-
return triangle_count;
}
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index c36d877a59..534a67195e 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1719,23 +1719,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
std::string user_data_path_cache = gDirUtilp->getCacheDir(false);
user_data_path_cache += gDirUtilp->getDirDelimiter();
- std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir();
- user_data_path_cookies += gDirUtilp->getDirDelimiter();
-
std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt");
- // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.)
- // If the linden username returned is blank, that can only mean we are
- // at the login page displaying login Web page or Web browser test via Develop menu.
- // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this
- // is what we always used before this change)
- std::string linden_user_dir = gDirUtilp->getLindenUserDir();
- if ( ! linden_user_dir.empty() )
- {
- user_data_path_cookies = linden_user_dir;
- user_data_path_cookies += gDirUtilp->getDirDelimiter();
- };
-
// See if the plugin executable exists
llstat s;
if(LLFile::stat(launcher_name, &s))
@@ -1752,7 +1737,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
{
media_source = new LLPluginClassMedia(owner);
media_source->setSize(default_width, default_height);
- media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_cef_log);
+ media_source->setUserDataPath(user_data_path_cache, gDirUtilp->getUserName(), user_data_path_cef_log);
media_source->setLanguageCode(LLUI::getLanguage());
media_source->setZoomFactor(zoom_factor);
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index 71ae7bfbc3..10099eda5b 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -205,8 +205,9 @@ bool LLViewerMediaFocus::getFocus()
}
// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value
-void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor, bool zoom_in_only)
+LLVector3d LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor, bool zoom_in_only)
{
+ LLVector3d camera_pos;
if (object)
{
gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
@@ -254,7 +255,7 @@ void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal,
distance += depth * 0.5;
// Finally animate the camera to this new position and focal point
- LLVector3d camera_pos, target_pos;
+ LLVector3d target_pos;
// The target lookat position is the center of the selection (in global coords)
target_pos = center;
// Target look-from (camera) position is "distance" away from the target along the normal
@@ -287,7 +288,7 @@ void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal,
if (zoom_in_only &&
(dist_vec_squared(gAgentCamera.getCameraPositionGlobal(), target_pos) < dist_vec_squared(camera_pos, target_pos)))
{
- return;
+ return camera_pos;
}
gAgentCamera.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() );
@@ -298,6 +299,7 @@ void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal,
// If we have no object, focus back on the avatar.
gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
}
+ return camera_pos;
}
void LLViewerMediaFocus::onFocusReceived()
{
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index fa469c36e3..effd08a559 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -63,7 +63,7 @@ public:
void update();
- static void setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor, bool zoom_in_only = false);
+ static LLVector3d setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor, bool zoom_in_only = false);
static F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
bool isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b6c7be2ed3..4890867f29 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -375,20 +375,6 @@ void initialize_menus();
// Break up groups of more than 6 items with separators
//-----------------------------------------------------------------------------
-void set_underclothes_menu_options()
-{
- if (gMenuHolder && gAgent.isTeen())
- {
- gMenuHolder->getChild<LLView>("Self Underpants")->setVisible(FALSE);
- gMenuHolder->getChild<LLView>("Self Undershirt")->setVisible(FALSE);
- }
- if (gMenuBarView && gAgent.isTeen())
- {
- gMenuBarView->getChild<LLView>("Menu Underpants")->setVisible(FALSE);
- gMenuBarView->getChild<LLView>("Menu Undershirt")->setVisible(FALSE);
- }
-}
-
void set_merchant_SLM_menu()
{
// All other cases (new merchant, not merchant, migrated merchant): show the new Marketplace Listings menu and enable the tool
@@ -740,6 +726,10 @@ U32 render_type_from_string(std::string render_type)
{
return LLPipeline::RENDER_TYPE_AVATAR;
}
+ else if ("controlAV" == render_type) // Animesh
+ {
+ return LLPipeline::RENDER_TYPE_CONTROL_AV;
+ }
else if ("surfacePatch" == render_type)
{
return LLPipeline::RENDER_TYPE_TERRAIN;
@@ -2777,7 +2767,6 @@ class LLObjectBuild : public view_listener_t
}
};
-
void handle_object_edit()
{
LLViewerParcelMgr::getInstance()->deselectLand();
@@ -2822,6 +2811,57 @@ void handle_object_edit()
return;
}
+void handle_attachment_edit(const LLUUID& inv_item_id)
+{
+ if (isAgentAvatarValid())
+ {
+ if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id))
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj);
+
+ handle_object_edit();
+ }
+ }
+}
+
+void handle_attachment_touch(const LLUUID& inv_item_id)
+{
+ if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) )
+ {
+ if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)))
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+
+ LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj);
+ if (!LLToolMgr::getInstance()->inBuildMode())
+ {
+ struct SetTransient : public LLSelectedNodeFunctor
+ {
+ bool apply(LLSelectNode* node)
+ {
+ node->setTransient(TRUE);
+ return true;
+ }
+ } f;
+ sel->applyToNodes(&f);
+ }
+
+ handle_object_touch();
+ }
+ }
+}
+
+bool enable_attachment_touch(const LLUUID& inv_item_id)
+{
+ if (isAgentAvatarValid())
+ {
+ const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id));
+ return (attach_obj) && (attach_obj->flagHandleTouch());
+ }
+ return false;
+}
+
void handle_object_inspect()
{
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 6882405407..0f63c8cf58 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -82,7 +82,6 @@ void handle_detach(void*);
BOOL enable_god_full(void* user_data);
BOOL enable_god_liaison(void* user_data);
BOOL enable_god_basic(void* user_data);
-void set_underclothes_menu_options();
void check_merchant_status(bool force = false);
void exchange_callingcard(const LLUUID& dest_id);
@@ -110,6 +109,10 @@ void handle_object_return();
void handle_object_delete();
void handle_object_edit();
+void handle_attachment_edit(const LLUUID& inv_item_id);
+void handle_attachment_touch(const LLUUID& inv_item_id);
+bool enable_attachment_touch(const LLUUID& inv_item_id);
+
void handle_buy_land();
// Takes avatar UUID, or if no UUID passed, uses last selected object
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index cd48b1e8e7..d43442d69d 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -552,7 +552,7 @@ class LLFileUploadModel : public view_listener_t
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::getInstance("upload_model");
if (fmp && !fmp->isModelLoading())
{
- fmp->loadModel(3);
+ fmp->loadHighLodModel();
}
return TRUE;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 06a8ebbe89..ea9dba3c4e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2220,8 +2220,12 @@ protected:
}
};
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMPROVED_IM("Process IM");
+
void process_improved_im(LLMessageSystem *msg, void **user_data)
{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMPROVED_IM);
+
LLUUID from_id;
BOOL from_group;
LLUUID to_id;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 9c91cde09a..aa775b2bab 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -284,6 +284,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mOnActiveList(FALSE),
mOnMap(FALSE),
mStatic(FALSE),
+ mSeatCount(0),
mNumFaces(0),
mRotTime(0.f),
mAngularVelocityRot(),
@@ -895,7 +896,12 @@ void LLViewerObject::addChild(LLViewerObject *childp)
if(childp->setParent(this))
{
mChildList.push_back(childp);
- childp->afterReparent();
+ childp->afterReparent();
+
+ if (childp->isAvatar())
+ {
+ mSeatCount++;
+ }
}
}
@@ -924,6 +930,11 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
{
childp->setParent(NULL);
}
+
+ if (childp->isAvatar())
+ {
+ mSeatCount--;
+ }
break;
}
}
@@ -981,21 +992,10 @@ BOOL LLViewerObject::isChild(LLViewerObject *childp) const
return FALSE;
}
-
// returns TRUE if at least one avatar is sitting on this object
BOOL LLViewerObject::isSeat() const
{
- for (child_list_t::const_iterator iter = mChildList.begin();
- iter != mChildList.end(); iter++)
- {
- LLViewerObject* child = *iter;
- if (child->isAvatar())
- {
- return TRUE;
- }
- }
- return FALSE;
-
+ return mSeatCount > 0;
}
BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 03c5403a1e..250c4ac328 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -114,7 +114,7 @@ class LLViewerObject
public LLTrace::MemTrackable<LLViewerObject>
{
protected:
- ~LLViewerObject(); // use unref()
+ virtual ~LLViewerObject(); // use unref()
// TomY: Provide for a list of extra parameter structures, mapped by structure name
struct ExtraParameter
@@ -832,6 +832,7 @@ protected:
BOOL mOnActiveList;
BOOL mOnMap; // On the map.
BOOL mStatic; // Object doesn't move.
+ S32 mSeatCount;
S32 mNumFaces;
F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega)
diff --git a/indra/newview/llviewerparcelaskplay.cpp b/indra/newview/llviewerparcelaskplay.cpp
index 74586dadc3..afbe2c94de 100644
--- a/indra/newview/llviewerparcelaskplay.cpp
+++ b/indra/newview/llviewerparcelaskplay.cpp
@@ -59,7 +59,10 @@ void LLViewerParcelAskPlay::initSingleton()
}
void LLViewerParcelAskPlay::cleanupSingleton()
{
- cancelNotification();
+ if (LLNotifications::instanceExists())
+ {
+ cancelNotification();
+ }
}
void LLViewerParcelAskPlay::askToPlay(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, ask_callback cb)
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index c966b7d4f9..d5365e4ee8 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1906,7 +1906,10 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
|| music_url.substr(0, 8) == "https://")
{
LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender());
- optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
+ if (region)
+ {
+ optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
+ }
}
else
{
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e67826454b..a30c5156fa 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -102,6 +102,7 @@ const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE;
S32 LLViewerRegion::sLastCameraUpdated = 0;
S32 LLViewerRegion::sNewObjectCreationThrottle = -1;
+LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup;
typedef std::map<std::string, std::string> CapabilityMap;
@@ -298,6 +299,11 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
++mSeedCapAttempts;
+ if (LLApp::isExiting())
+ {
+ return;
+ }
+
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
@@ -412,6 +418,11 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
break; // no retry
}
+ if (LLApp::isExiting())
+ {
+ break;
+ }
+
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
@@ -515,6 +526,11 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
continue;
}
+ if (LLApp::isExiting())
+ {
+ break;
+ }
+
// remove the http_result from the llsd
result.erase("http_result");
@@ -609,6 +625,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mImpl->mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS
mImpl->mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME
mImpl->mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE
+ mImpl->mObjectPartition.push_back(new LLAvatarPartition(this)); //PARTITION_AVATAR
+ mImpl->mObjectPartition.push_back(new LLControlAVPartition(this)); //PARTITION_CONTROL_AV
mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE
mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE
mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE
@@ -633,6 +651,9 @@ void LLViewerRegion::initStats()
mAlive = false; // can become false if circuit disconnects
}
+static LLTrace::BlockTimerStatHandle FTM_CLEANUP_REGION_OBJECTS("Cleanup Region Objects");
+static LLTrace::BlockTimerStatHandle FTM_SAVE_REGION_CACHE("Save Region Cache");
+
LLViewerRegion::~LLViewerRegion()
{
mDead = TRUE;
@@ -647,7 +668,10 @@ LLViewerRegion::~LLViewerRegion()
disconnectAllNeighbors();
LLViewerPartSim::getInstance()->cleanupRegion(this);
- gObjectList.killObjects(this);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_CLEANUP_REGION_OBJECTS);
+ gObjectList.killObjects(this);
+ }
delete mImpl->mCompositionp;
delete mParcelOverlay;
@@ -658,7 +682,10 @@ LLViewerRegion::~LLViewerRegion()
#endif
std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
- saveObjectCache();
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SAVE_REGION_CACHE);
+ saveObjectCache();
+ }
delete mImpl;
mImpl = NULL;
@@ -727,6 +754,8 @@ void LLViewerRegion::saveObjectCache()
mCacheDirty = FALSE;
}
+ // Map of LLVOCacheEntry takes time to release, store map for cleanup on idle
+ sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end());
mImpl->mCacheMap.clear();
}
@@ -1488,6 +1517,16 @@ void LLViewerRegion::idleUpdate(F32 max_update_time)
return;
}
+// static
+void LLViewerRegion::idleCleanup(F32 max_update_time)
+{
+ LLTimer update_timer;
+ while (!sRegionCacheCleanup.empty() && (max_update_time - update_timer.getElapsedTimeF32() > 0))
+ {
+ sRegionCacheCleanup.erase(sRegionCacheCleanup.begin());
+ }
+}
+
//update the throttling number for new object creation
void LLViewerRegion::calcNewObjectCreationThrottle()
{
@@ -3144,7 +3183,7 @@ void LLViewerRegion::setCapabilitiesReceived(bool received)
{
mCapabilitiesReceivedSignal(getRegionID());
- //LLFloaterPermsDefault::sendInitialPerms();
+ LLFloaterPermsDefault::sendInitialPerms();
// This is a single-shot signal. Forget callbacks to save resources.
mCapabilitiesReceivedSignal.disconnect_all_slots();
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 1b226ac2c6..477aabb971 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -86,6 +86,8 @@ public:
PARTITION_GRASS,
PARTITION_VOLUME,
PARTITION_BRIDGE,
+ PARTITION_AVATAR,
+ PARTITION_CONTROL_AV, // Animesh
PARTITION_HUD_PARTICLE,
PARTITION_VO_CACHE,
PARTITION_NONE,
@@ -230,6 +232,9 @@ public:
F32 getWidth() const { return mWidth; }
+ // regions are expensive to release, this function gradually releases cache from memory
+ static void idleCleanup(F32 max_update_time);
+
void idleUpdate(F32 max_update_time);
void lightIdleUpdate();
bool addVisibleGroup(LLViewerOctreeGroup* group);
@@ -548,6 +553,9 @@ private:
LLSD mSimulatorFeatures;
+ typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t;
+ static vocache_entry_map_t sRegionCacheCleanup;
+
// the materials capability throttle
LLFrameTimer mMaterialsCapThrottleTimer;
LLFrameTimer mRenderInfoRequestTimer;
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index f108d96320..be5c22e7c3 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -400,6 +400,15 @@ void LLViewerShaderMgr::setShaders()
return;
}
+ if (!gGLManager.mHasShaderObjects
+ || !gGLManager.mHasVertexShader
+ || !gGLManager.mHasFragmentShader)
+ {
+ // Viewer will show 'hardware requirements' warning later
+ LL_INFOS("ShaderLoading") << "Shaders not supported" << LL_ENDL;
+ return;
+ }
+
static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) max_texture_index), 1);
diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp
index 7f7d190b92..c501dd0035 100644
--- a/indra/newview/llviewertexlayer.cpp
+++ b/indra/newview/llviewertexlayer.cpp
@@ -54,7 +54,7 @@ LLViewerTexLayerSetBuffer::LLViewerTexLayerSetBuffer(LLTexLayerSet* const owner,
S32 width, S32 height) :
// ORDER_LAST => must render these after the hints are created.
LLTexLayerSetBuffer(owner),
- LLViewerDynamicTexture( width, height, 4, LLViewerDynamicTexture::ORDER_LAST, TRUE ),
+ LLViewerDynamicTexture(width, height, 4, LLViewerDynamicTexture::ORDER_LAST, FALSE),
mNeedsUpdate(TRUE),
mNumLowresUpdates(0)
{
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index a2cec9a613..bd83a61e5b 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1238,6 +1238,8 @@ void LLViewerFetchedTexture::loadFromFastCache()
{
if (mBoostLevel == LLGLTexture::BOOST_ICON)
{
+ // Shouldn't do anything usefull since texures in fast cache are 16x16,
+ // it is here in case fast cache changes.
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS;
S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS;
if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
@@ -1485,7 +1487,8 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
mOrigWidth = mRawImage->getWidth();
mOrigHeight = mRawImage->getHeight();
-
+ // This is only safe because it's a local image and fetcher doesn't use raw data
+ // from local images, but this might become unsafe in case of changes to fetcher
if (mBoostLevel == BOOST_PREVIEW)
{
mRawImage->biasedScaleToPowerOfTwo(1024);
@@ -1989,6 +1992,7 @@ bool LLViewerFetchedTexture::updateFetch()
if (mRawImage.notNull()) sRawCount--;
if (mAuxRawImage.notNull()) sAuxCount--;
+ // keep in mind that fetcher still might need raw image, don't modify original
bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage,
mLastHttpGetStatus);
if (mRawImage.notNull()) sRawCount++;
@@ -2048,7 +2052,8 @@ bool LLViewerFetchedTexture::updateFetch()
if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
{
// scale oversized icon, no need to give more work to gl
- mRawImage->scale(expected_width, expected_height);
+ // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy
+ mRawImage = mRawImage->scaled(expected_width, expected_height);
}
}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 0cc1e0df06..bea4f2e4a5 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -346,6 +346,12 @@ public:
void update()
{
+ if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ clearText();
+ return;
+ }
+
static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ;
std::string wind_vel_text;
@@ -1396,6 +1402,7 @@ BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
void LLViewerWindow::handleQuit(LLWindow *window)
{
+ LL_INFOS() << "Window forced quit" << LL_ENDL;
LLAppViewer::instance()->forceQuit();
}
@@ -2316,7 +2323,7 @@ void LLViewerWindow::shutdownGL()
LLViewerWindow::~LLViewerWindow()
{
LL_INFOS() << "Destroying Window" << LL_ENDL;
- gDebugWindowProc = TRUE; // event catching, at this point it shouldn't output at all
+ gDebugWindowProc = TRUE; // event catching, disable once we figure out cause for exit crashes
destroyWindow();
delete mDebugText;
@@ -3924,12 +3931,12 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
BOOL draw_handles = TRUE;
- if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isSelfAvatarSelected())
+ if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected())
{
draw_handles = FALSE;
}
- if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move)
+ if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected())
{
draw_handles = FALSE;
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index d567623ac0..0aee4a3398 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1578,13 +1578,16 @@ void LLVOAvatar::renderCollisionVolumes()
}
}
-void LLVOAvatar::renderBones()
+void LLVOAvatar::renderBones(const std::string &selected_joint)
{
LLGLEnable blend(GL_BLEND);
avatar_joint_list_t::iterator iter = mSkeleton.begin();
- avatar_joint_list_t::iterator end = mSkeleton.end();
+ avatar_joint_list_t::iterator end = mSkeleton.end();
+ // For selected joints
+ static LLVector3 SELECTED_COLOR_OCCLUDED(1.0f, 1.0f, 0.0f);
+ static LLVector3 SELECTED_COLOR_VISIBLE(0.5f, 0.5f, 0.5f);
// For bones with position overrides defined
static LLVector3 OVERRIDE_COLOR_OCCLUDED(1.0f, 0.0f, 0.0f);
static LLVector3 OVERRIDE_COLOR_VISIBLE(0.5f, 0.5f, 0.5f);
@@ -1611,7 +1614,18 @@ void LLVOAvatar::renderBones()
LLVector3 pos;
LLUUID mesh_id;
- if (jointp->hasAttachmentPosOverride(pos,mesh_id))
+ F32 sphere_scale = SPHERE_SCALEF;
+
+ // We are in render, so it is preferable to implement selection
+ // in a different way, but since this is for debug/preview, this
+ // is low priority
+ if (jointp->getName() == selected_joint)
+ {
+ sphere_scale *= 16;
+ occ_color = SELECTED_COLOR_OCCLUDED;
+ visible_color = SELECTED_COLOR_VISIBLE;
+ }
+ else if (jointp->hasAttachmentPosOverride(pos,mesh_id))
{
occ_color = OVERRIDE_COLOR_OCCLUDED;
visible_color = OVERRIDE_COLOR_VISIBLE;
@@ -1632,7 +1646,6 @@ void LLVOAvatar::renderBones()
LLVector3 begin_pos(0,0,0);
LLVector3 end_pos(jointp->getEnd());
- F32 sphere_scale = SPHERE_SCALEF;
gGL.pushMatrix();
gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] );
@@ -2414,6 +2427,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid)
}
static LLTrace::BlockTimerStatHandle FTM_AVATAR_UPDATE("Avatar Update");
+static LLTrace::BlockTimerStatHandle FTM_AVATAR_UPDATE_COMPLEXITY("Avatar Update Complexity");
static LLTrace::BlockTimerStatHandle FTM_JOINT_UPDATE("Update Joints");
//------------------------------------------------------------------------
@@ -2456,14 +2470,13 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
return;
}
- if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))
+ if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))
&& !(gSavedSettings.getBOOL("DisableAllRenderTypes")) && !isSelf())
{
return;
}
// Update should be happening max once per frame.
- const S32 upd_freq = 4; // force update every upd_freq frames.
if ((mLastAnimExtents[0]==LLVector3())||
(mLastAnimExtents[1])==LLVector3())
{
@@ -2471,6 +2484,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
}
else
{
+ const S32 upd_freq = 4; // force update every upd_freq frames.
mNeedsExtentUpdate = ((LLDrawable::getCurrentFrame()+mID.mData[0])%upd_freq==0);
}
@@ -2555,8 +2569,41 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
}
idleUpdateNameTag( mLastRootPos );
+
+ // Complexity has stale mechanics, but updates still can be very rapid
+ // so spread avatar complexity calculations over frames to lesen load from
+ // rapid updates and to make sure all avatars are not calculated at once.
+ S32 compl_upd_freq = 20;
+ if (isControlAvatar())
+ {
+ // animeshes do not (or won't) have impostors nor change outfis,
+ // no need for high frequency
+ compl_upd_freq = 100;
+ }
+ else if (mLastRezzedStatus <= 0) //cloud or init
+ {
+ compl_upd_freq = 60;
+ }
+ else if (isSelf())
+ {
+ compl_upd_freq = 5;
+ }
+ else if (mLastRezzedStatus == 1) //'grey', not fully loaded
+ {
+ compl_upd_freq = 40;
+ }
+ else if (isInMuteList()) //cheap, buffers value from search
+ {
+ compl_upd_freq = 100;
+ }
+
+ if ((LLFrameTimer::getFrameCount() + mID.mData[0]) % compl_upd_freq == 0)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_AVATAR_UPDATE_COMPLEXITY);
idleUpdateRenderComplexity();
}
+ idleUpdateDebugInfo();
+}
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
{
@@ -2866,7 +2913,10 @@ F32 LLVOAvatar::calcMorphAmount()
void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
{
// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
- if ( voice_enabled && (LLVoiceClient::getInstance()->lipSyncEnabled()) && LLVoiceClient::getInstance()->getIsSpeaking( mID ) )
+ if ( voice_enabled
+ && mLastRezzedStatus > 0 // no point updating lip-sync for clouds
+ && (LLVoiceClient::getInstance()->lipSyncEnabled())
+ && LLVoiceClient::getInstance()->getIsSpeaking( mID ) )
{
F32 ooh_morph_amount = 0.0f;
F32 aah_morph_amount = 0.0f;
@@ -3214,7 +3264,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
std::string title_str = title->getString();
LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);
addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerifSmall());
+ LLFontGL::getFontSansSerifSmall(), true);
}
static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames", true);
@@ -3234,7 +3284,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
if (show_display_names)
{
addNameTagLine(av_name.getDisplayName(), name_tag_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerif());
+ LLFontGL::getFontSansSerif(), true);
}
// Suppress SLID display if display name matches exactly (ugh)
if (show_usernames && !av_name.isDisplayNameDefault())
@@ -3242,14 +3292,14 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
// *HACK: Desaturate the color
LLColor4 username_color = name_tag_color * 0.83f;
addNameTagLine(av_name.getUserName(), username_color, LLFontGL::NORMAL,
- LLFontGL::getFontSansSerifSmall());
+ LLFontGL::getFontSansSerifSmall(), true);
}
}
else
{
const LLFontGL* font = LLFontGL::getFontSansSerif();
std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() );
- addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font);
+ addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font, true);
}
mNameAway = is_away;
@@ -3341,7 +3391,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
}
}
-void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font)
+void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses)
{
llassert(mNameText);
if (mVisibleChat)
@@ -3350,7 +3400,7 @@ void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color,
}
else
{
- mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font);
+ mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font, use_ellipses);
}
mNameIsSet |= !line.empty();
}
@@ -3900,6 +3950,11 @@ void LLVOAvatar::computeUpdatePeriod()
{ //background avatars are REALLY slow updating impostors
mUpdatePeriod = 16;
}
+ else if (mLastRezzedStatus <= 0)
+ {
+ // Don't update cloud avatars too often
+ mUpdatePeriod = 8;
+ }
else if ( shouldImpostor(3) )
{ //back 25% of max visible avatars are slow updating impostors
mUpdatePeriod = 8;
@@ -4286,15 +4341,15 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// Set mUpdatePeriod and visible based on distance and other criteria.
//--------------------------------------------------------------------
computeUpdatePeriod();
- visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE;
+ bool needs_update = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0;
//--------------------------------------------------------------------
- // Early out if not visible and not self
+ // Early out if does not need update and not self
// don't early out for your own avatar, as we rely on your animations playing reliably
// for example, the "turn around" animation when entering customize avatar needs to trigger
// even when your avatar is offscreen
//--------------------------------------------------------------------
- if (!visible && !isSelf())
+ if (!needs_update && !isSelf())
{
updateMotions(LLCharacter::HIDDEN_UPDATE);
return FALSE;
@@ -4343,12 +4398,17 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
mSpeed = speed;
// update animations
- if (mSpecialRenderMode == 1) // Animation Preview
+ if (!visible)
+ {
+ updateMotions(LLCharacter::HIDDEN_UPDATE);
+ }
+ else if (mSpecialRenderMode == 1) // Animation Preview
{
updateMotions(LLCharacter::FORCE_UPDATE);
}
else
{
+ // Might be better to do HIDDEN_UPDATE if cloud
updateMotions(LLCharacter::NORMAL_UPDATE);
}
@@ -4376,10 +4436,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// Update child joints as needed.
mRoot->updateWorldMatrixChildren();
+ if (visible)
+ {
// System avatar mesh vertices need to be reskinned.
mNeedsSkin = TRUE;
+ }
- return TRUE;
+ return visible;
}
//-----------------------------------------------------------------------------
@@ -6834,13 +6897,13 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
pipeline->allocDrawable(this);
mDrawable->setLit(FALSE);
- LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR);
+ LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*)gPipeline.getPool(mIsControlAvatar ? LLDrawPool::POOL_CONTROL_AV : LLDrawPool::POOL_AVATAR);
// Only a single face (one per avatar)
//this face will be splitted into several if its vertex buffer is too long.
mDrawable->setState(LLDrawable::ACTIVE);
mDrawable->addFace(poolp, NULL);
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR);
+ mDrawable->setRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR);
mNumInitFaces = mDrawable->getNumFaces() ;
@@ -6865,7 +6928,7 @@ static LLTrace::BlockTimerStatHandle FTM_UPDATE_AVATAR("Update Avatar");
BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
{
LL_RECORD_BLOCK_TIME(FTM_UPDATE_AVATAR);
- if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
+ if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)))
{
return TRUE;
}
@@ -10021,7 +10084,7 @@ void LLVOAvatar::onActiveOverrideMeshesChanged()
U32 LLVOAvatar::getPartitionType() const
{
// Avatars merely exist as drawables in the bridge partition
- return LLViewerRegion::PARTITION_BRIDGE;
+ return mIsControlAvatar ? LLViewerRegion::PARTITION_CONTROL_AV : LLViewerRegion::PARTITION_AVATAR;
}
//static
@@ -10142,7 +10205,10 @@ void LLVOAvatar::idleUpdateRenderComplexity()
// Render Complexity
calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed
+}
+void LLVOAvatar::idleUpdateDebugInfo()
+{
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO))
{
std::string info_line;
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index ca6ac5c902..cfb007cbc9 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -284,8 +284,9 @@ public:
static void invalidateNameTag(const LLUUID& agent_id);
// force all name tags to rebuild, useful when display names turned on/off
static void invalidateNameTags();
- void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
+ void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses = false);
void idleUpdateRenderComplexity();
+ void idleUpdateDebugInfo();
void accountRenderComplexityForObject(const LLViewerObject *attached_object,
const F32 max_attachment_complexity,
LLVOVolume::texture_cost_t& textures,
@@ -443,7 +444,7 @@ public:
F32 getLastSkinTime() { return mLastSkinTime; }
U32 renderTransparent(BOOL first_pass);
void renderCollisionVolumes();
- void renderBones();
+ void renderBones(const std::string &selected_joint = std::string());
void renderJoints();
static void deleteCachedImages(bool clearAll=true);
static void destroyGL();
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 16b27fd144..aea12380e8 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2667,11 +2667,6 @@ void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch)
{
gAgentCamera.changeCameraToCustomizeAvatar();
}
-
-#if 0
- gAgentAvatarp->clearVisualParamWeights();
- gAgentAvatarp->idleUpdateAppearanceAnimation();
-#endif
gAgentAvatarp->invalidateAll(); // mark all bakes as dirty, request updates
gAgentAvatarp->updateMeshTextures(); // make sure correct textures are applied to the avatar mesh.
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 07660ca6ac..689eeee0e3 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -347,36 +347,24 @@ void LLVOCacheEntry::dump() const
BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
{
- BOOL success;
- success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
- if(success)
- {
- success = check_write(apr_file, (void*)&mCRC, sizeof(U32));
- }
- if(success)
- {
- success = check_write(apr_file, (void*)&mHitCount, sizeof(S32));
- }
- if(success)
- {
- success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32));
- }
- if(success)
- {
- success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
- }
- if(success)
- {
- S32 size = mDP.getBufferSize();
- success = check_write(apr_file, (void*)&size, sizeof(S32));
-
- if(success)
- {
- success = check_write(apr_file, (void*)mBuffer, size);
- }
- }
-
- return success ;
+ static const S32 data_buffer_size = 6 * sizeof(S32);
+ static U8 data_buffer[data_buffer_size];
+ S32 size = mDP.getBufferSize();
+
+ memcpy(data_buffer, &mLocalID, sizeof(U32));
+ memcpy(data_buffer + sizeof(U32), &mCRC, sizeof(U32));
+ memcpy(data_buffer + (2 * sizeof(U32)), &mHitCount, sizeof(S32));
+ memcpy(data_buffer + (3 * sizeof(U32)), &mDupeCount, sizeof(S32));
+ memcpy(data_buffer + (4 * sizeof(U32)), &mCRCChangeCount, sizeof(S32));
+ memcpy(data_buffer + (5 * sizeof(U32)), &size, sizeof(S32));
+
+ BOOL success = check_write(apr_file, (void*)data_buffer, data_buffer_size);
+ if (success)
+ {
+ success = check_write(apr_file, (void*)mBuffer, size);
+ }
+
+ return success;
}
//static
@@ -1537,7 +1525,8 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
{
S32 num_entries = cache_entry_map.size() ;
success = check_write(&apr_file, &num_entries, sizeof(S32));
-
+
+ // This can have a lot of entries, so might be better to dump them into buffer first and write in one go.
for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
{
if(!removal_enabled || iter->second->isValid())
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index cc590fc947..377f3174f3 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -981,7 +981,12 @@ LLSpeakerVolumeStorage::LLSpeakerVolumeStorage()
LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage()
{
- save();
+}
+
+//virtual
+void LLSpeakerVolumeStorage::cleanupSingleton()
+{
+ save();
}
void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, F32 volume)
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 3d04e1f0db..1a4d253208 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -499,9 +499,13 @@ protected:
**/
class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage>
{
- LLSINGLETON(LLSpeakerVolumeStorage);
+ LLSINGLETON_C11(LLSpeakerVolumeStorage);
~LLSpeakerVolumeStorage();
LOG_CLASS(LLSpeakerVolumeStorage);
+
+protected:
+ virtual void cleanupSingleton() override;
+
public:
/**
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 42a1cf95a7..a8d668420e 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -274,6 +274,8 @@ static void killGateway()
///////////////////////////////////////////////////////////////////////////////////////////////
+bool LLVivoxVoiceClient::sShuttingDown = false;
+
LLVivoxVoiceClient::LLVivoxVoiceClient() :
mSessionTerminateRequested(false),
mRelogRequested(false),
@@ -381,6 +383,7 @@ LLVivoxVoiceClient::~LLVivoxVoiceClient()
{
mAvatarNameCacheConnection.disconnect();
}
+ sShuttingDown = true;
}
//---------------------------------------------------
@@ -411,8 +414,11 @@ void LLVivoxVoiceClient::terminate()
}
else
{
+ mRelogRequested = false;
killGateway();
}
+
+ sShuttingDown = true;
}
//---------------------------------------------------
@@ -660,12 +666,18 @@ void LLVivoxVoiceClient::voiceControlCoro()
U32 retry = 0;
- while (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
+ while (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && !sShuttingDown)
{
LL_DEBUGS("Voice") << "Suspending voiceControlCoro() momentarily for teleport. Tuning: " << mTuningMode << ". Relog: " << mRelogRequested << LL_ENDL;
llcoro::suspendUntilTimeout(1.0);
}
+ if (sShuttingDown)
+ {
+ mIsCoroutineActive = false;
+ return;
+ }
+
do
{
bool success = startAndConnectSession();
@@ -691,7 +703,7 @@ void LLVivoxVoiceClient::voiceControlCoro()
<< "disconnected"
<< " RelogRequested=" << mRelogRequested
<< LL_ENDL;
- if (mRelogRequested)
+ if (mRelogRequested && !sShuttingDown)
{
if (!success)
{
@@ -706,14 +718,14 @@ void LLVivoxVoiceClient::voiceControlCoro()
LL_INFOS("Voice") << "will attempt to reconnect to voice" << LL_ENDL;
}
- while (isGatewayRunning() || gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
+ while (isGatewayRunning() || (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && !sShuttingDown))
{
LL_INFOS("Voice") << "waiting for SLVoice to exit" << LL_ENDL;
llcoro::suspendUntilTimeout(1.0);
}
}
}
- while (mVoiceEnabled && mRelogRequested);
+ while (mVoiceEnabled && mRelogRequested && !sShuttingDown);
mIsCoroutineActive = false;
LL_INFOS("Voice") << "exiting" << LL_ENDL;
}
@@ -758,7 +770,7 @@ bool LLVivoxVoiceClient::endAndDisconnectSession()
bool LLVivoxVoiceClient::callbackEndDaemon(const LLSD& data)
{
- if (!LLAppViewer::isExiting() && mVoiceEnabled)
+ if (!sShuttingDown && mVoiceEnabled)
{
LL_WARNS("Voice") << "SLVoice terminated " << ll_stream_notation_sd(data) << LL_ENDL;
terminateAudioSession(false);
@@ -915,7 +927,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
LL_DEBUGS("Voice") << "Connecting to vivox daemon:" << mDaemonHost << LL_ENDL;
LLVoiceVivoxStats::getInstance()->reset();
- while (!mConnected)
+ while (!mConnected && !sShuttingDown)
{
LLVoiceVivoxStats::getInstance()->connectionAttemptStart();
LL_DEBUGS("Voice") << "Attempting to connect to vivox daemon: " << mDaemonHost << LL_ENDL;
@@ -934,6 +946,11 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
}
//---------------------------------------------------------------------
+ if (sShuttingDown && !mConnected)
+ {
+ return false;
+ }
+
llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
while (!mPump)
@@ -970,7 +987,7 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
{
LL_INFOS("Voice") << "Provisioning voice account." << LL_ENDL;
- while (!gAgent.getRegion() || !gAgent.getRegion()->capabilitiesReceived())
+ 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.
@@ -1014,10 +1031,15 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
{
provisioned = true;
}
- } while (!provisioned && retryCount <= PROVISION_RETRY_MAX);
+ } while (!provisioned && retryCount <= PROVISION_RETRY_MAX && !sShuttingDown);
+
+ if (sShuttingDown && !provisioned)
+ {
+ return false;
+ }
LLVoiceVivoxStats::getInstance()->provisionAttemptEnd(provisioned);
- if (! provisioned )
+ if (!provisioned)
{
LL_WARNS("Voice") << "Could not access voice provision cap after " << retryCount << " attempts." << LL_ENDL;
return false;
@@ -1058,6 +1080,11 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
LL_WARNS("Voice") << "cannot establish connection; enabled "<<mVoiceEnabled<<" initialized "<<mIsInitialized<<LL_ENDL;
return false;
}
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
LLSD result;
bool connected(false);
@@ -1078,7 +1105,7 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
connected = LLSD::Boolean(result["connector"]);
if (!connected)
{
- if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX)
+ if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX && !sShuttingDown)
{
F32 timeout = LLSD::Real(result["retry"]);
timeout *= retries;
@@ -1106,7 +1133,7 @@ bool LLVivoxVoiceClient::establishVoiceConnection()
LL_DEBUGS("Voice") << (connected ? "" : "not ") << "connected, "
<< (giving_up ? "" : "not ") << "giving up"
<< LL_ENDL;
- } while (!connected && !giving_up);
+ } while (!connected && !giving_up && !sShuttingDown);
if (giving_up)
{
@@ -1193,7 +1220,7 @@ bool LLVivoxVoiceClient::loginToVivox()
{
std::string loginresp = result["login"];
- if ((loginresp == "retry") || (loginresp == "timeout"))
+ if (((loginresp == "retry") || (loginresp == "timeout")) && !sShuttingDown)
{
LL_WARNS("Voice") << "login failed with status '" << loginresp << "' "
<< " count " << loginRetryCount << "/" << LOGIN_RETRY_MAX
@@ -1235,9 +1262,14 @@ bool LLVivoxVoiceClient::loginToVivox()
{
account_login = true;
}
+ else if (sShuttingDown)
+ {
+ mIsLoggingIn = false;
+ return false;
+ }
}
- } while (!response_ok || !account_login);
+ } while ((!response_ok || !account_login) && !sShuttingDown);
mRelogRequested = false;
mIsLoggedIn = true;
@@ -1690,12 +1722,12 @@ bool LLVivoxVoiceClient::terminateAudioSession(bool wait)
// the region chat.
mSessionTerminateRequested = false;
- bool status=((mVoiceEnabled || !mIsInitialized) && !mRelogRequested && !LLApp::isExiting());
+ bool status=((mVoiceEnabled || !mIsInitialized) && !mRelogRequested && !sShuttingDown);
LL_DEBUGS("Voice") << "exiting"
<< " VoiceEnabled " << mVoiceEnabled
<< " IsInitialized " << mIsInitialized
<< " RelogRequested " << mRelogRequested
- << " AppExiting " << LLApp::isExiting()
+ << " ShuttingDown " << (sShuttingDown ? "TRUE" : "FALSE")
<< " returning " << status
<< LL_ENDL;
return status;
@@ -1712,6 +1744,12 @@ bool LLVivoxVoiceClient::waitForChannel()
return false;
}
+ if (sShuttingDown)
+ {
+ logoutOfVivox(true);
+ return false;
+ }
+
if (LLVoiceClient::instance().getVoiceEffectEnabled())
{
retrieveVoiceFonts();
@@ -1733,6 +1771,12 @@ bool LLVivoxVoiceClient::waitForChannel()
mIsProcessingChannels = true;
llcoro::suspend();
+ if (sShuttingDown)
+ {
+ mRelogRequested = false;
+ break;
+ }
+
if (mTuningMode)
{
performMicTuning();
@@ -1777,7 +1821,14 @@ bool LLVivoxVoiceClient::waitForChannel()
{
llcoro::suspendUntilTimeout(1.0);
}
- } while (mVoiceEnabled && !mRelogRequested);
+
+ if (sShuttingDown)
+ {
+ mRelogRequested = false;
+ break;
+ }
+
+ } while (mVoiceEnabled && !mRelogRequested && !sShuttingDown);
LL_DEBUGS("Voice")
<< "leaving inner waitForChannel loop"
@@ -1799,14 +1850,14 @@ bool LLVivoxVoiceClient::waitForChannel()
return false;
}
}
- } while (mVoiceEnabled && mRelogRequested && isGatewayRunning());
+ } while (mVoiceEnabled && mRelogRequested && isGatewayRunning() && !sShuttingDown);
LL_DEBUGS("Voice")
<< "exiting"
<< " RelogRequested=" << mRelogRequested
<< " VoiceEnabled=" << mVoiceEnabled
<< LL_ENDL;
- return true;
+ return !sShuttingDown;
}
bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 210c726452..699c85066b 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -912,6 +912,8 @@ private:
bool mIsProcessingChannels;
bool mIsCoroutineActive;
+ static bool sShuttingDown; // corutines can last longer than vivox so we need a static variable as a shutdown flag
+
LLEventMailDrop mVivoxPump;
};
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 98eb2d3cdc..492d37edba 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -235,7 +235,8 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mLastFetchedMediaVersion = -1;
memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS);
mMDCImplCount = 0;
- mLastRiggingInfoLOD = -1;
+ mLastRiggingInfoLOD = -1;
+ mResetDebugText = false;
}
LLVOVolume::~LLVOVolume()
@@ -1391,6 +1392,15 @@ BOOL LLVOVolume::calcLOD()
{
std::string debug_object_text = get_debug_object_lod_text(this);
setDebugText(debug_object_text);
+ mResetDebugText = true;
+ }
+ }
+ else
+ {
+ if (mResetDebugText)
+ {
+ restoreHudText();
+ mResetDebugText = false;
}
}
@@ -4585,8 +4595,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
{
U8 mode = mat->getDiffuseAlphaMode();
- if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE ||
- mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
+ if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE
+ || mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE
+ || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && mat->getAlphaMaskCutoff() == 0))
{
ignore_alpha = true;
}
@@ -4892,6 +4903,14 @@ U32 LLVOVolume::getPartitionType() const
{
return LLViewerRegion::PARTITION_HUD;
}
+ if (isAnimatedObject() && getControlAvatar())
+ {
+ return LLViewerRegion::PARTITION_CONTROL_AV;
+ }
+ if (isAttachment())
+ {
+ return LLViewerRegion::PARTITION_AVATAR;
+ }
return LLViewerRegion::PARTITION_VOLUME;
}
@@ -4922,6 +4941,20 @@ LLVolumeGeometryManager()
mSlopRatio = 0.25f;
}
+LLAvatarBridge::LLAvatarBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
+ : LLVolumeBridge(drawablep, regionp)
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
+ mPartitionType = LLViewerRegion::PARTITION_AVATAR;
+}
+
+LLControlAVBridge::LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
+ : LLVolumeBridge(drawablep, regionp)
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_CONTROL_AV;
+ mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV;
+}
+
bool can_batch_texture(LLFace* facep)
{
if (facep->getTextureEntry()->getBumpmap())
@@ -5100,7 +5133,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
}
- if (index < 255 && idx >= 0)
+ if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0)
{
if (mat || draw_vec[idx]->mMaterial)
{ //can't batch textures when materials are present (yet)
@@ -5146,7 +5179,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mEnd += facep->getGeomCount();
draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
- if (index < 255 && index >= draw_vec[idx]->mTextureList.size())
+ if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= draw_vec[idx]->mTextureList.size())
{
draw_vec[idx]->mTextureList.resize(index+1);
draw_vec[idx]->mTextureList[index] = tex;
@@ -5233,7 +5266,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_info->mDrawMode = LLRender::TRIANGLE_STRIP;
}
- if (index < 255)
+ if (index < FACE_DO_NOT_BATCH_TEXTURES)
{ //initialize texture list for texture batching
draw_info->mTextureList.resize(index+1);
draw_info->mTextureList[index] = tex;
@@ -5266,7 +5299,8 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)
LLDrawPool* drawpool = face->getPool();
if (drawpool)
{
- if (drawpool->getType() == LLDrawPool::POOL_AVATAR)
+ if (drawpool->getType() == LLDrawPool::POOL_AVATAR
+ || drawpool->getType() == LLDrawPool::POOL_CONTROL_AV)
{
return (LLDrawPoolAvatar*) drawpool;
}
@@ -5545,7 +5579,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
//remove face from old pool if it exists
LLDrawPool* old_pool = facep->getPool();
- if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR)
+ if (old_pool
+ && (old_pool->getType() == LLDrawPool::POOL_AVATAR || old_pool->getType() == LLDrawPool::POOL_CONTROL_AV))
{
((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep);
}
@@ -6365,7 +6400,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
//face has no texture index
facep->mDrawInfo = NULL;
- facep->setTextureIndex(255);
+ facep->setTextureIndex(FACE_DO_NOT_BATCH_TEXTURES);
if (geom_count + facep->getGeomCount() > max_vertices)
{ //cut batches on geom count too big
@@ -6429,7 +6464,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
facep->setGeomIndex(index_offset);
facep->setVertexBuffer(buffer);
- if (batch_textures && facep->getTextureIndex() == 255)
+ if (batch_textures && facep->getTextureIndex() == FACE_DO_NOT_BATCH_TEXTURES)
{
LL_ERRS() << "Invalid texture index." << LL_ENDL;
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index de00ef494e..ce400a3498 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -424,6 +424,8 @@ private:
S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS];
S32 mMDCImplCount;
+ bool mResetDebugText;
+
LLPointer<LLRiggedVolume> mRiggedVolume;
// statics
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index ccda92810e..12def24a0d 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -145,7 +145,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
static const unsigned int vertices_per_quad = 4;
static const unsigned int indices_per_quad = 6;
- const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") && LLGLSLShader::sNoFixedFunction ? 16 : 1;
+ const S32 size = LLPipeline::sRenderTransparentWater && LLGLSLShader::sNoFixedFunction ? 16 : 1;
const S32 num_quads = size * size;
face->setSize(vertices_per_quad * num_quads,
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 368a3f2335..d428cb1568 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -99,6 +99,9 @@ LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline)
inline F32 LLVOWLSky::calcPhi(U32 i)
{
+ // Calc: PI/8 * 1-((1-t^4)*(1-t^4)) { 0<t<1 }
+ // Demos: \pi/8*\left(1-((1-x^{4})*(1-x^{4}))\right)\ \left\{0<x\le1\right\}
+
// i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f]
F32 t = float(i) / float(getNumStacks());
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index e7bbee5efd..e7f62e77b4 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -38,6 +38,7 @@
#include "llgesturemgr.h"
#include "lltransutil.h"
#include "llviewerattachmenu.h"
+#include "llviewermenu.h"
#include "llvoavatarself.h"
class LLFindOutfitItems : public LLInventoryCollectFunctor
@@ -794,7 +795,7 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu()
// Register handlers common for all wearable types.
registrar.add("Wearable.Wear", boost::bind(wear_multiple, ids, true));
registrar.add("Wearable.Add", boost::bind(wear_multiple, ids, false));
- registrar.add("Wearable.Edit", boost::bind(handleMultiple, LLAgentWearables::editWearable, ids));
+ registrar.add("Wearable.Edit", boost::bind(handle_item_edit, selected_id));
registrar.add("Wearable.CreateNew", boost::bind(createNewWearable, selected_id));
registrar.add("Wearable.ShowOriginal", boost::bind(show_item_original, selected_id));
registrar.add("Wearable.TakeOffDetach",
@@ -809,6 +810,7 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu()
// Register handlers for attachments.
registrar.add("Attachment.Detach",
boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids));
+ registrar.add("Attachment.Touch", boost::bind(handle_attachment_touch, selected_id));
registrar.add("Attachment.Profile", boost::bind(show_item_profile, selected_id));
registrar.add("Object.Attach", boost::bind(LLViewerAttachMenu::attachObjects, ids, _2));
@@ -838,6 +840,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
U32 n_already_worn = 0; // number of items worn of same type as selected items
U32 n_links = 0; // number of links among the selected items
U32 n_editable = 0; // number of editable items among the selected ones
+ U32 n_touchable = 0; // number of touchable items among the selected ones
bool can_be_worn = true;
@@ -858,12 +861,17 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
const LLWearableType::EType wearable_type = item->getWearableType();
const bool is_link = item->getIsLinkType();
const bool is_worn = get_is_item_worn(id);
- const bool is_editable = gAgentWearables.isWearableModifiable(id);
+ const bool is_editable = get_is_item_editable(id);
+ const bool is_touchable = enable_attachment_touch(id);
const bool is_already_worn = gAgentWearables.selfHasWearable(wearable_type);
if (is_worn)
{
++n_worn;
}
+ if (is_touchable)
+ {
+ ++n_touchable;
+ }
if (is_editable)
{
++n_editable;
@@ -893,8 +901,10 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
setMenuItemEnabled(menu, "wear_add", LLAppearanceMgr::instance().canAddWearables(ids));
setMenuItemVisible(menu, "wear_replace", n_worn == 0 && n_already_worn != 0 && can_be_worn);
//visible only when one item selected and this item is worn
- setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1);
- setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1);
+ setMenuItemVisible(menu, "touch", !standalone && mask == MASK_ATTACHMENT && n_worn == n_items);
+ setMenuItemEnabled(menu, "touch", n_touchable && n_worn == 1 && n_items == 1);
+ setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART|MASK_ATTACHMENT) && n_worn == n_items);
+ setMenuItemEnabled(menu, "edit", n_editable && n_worn == 1 && n_items == 1);
setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1);
setMenuItemEnabled(menu, "create_new", LLAppearanceMgr::instance().canAddWearables(ids));
setMenuItemVisible(menu, "show_original", !standalone);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 8989bae96a..a1a1db35d6 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -730,11 +730,20 @@ void LLWorld::updateRegions(F32 max_update_time)
{
//perform some necessary but very light updates.
(*iter)->lightIdleUpdate();
- }
+ }
+ }
+
+ if(max_time > 0.f)
+ {
+ max_time = llmin((F32)(max_update_time - update_timer.getElapsedTimeF32()), max_update_time * 0.25f);
+ }
+ if(max_time > 0.f)
+ {
+ LLViewerRegion::idleCleanup(max_time);
}
sample(sNumActiveCachedObjects, mNumOfActiveCachedObjects);
- }
+}
void LLWorld::clearAllVisibleObjects()
{
@@ -1208,11 +1217,14 @@ public:
}
};
+static LLTrace::BlockTimerStatHandle FTM_DISABLE_REGION("Disable Region");
// disable the circuit to this simulator
// Called in response to "DisableSimulator" message.
void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
-{
- LLHost host = mesgsys->getSender();
+{
+ LL_RECORD_BLOCK_TIME(FTM_DISABLE_REGION);
+
+ LLHost host = mesgsys->getSender();
//LL_INFOS() << "Disabling simulator with message from " << host << LL_ENDL;
LLWorld::getInstance()->removeRegion(host);
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 8e2539606b..32c8ce66a0 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -240,16 +240,16 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
if (!status)
{
+ mImpl->setHttpStatus(status);
+ LLSD errordata = status.getErrorData();
+ mImpl->mErrorCertData = errordata;
+
if ((status.toULong() != CURLE_SSL_PEER_CERTIFICATE) &&
(status.toULong() != CURLE_SSL_CACERT))
{
// if we have a curl error that's not already been handled
- // (a non cert error), then generate the error message as
+ // (a non cert error), then generate the warning message as
// appropriate
- mImpl->setHttpStatus(status);
- LLSD errordata = status.getErrorData();
- mImpl->mErrorCertData = errordata;
-
LL_WARNS() << "LLXMLRPCTransaction error "
<< status.toHex() << ": " << status.toString() << LL_ENDL;
LL_WARNS() << "LLXMLRPCTransaction request URI: "
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 01438bfb9f..644934d1d8 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -329,6 +329,7 @@ bool LLPipeline::sDelayVBUpdate = true;
bool LLPipeline::sAutoMaskAlphaDeferred = true;
bool LLPipeline::sAutoMaskAlphaNonDeferred = false;
bool LLPipeline::sDisableShaders = false;
+bool LLPipeline::sRenderTransparentWater = true;
bool LLPipeline::sRenderBump = true;
bool LLPipeline::sBakeSunlight = false;
bool LLPipeline::sNoAlpha = false;
@@ -1044,30 +1045,31 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
}
//static
+void LLPipeline::updateRenderTransparentWater()
+{
+ sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater");
+}
+
+//static
void LLPipeline::updateRenderBump()
{
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
}
-//static
+// static
void LLPipeline::updateRenderDeferred()
{
- bool deferred = (bool(RenderDeferred &&
- LLRenderTarget::sUseFBO &&
- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
- LLPipeline::sRenderBump &&
- RenderAvatarVP &&
- WindLightUseAtmosShaders)) &&
- !gUseWireframe;
-
- sRenderDeferred = deferred;
- if (deferred)
- { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all
- sRenderGlow = true;
- }
+ sRenderDeferred = !gUseWireframe &&
+ RenderDeferred &&
+ LLRenderTarget::sUseFBO &&
+ LLPipeline::sRenderBump &&
+ LLPipeline::sRenderTransparentWater &&
+ RenderAvatarVP &&
+ WindLightUseAtmosShaders &&
+ (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
}
-//static
+// static
void LLPipeline::refreshCachedSettings()
{
LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
@@ -1259,24 +1261,20 @@ void LLPipeline::createGLBuffers()
GLuint resX = gViewerWindow->getWorldViewWidthRaw();
GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-
- if (LLPipeline::sRenderGlow)
- { //screen space glow buffers
- const U32 glow_res = llmax(1,
- llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
- for (U32 i = 0; i < 3; i++)
- {
- mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
- }
+ // allocate screen space glow buffers
+ const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
+ for (U32 i = 0; i < 3; i++)
+ {
+ mGlow[i].allocate(512, glow_res, GL_RGBA, FALSE, FALSE);
+ }
- allocateScreenBuffer(resX,resY);
- mScreenWidth = 0;
- mScreenHeight = 0;
- }
-
- if (sRenderDeferred)
- {
+ allocateScreenBuffer(resX, resY);
+ mScreenWidth = 0;
+ mScreenHeight = 0;
+
+ if (sRenderDeferred)
+ {
if (!mNoiseMap)
{
const U32 noiseRes = 128;
@@ -1609,6 +1607,7 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
break;
case LLDrawPool::POOL_AVATAR:
+ case LLDrawPool::POOL_CONTROL_AV:
break; // Do nothing
case LLDrawPool::POOL_SKY:
@@ -1995,7 +1994,7 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
if (done)
{
- if (drawablep->isRoot())
+ if (drawablep->isRoot() && !drawablep->isState(LLDrawable::ACTIVE))
{
drawablep->makeStatic();
}
@@ -3362,6 +3361,7 @@ static LLTrace::BlockTimerStatHandle FTM_RESET_DRAWORDER("Reset Draw Order");
void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
{
if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
LLPipeline::RENDER_TYPE_GROUND,
LLPipeline::RENDER_TYPE_TERRAIN,
LLPipeline::RENDER_TYPE_TREE,
@@ -5774,6 +5774,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
break;
case LLDrawPool::POOL_AVATAR:
+ case LLDrawPool::POOL_CONTROL_AV:
break; // Do nothing
case LLDrawPool::POOL_SKY:
@@ -5922,6 +5923,7 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
break;
case LLDrawPool::POOL_AVATAR:
+ case LLDrawPool::POOL_CONTROL_AV:
break; // Do nothing
case LLDrawPool::POOL_SKY:
@@ -6059,25 +6061,18 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_
{
return max_dist;
}
- F32 radius = light->getLightRadius();
bool selected = light->isSelected();
- LLVector3 dpos = light->getRenderPosition() - cam_pos;
- F32 dist2 = dpos.lengthSquared();
- if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
- {
- return max_dist;
- }
- F32 dist = (F32) sqrt(dist2);
- dist *= 1.f / inten;
- dist -= radius;
if (selected)
{
- dist -= 10000.f; // selected lights get highest priority
+ return 0.f; // selected lights get highest priority
}
+ F32 radius = light->getLightRadius();
+ F32 dist = dist_vec(light->getRenderPosition(), cam_pos);
+ dist = llmax(dist - radius, 0.f);
if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
{
// moving lights get a little higher priority (too much causes artifacts)
- dist -= light->getLightRadius()*0.25f;
+ dist = llmax(dist - light->getLightRadius()*0.25f, 0.f);
}
return dist;
}
@@ -6096,13 +6091,18 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
// mNearbyLight (and all light_set_t's) are sorted such that
// begin() == the closest light and rbegin() == the farthest light
const S32 MAX_LOCAL_LIGHTS = 6;
-// LLVector3 cam_pos = gAgent.getCameraPositionAgent();
- LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
- camera.getOrigin() :
- gAgent.getPositionAgent();
-
- F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
+ LLVector3 cam_pos = camera.getOrigin();
+ F32 max_dist;
+ if (LLPipeline::sRenderDeferred)
+ {
+ max_dist = RenderFarClip;
+ }
+ else
+ {
+ max_dist = llmin(RenderFarClip, LIGHT_MAX_RADIUS * 4.f);
+ }
+
// UPDATE THE EXISTING NEARBY LIGHTS
light_set_t cur_nearby_lights;
for (light_set_t::iterator iter = mNearbyLights.begin();
@@ -6136,8 +6136,38 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
continue;
}
- F32 dist = calc_light_dist(volight, cam_pos, max_dist);
- cur_nearby_lights.insert(Light(drawable, dist, light->fade));
+ F32 dist = calc_light_dist(volight, cam_pos, max_dist);
+ F32 fade = light->fade;
+ // actual fade gets decreased/increased by setupHWLights
+ // light->fade value is 'time'.
+ // >=0 and light will become visible as value increases
+ // <0 and light will fade out
+ if (dist < max_dist)
+ {
+ if (fade < 0)
+ {
+ // mark light to fade in
+ // if fade was -LIGHT_FADE_TIME - it was fully invisible
+ // if fade -0 - it was fully visible
+ // visibility goes up from 0 to LIGHT_FADE_TIME.
+ fade += LIGHT_FADE_TIME;
+ }
+ }
+ else
+ {
+ // mark light to fade out
+ // visibility goes down from -0 to -LIGHT_FADE_TIME.
+ if (fade >= LIGHT_FADE_TIME)
+ {
+ fade = -0.0001f; // was fully visible
+ }
+ else if (fade >= 0)
+ {
+ // 0.75 visible light should stay 0.75 visible, but should reverse direction
+ fade -= LIGHT_FADE_TIME;
+ }
+ }
+ cur_nearby_lights.insert(Light(drawable, dist, fade));
}
mNearbyLights = cur_nearby_lights;
@@ -6156,17 +6186,23 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
{
continue; // no lighting from HUD objects
}
- F32 dist = calc_light_dist(light, cam_pos, max_dist);
- if (dist >= max_dist)
+ if (!sRenderAttachedLights && light && light->isAttachment())
{
continue;
}
- if (!sRenderAttachedLights && light && light->isAttachment())
+ LLVOAvatar * av = light->getAvatar();
+ if (av && (av->isTooComplex() || av->isInMuteList()))
+ {
+ // avatars that are already in the list will be removed by removeMutedAVsLights
+ continue;
+ }
+ F32 dist = calc_light_dist(light, cam_pos, max_dist);
+ if (dist >= max_dist)
{
continue;
}
new_nearby_lights.insert(Light(drawable, dist, 0.f));
- if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
+ if (!LLPipeline::sRenderDeferred && new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
{
new_nearby_lights.erase(--new_nearby_lights.end());
const Light& last = *new_nearby_lights.rbegin();
@@ -6179,7 +6215,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
iter != new_nearby_lights.end(); iter++)
{
const Light* light = &(*iter);
- if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
+ if (LLPipeline::sRenderDeferred || mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
{
mNearbyLights.insert(*light);
((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
@@ -6192,10 +6228,22 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
Light* farthest_light = (const_cast<Light*>(&(*(mNearbyLights.rbegin()))));
if (light->dist < farthest_light->dist)
{
- if (farthest_light->fade >= 0.f)
- {
- farthest_light->fade = -(gFrameIntervalSeconds.value());
- }
+ // mark light to fade out
+ // visibility goes down from -0 to -LIGHT_FADE_TIME.
+ //
+ // This is a mess, but for now it needs to be in sync
+ // with fade code above. Ex: code above detects distance < max,
+ // sets fade time to positive, this code then detects closer
+ // lights and sets fade time negative, fully compensating
+ // for the code above
+ if (farthest_light->fade >= LIGHT_FADE_TIME)
+ {
+ farthest_light->fade = -0.0001f; // was fully visible
+ }
+ else if (farthest_light->fade >= 0)
+ {
+ farthest_light->fade -= LIGHT_FADE_TIME;
+ }
}
else
{
@@ -6315,12 +6363,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
}
}
- const LLViewerObject *vobj = drawable->getVObj();
- if(vobj && vobj->getAvatar() && vobj->getAvatar()->isInMuteList())
- {
- continue;
- }
-
if (drawable->isState(LLDrawable::ACTIVE))
{
mLightMovingMask |= (1<<cur_light);
@@ -6427,41 +6469,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
light->setAmbient(LLColor4::black);
light->setSpecular(LLColor4::black);
}
- if (gAgentAvatarp &&
- gAgentAvatarp->mSpecialRenderMode == 3)
- {
- LLColor4 light_color = LLColor4::white;
- light_color.mV[3] = 0.0f;
-
- LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
- LLVector4 light_pos_gl(light_pos, 1.0f);
- F32 light_radius = 16.f;
-
- F32 x = 3.f;
- float linatten = x / (light_radius); // % of brightness at radius
-
- if (LLPipeline::sRenderDeferred)
- {
- /*light_color.mV[0] = powf(light_color.mV[0], 2.2f);
- light_color.mV[1] = powf(light_color.mV[1], 2.2f);
- light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/
- }
-
- mHWLightColors[2] = light_color;
- LLLightState* light = gGL.getLight(2);
-
- light->setPosition(light_pos_gl);
- light->setDiffuse(light_color);
- light->setDiffuseB(light_color * 0.25f);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- light->setQuadraticAttenuation(0.f);
- light->setConstantAttenuation(0.f);
- light->setLinearAttenuation(linatten);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
- }
+ // Bookmark comment to allow searching for mSpecialRenderMode == 3 (avatar edit mode),
+ // prev site of forward (non-deferred) character light injection, removed by SL-13522 09/20
// Init GL state
if (!LLGLSLShader::sNoFixedFunction)
@@ -6600,7 +6610,7 @@ void LLPipeline::enableLightsPreview()
light->enable();
light->setPosition(light_pos);
light->setDiffuse(diffuse0);
- light->setAmbient(LLColor4::black);
+ light->setAmbient(ambient);
light->setSpecular(specular0);
light->setSpotExponent(0.f);
light->setSpotCutoff(180.f);
@@ -6611,7 +6621,7 @@ void LLPipeline::enableLightsPreview()
light->enable();
light->setPosition(light_pos);
light->setDiffuse(diffuse1);
- light->setAmbient(LLColor4::black);
+ light->setAmbient(ambient);
light->setSpecular(specular1);
light->setSpotExponent(0.f);
light->setSpotCutoff(180.f);
@@ -6621,7 +6631,7 @@ void LLPipeline::enableLightsPreview()
light->enable();
light->setPosition(light_pos);
light->setDiffuse(diffuse2);
- light->setAmbient(LLColor4::black);
+ light->setAmbient(ambient);
light->setSpecular(specular2);
light->setSpotExponent(0.f);
light->setSpotCutoff(180.f);
@@ -7151,7 +7161,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
{
if ((j == LLViewerRegion::PARTITION_VOLUME) ||
- (j == LLViewerRegion::PARTITION_BRIDGE) ||
+ (j == LLViewerRegion::PARTITION_BRIDGE) ||
+ (j == LLViewerRegion::PARTITION_CONTROL_AV) ||
(j == LLViewerRegion::PARTITION_TERRAIN) ||
(j == LLViewerRegion::PARTITION_TREE) ||
(j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now
@@ -7213,7 +7224,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
{
LLViewerRegion* region = *iter;
- LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+ LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR);
if (part && hasRenderType(part->mDrawableType))
{
LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
@@ -7539,641 +7550,633 @@ void LLPipeline::bindScreenToTexture()
static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom");
-void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
+void LLPipeline::renderFinalize()
{
- if (!(gPipeline.canUseVertexShaders() &&
- sRenderGlow))
- {
- return;
- }
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
+ assertInitialized();
- assertInitialized();
+ if (gUseWireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
- if (gUseWireframe)
- {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
+ LLVector2 tc1(0, 0);
+ LLVector2 tc2((F32) mScreen.getWidth() * 2, (F32) mScreen.getHeight() * 2);
- LLVector2 tc1(0,0);
- LLVector2 tc2((F32) mScreen.getWidth()*2,
- (F32) mScreen.getHeight()*2);
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
+ gGL.color4f(1, 1, 1, 1);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable cull(GL_CULL_FACE);
- LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
- gGL.color4f(1,1,1,1);
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable cull(GL_CULL_FACE);
-
- enableLightsFullbright();
+ enableLightsFullbright();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
- LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDisable test(GL_ALPHA_TEST);
- gGL.setColorMask(true, true);
- glClearColor(0,0,0,0);
-
- {
- {
- LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
- mGlow[2].bindTarget();
- mGlow[2].clear();
- }
-
- gGlowExtractProgram.bind();
- F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
- F32 maxAlpha = RenderGlowMaxExtractAlpha;
- F32 warmthAmount = RenderGlowWarmthAmount;
- LLVector3 lumWeights = RenderGlowLumWeights;
- LLVector3 warmthWeights = RenderGlowWarmthWeights;
-
-
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
- gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
- gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
- LLGLEnable blend_on(GL_BLEND);
- LLGLEnable test(GL_ALPHA_TEST);
-
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-
- mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
-
- gGL.color4f(1,1,1,1);
- gPipeline.enableLightsFullbright();
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+ gGL.setColorMask(true, true);
+ glClearColor(0, 0, 0, 0);
- mGlow[2].flush();
- }
+ if (sRenderGlow)
+ {
+ {
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
+ mGlow[2].bindTarget();
+ mGlow[2].clear();
+ }
- tc1.setVec(0,0);
- tc2.setVec(2,2);
+ gGlowExtractProgram.bind();
+ F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
+ F32 maxAlpha = RenderGlowMaxExtractAlpha;
+ F32 warmthAmount = RenderGlowWarmthAmount;
+ LLVector3 lumWeights = RenderGlowLumWeights;
+ LLVector3 warmthWeights = RenderGlowWarmthWeights;
+
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
+ gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1],
+ lumWeights.mV[2]);
+ gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1],
+ warmthWeights.mV[2]);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
+
+ {
+ LLGLEnable blend_on(GL_BLEND);
+ LLGLEnable test(GL_ALPHA_TEST);
- // power of two between 1 and 1024
- U32 glowResPow = RenderGlowResolutionPow;
- const U32 glow_res = llmax(1,
- llmin(1024, 1 << glowResPow));
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- S32 kernel = RenderGlowIterations*2;
- F32 delta = RenderGlowWidth / glow_res;
- // Use half the glow width if we have the res set to less than 9 so that it looks
- // almost the same in either case.
- if (glowResPow < 9)
- {
- delta *= 0.5f;
- }
- F32 strength = RenderGlowStrength;
+ mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
- gGlowProgram.bind();
- gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
+ gGL.color4f(1, 1, 1, 1);
+ gPipeline.enableLightsFullbright();
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- for (S32 i = 0; i < kernel; i++)
- {
- {
- LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
- mGlow[i%2].bindTarget();
- mGlow[i%2].clear();
- }
-
- if (i == 0)
- {
- gGL.getTexUnit(0)->bind(&mGlow[2]);
- }
- else
- {
- gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
- }
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- if (i%2 == 0)
- {
- gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
- }
- else
- {
- gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
- }
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- mGlow[i%2].flush();
- }
+ gGL.end();
- gGlowProgram.unbind();
+ gGL.getTexUnit(0)->unbind(mScreen.getUsage());
- /*if (LLRenderTarget::sUseFBO)
- {
- LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- }*/
+ mGlow[2].flush();
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ tc1.setVec(0, 0);
+ tc2.setVec(2, 2);
+ }
- tc2.setVec((F32) mScreen.getWidth(),
- (F32) mScreen.getHeight());
+ // power of two between 1 and 1024
+ U32 glowResPow = RenderGlowResolutionPow;
+ const U32 glow_res = llmax(1, llmin(1024, 1 << glowResPow));
- gGL.flush();
-
- LLVertexBuffer::unbind();
+ S32 kernel = RenderGlowIterations * 2;
+ F32 delta = RenderGlowWidth / glow_res;
+ // Use half the glow width if we have the res set to less than 9 so that it looks
+ // almost the same in either case.
+ if (glowResPow < 9)
+ {
+ delta *= 0.5f;
+ }
+ F32 strength = RenderGlowStrength;
- if (LLPipeline::sRenderDeferred)
- {
+ gGlowProgram.bind();
+ gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
- bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
- (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
- RenderDepthOfField;
+ for (S32 i = 0; i < kernel; i++)
+ {
+ {
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
+ mGlow[i % 2].bindTarget();
+ mGlow[i % 2].clear();
+ }
+ if (i == 0)
+ {
+ gGL.getTexUnit(0)->bind(&mGlow[2]);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(&mGlow[(i - 1) % 2]);
+ }
- bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+ if (i % 2 == 0)
+ {
+ gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
+ }
+ else
+ {
+ gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
+ }
- gViewerWindow->setup3DViewport();
-
- if (dof_enabled)
- {
- LLGLSLShader* shader = &gDeferredPostProgram;
- LLGLDisable blend(GL_BLEND);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- //depth of field focal plane calculations
- static F32 current_distance = 16.f;
- static F32 start_distance = 16.f;
- static F32 transition_time = 1.f;
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- LLVector3 focus_point;
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
- if (obj && obj->mDrawable && obj->isSelected())
- { //focus on selected media object
- S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
- if (obj && obj->mDrawable)
- {
- LLFace* face = obj->mDrawable->getFace(face_idx);
- if (face)
- {
- focus_point = face->getPositionAgent();
- }
- }
- }
-
- if (focus_point.isExactlyZero())
- {
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
- { //focus on point under cursor
- focus_point.set(gDebugRaycastIntersection.getF32ptr());
- }
- else if (gAgentCamera.cameraMouselook())
- { //focus on point under mouselook crosshairs
- LLVector4a result;
- result.clear();
+ gGL.end();
- gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE,
- NULL,
- &result);
+ mGlow[i % 2].flush();
+ }
- focus_point.set(result.getF32ptr());
- }
- else
- {
- //focus on alt-zoom target
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal());
- }
- }
- }
+ gGlowProgram.unbind();
+ }
+ else // !sRenderGlow, skip the glow ping-pong and just clear the result target
+ {
+ mGlow[1].bindTarget();
+ mGlow[1].clear();
+ mGlow[1].flush();
+ }
- LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
- F32 target_distance = 16.f;
- if (!focus_point.isExactlyZero())
- {
- target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
- }
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- if (transition_time >= 1.f &&
- fabsf(current_distance-target_distance)/current_distance > 0.01f)
- { //large shift happened, interpolate smoothly to new target distance
- transition_time = 0.f;
- start_distance = current_distance;
- }
- else if (transition_time < 1.f)
- { //currently in a transition, continue interpolating
- transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds.value();
- transition_time = llmin(transition_time, 1.f);
+ tc2.setVec((F32) mScreen.getWidth(), (F32) mScreen.getHeight());
- F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
- current_distance = start_distance + (target_distance-start_distance)*t;
- }
- else
- { //small or no change, just snap to target distance
- current_distance = target_distance;
- }
+ gGL.flush();
- //convert to mm
- F32 subject_distance = current_distance*1000.f;
- F32 fnumber = CameraFNumber;
- F32 default_focal_length = CameraFocalLength;
+ LLVertexBuffer::unbind();
- F32 fov = LLViewerCamera::getInstance()->getView();
-
- const F32 default_fov = CameraFieldOfView * F_PI/180.f;
-
- //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
-
- F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
+ if (LLPipeline::sRenderDeferred)
+ {
- F32 focal_length = dv/(2*tanf(fov/2.f));
-
- //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
-
- // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
- // where N = fnumber
- // s2 = dot distance
- // s1 = subject distance
- // f = focal length
- //
+ bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
+ (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
+ RenderDepthOfField;
- F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
- blur_constant /= 1000.f; //convert to meters for shader
- F32 magnification = focal_length/(subject_distance-focal_length);
+ bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
- { //build diffuse+bloom+CoF
- mDeferredLight.bindTarget();
- shader = &gDeferredCoFProgram;
+ gViewerWindow->setup3DViewport();
- bindDeferredShader(*shader);
+ if (dof_enabled)
+ {
+ LLGLSLShader *shader = &gDeferredPostProgram;
+ LLGLDisable blend(GL_BLEND);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
+ // depth of field focal plane calculations
+ static F32 current_distance = 16.f;
+ static F32 start_distance = 16.f;
+ static F32 transition_time = 1.f;
- shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
- shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
- shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
- shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+ LLVector3 focus_point;
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
+ LLViewerObject *obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+ if (obj && obj->mDrawable && obj->isSelected())
+ { // focus on selected media object
+ S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+ if (obj && obj->mDrawable)
+ {
+ LLFace *face = obj->mDrawable->getFace(face_idx);
+ if (face)
+ {
+ focus_point = face->getPositionAgent();
+ }
+ }
+ }
- unbindDeferredShader(*shader);
- mDeferredLight.flush();
- }
+ if (focus_point.isExactlyZero())
+ {
+ if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ { // focus on point under cursor
+ focus_point.set(gDebugRaycastIntersection.getF32ptr());
+ }
+ else if (gAgentCamera.cameraMouselook())
+ { // focus on point under mouselook crosshairs
+ LLVector4a result;
+ result.clear();
- U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale);
- U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale);
-
- { //perform DoF sampling at half-res (preserve alpha channel)
- mScreen.bindTarget();
- glViewport(0,0, dof_width, dof_height);
- gGL.setColorMask(true, false);
+ gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
- shader = &gDeferredPostProgram;
- bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- if (channel > -1)
- {
- mDeferredLight.bindTexture(0, channel);
- }
+ focus_point.set(result.getF32ptr());
+ }
+ else
+ {
+ // focus on alt-zoom target
+ LLViewerRegion *region = gAgent.getRegion();
+ if (region)
+ {
+ focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
+ }
+ }
+ }
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
+ LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+ F32 target_distance = 16.f;
+ if (!focus_point.isExactlyZero())
+ {
+ target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye);
+ }
- unbindDeferredShader(*shader);
- mScreen.flush();
- gGL.setColorMask(true, true);
- }
-
- { //combine result based on alpha
- if (multisample)
- {
- mDeferredLight.bindTarget();
- glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
- }
- else
- {
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- }
+ if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f)
+ { // large shift happened, interpolate smoothly to new target distance
+ transition_time = 0.f;
+ start_distance = current_distance;
+ }
+ else if (transition_time < 1.f)
+ { // currently in a transition, continue interpolating
+ transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value();
+ transition_time = llmin(transition_time, 1.f);
- shader = &gDeferredDoFCombineProgram;
- bindDeferredShader(*shader);
-
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
+ F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f;
+ current_distance = start_distance + (target_distance - start_distance) * t;
+ }
+ else
+ { // small or no change, just snap to target distance
+ current_distance = target_distance;
+ }
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
- shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1);
- shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1);
+ // convert to mm
+ F32 subject_distance = current_distance * 1000.f;
+ F32 fnumber = CameraFNumber;
+ F32 default_focal_length = CameraFocalLength;
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
+ F32 fov = LLViewerCamera::getInstance()->getView();
- unbindDeferredShader(*shader);
+ const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
- if (multisample)
- {
- mDeferredLight.flush();
- }
- }
- }
- else
- {
- if (multisample)
- {
- mDeferredLight.bindTarget();
- }
- LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
-
- bindDeferredShader(*shader);
-
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
+ // F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
+ F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
- unbindDeferredShader(*shader);
+ F32 focal_length = dv / (2 * tanf(fov / 2.f));
- if (multisample)
- {
- mDeferredLight.flush();
- }
- }
+ // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
- if (multisample)
- {
- //bake out texture2D with RGBL for FXAA shader
- mFXAABuffer.bindTarget();
-
- S32 width = mScreen.getWidth();
- S32 height = mScreen.getHeight();
- glViewport(0, 0, width, height);
+ // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+ // where N = fnumber
+ // s2 = dot distance
+ // s1 = subject distance
+ // f = focal length
+ //
- LLGLSLShader* shader = &gGlowCombineFXAAProgram;
+ F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length));
+ blur_constant /= 1000.f; // convert to meters for shader
+ F32 magnification = focal_length / (subject_distance - focal_length);
- shader->bind();
- shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+ { // build diffuse+bloom+CoF
+ mDeferredLight.bindTarget();
+ shader = &gDeferredCoFProgram;
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- if (channel > -1)
- {
- mDeferredLight.bindTexture(0, channel);
- }
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex2f(-1,-1);
- gGL.vertex2f(-1,3);
- gGL.vertex2f(3,-1);
- gGL.end();
+ bindDeferredShader(*shader);
- gGL.flush();
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
- shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- shader->unbind();
-
- mFXAABuffer.flush();
+ shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
+ shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+ shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
+ shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
- shader = &gFXAAProgram;
- shader->bind();
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
- if (channel > -1)
- {
- mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
- }
-
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
- F32 scale_x = (F32) width/mFXAABuffer.getWidth();
- F32 scale_y = (F32) height/mFXAABuffer.getHeight();
- shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
- shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y);
- shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y);
- shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex2f(-1,-1);
- gGL.vertex2f(-1,3);
- gGL.vertex2f(3,-1);
- gGL.end();
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- gGL.flush();
- shader->unbind();
- }
- }
- else
- {
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
- buff->allocateBuffer(3,0,TRUE);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- LLStrider<LLVector3> v;
- LLStrider<LLVector2> uv1;
- LLStrider<LLVector2> uv2;
+ gGL.end();
- buff->getVertexStrider(v);
- buff->getTexCoord0Strider(uv1);
- buff->getTexCoord1Strider(uv2);
-
- uv1[0] = LLVector2(0, 0);
- uv1[1] = LLVector2(0, 2);
- uv1[2] = LLVector2(2, 0);
-
- uv2[0] = LLVector2(0, 0);
- uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
- uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
-
- v[0] = LLVector3(-1,-1,0);
- v[1] = LLVector3(-1,3,0);
- v[2] = LLVector3(3,-1,0);
-
- buff->flush();
+ unbindDeferredShader(*shader);
+ mDeferredLight.flush();
+ }
- LLGLDisable blend(GL_BLEND);
+ U32 dof_width = (U32)(mScreen.getWidth() * CameraDoFResScale);
+ U32 dof_height = (U32)(mScreen.getHeight() * CameraDoFResScale);
- if (LLGLSLShader::sNoFixedFunction)
- {
- gGlowCombineProgram.bind();
- }
- else
- {
- //tex unit 0
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
- //tex unit 1
- gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
- }
-
- gGL.getTexUnit(0)->bind(&mGlow[1]);
- gGL.getTexUnit(1)->bind(&mScreen);
-
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- buff->setBuffer(mask);
- buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gGlowCombineProgram.unbind();
- }
- else
- {
- gGL.getTexUnit(1)->disable();
- gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+ { // perform DoF sampling at half-res (preserve alpha channel)
+ mScreen.bindTarget();
+ glViewport(0, 0, dof_width, dof_height);
+ gGL.setColorMask(true, false);
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
- }
-
- }
+ shader = &gDeferredPostProgram;
+ bindDeferredShader(*shader);
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ if (channel > -1)
+ {
+ mDeferredLight.bindTexture(0, channel);
+ }
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
- if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
- {
- if (LLGLSLShader::sNoFixedFunction)
- {
- gSplatTextureRectProgram.bind();
- }
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- gGL.setColorMask(true, false);
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
- LLVector2 tc1(0,0);
- LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
- (F32) gViewerWindow->getWorldViewHeightRaw()*2);
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
- LLGLEnable blend(GL_BLEND);
- gGL.color4f(1,1,1,0.75f);
+ gGL.end();
- gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+ unbindDeferredShader(*shader);
+ mScreen.flush();
+ gGL.setColorMask(true, true);
+ }
- gGL.begin(LLRender::TRIANGLES);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
- gGL.flush();
+ { // combine result based on alpha
+ if (multisample)
+ {
+ mDeferredLight.bindTarget();
+ glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+ }
+ else
+ {
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ }
- if (LLGLSLShader::sNoFixedFunction)
- {
- gSplatTextureRectProgram.unbind();
- }
- }
+ shader = &gDeferredDoFCombineProgram;
+ bindDeferredShader(*shader);
-
- if (LLRenderTarget::sUseFBO)
- { //copy depth buffer from mScreen to framebuffer
- LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
- 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
- }
-
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+ shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width - 1);
+ shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height - 1);
- LLVertexBuffer::unbind();
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
+
+ if (multisample)
+ {
+ mDeferredLight.flush();
+ }
+ }
+ }
+ else
+ {
+ if (multisample)
+ {
+ mDeferredLight.bindTarget();
+ }
+ LLGLSLShader *shader = &gDeferredPostNoDoFProgram;
+
+ bindDeferredShader(*shader);
+
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
+
+ if (multisample)
+ {
+ mDeferredLight.flush();
+ }
+ }
+
+ if (multisample)
+ {
+ // bake out texture2D with RGBL for FXAA shader
+ mFXAABuffer.bindTarget();
+
+ S32 width = mScreen.getWidth();
+ S32 height = mScreen.getHeight();
+ glViewport(0, 0, width, height);
+
+ LLGLSLShader *shader = &gGlowCombineFXAAProgram;
+
+ shader->bind();
+ shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ if (channel > -1)
+ {
+ mDeferredLight.bindTexture(0, channel);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex2f(-1, -1);
+ gGL.vertex2f(-1, 3);
+ gGL.vertex2f(3, -1);
+ gGL.end();
+
+ gGL.flush();
+
+ shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ shader->unbind();
+
+ mFXAABuffer.flush();
+
+ shader = &gFXAAProgram;
+ shader->bind();
+
+ channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+ if (channel > -1)
+ {
+ mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+ }
+
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+ F32 scale_x = (F32) width / mFXAABuffer.getWidth();
+ F32 scale_y = (F32) height / mFXAABuffer.getHeight();
+ shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
+ shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
+ shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
+ 0.5f / width * scale_x, 0.5f / height * scale_y);
+ shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y,
+ 2.f / width * scale_x, 2.f / height * scale_y);
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex2f(-1, -1);
+ gGL.vertex2f(-1, 3);
+ gGL.vertex2f(3, -1);
+ gGL.end();
+
+ gGL.flush();
+ shader->unbind();
+ }
+ }
+ else // not deferred
+ {
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
+ buff->allocateBuffer(3, 0, TRUE);
+
+ LLStrider<LLVector3> v;
+ LLStrider<LLVector2> uv1;
+ LLStrider<LLVector2> uv2;
+
+ buff->getVertexStrider(v);
+ buff->getTexCoord0Strider(uv1);
+ buff->getTexCoord1Strider(uv2);
+
+ uv1[0] = LLVector2(0, 0);
+ uv1[1] = LLVector2(0, 2);
+ uv1[2] = LLVector2(2, 0);
+
+ uv2[0] = LLVector2(0, 0);
+ uv2[1] = LLVector2(0, tc2.mV[1] * 2.f);
+ uv2[2] = LLVector2(tc2.mV[0] * 2.f, 0);
+
+ v[0] = LLVector3(-1, -1, 0);
+ v[1] = LLVector3(-1, 3, 0);
+ v[2] = LLVector3(3, -1, 0);
+
+ buff->flush();
+
+ LLGLDisable blend(GL_BLEND);
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gGlowCombineProgram.bind();
+ }
+ else
+ {
+ // tex unit 0
+ gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
+ // tex unit 1
+ gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR,
+ LLTexUnit::TBS_PREV_COLOR);
+ }
+
+ gGL.getTexUnit(0)->bind(&mGlow[1]);
+ gGL.getTexUnit(1)->bind(&mScreen);
+
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ buff->setBuffer(mask);
+ buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gGlowCombineProgram.unbind();
+ }
+ else
+ {
+ gGL.getTexUnit(1)->disable();
+ gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ gGL.getTexUnit(0)->activate();
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+ }
+ }
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+ {
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gSplatTextureRectProgram.bind();
+ }
+
+ gGL.setColorMask(true, false);
+
+ LLVector2 tc1(0, 0);
+ LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw() * 2,
+ (F32) gViewerWindow->getWorldViewHeightRaw() * 2);
+
+ LLGLEnable blend(GL_BLEND);
+ gGL.color4f(1, 1, 1, 0.75f);
+
+ gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+
+ gGL.begin(LLRender::TRIANGLES);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
+
+ gGL.end();
+ gGL.flush();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gSplatTextureRectProgram.unbind();
+ }
+ }
+
+ if (LLRenderTarget::sUseFBO)
+ { // copy depth buffer from mScreen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 0, 0,
+ mScreen.getWidth(), mScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+ }
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
}
static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred");
@@ -8453,628 +8456,622 @@ static LLTrace::BlockTimerStatHandle FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
static LLTrace::BlockTimerStatHandle FTM_PROJECTORS("Projectors");
static LLTrace::BlockTimerStatHandle FTM_POST("Post");
-
-void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target)
+void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
- if (!sCull)
- {
- return;
- }
+ if (!sCull)
+ {
+ return;
+ }
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LLRenderTarget *deferred_target = &mDeferredScreen;
+ LLRenderTarget *deferred_depth_target = &mDeferredDepth;
+ LLRenderTarget *deferred_light_target = &mDeferredLight;
- {
- LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
- LLViewerCamera* camera = LLViewerCamera::getInstance();
- {
- LLGLDepthTest depth(GL_TRUE);
- deferred_depth_target->copyContents(*deferred_target, 0, 0, deferred_target->getWidth(), deferred_target->getHeight(),
- 0, 0, deferred_depth_target->getWidth(), deferred_depth_target->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
+ {
+ LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
+ LLViewerCamera *camera = LLViewerCamera::getInstance();
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ deferred_depth_target->copyContents(*deferred_target,
+ 0,
+ 0,
+ deferred_target->getWidth(),
+ deferred_target->getHeight(),
+ 0,
+ 0,
+ deferred_depth_target->getWidth(),
+ deferred_depth_target->getHeight(),
+ GL_DEPTH_BUFFER_BIT,
+ GL_NEAREST);
+ }
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
- //ati doesn't seem to love actually using the stencil buffer on FBO's
- LLGLDisable stencil(GL_STENCIL_TEST);
- //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
- //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ // ati doesn't seem to love actually using the stencil buffer on FBO's
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ // glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+ // glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- gGL.setColorMask(true, true);
-
- //draw a cube around every light
- LLVertexBuffer::unbind();
+ gGL.setColorMask(true, true);
- LLGLEnable cull(GL_CULL_FACE);
- LLGLEnable blend(GL_BLEND);
+ // draw a cube around every light
+ LLVertexBuffer::unbind();
+
+ LLGLEnable cull(GL_CULL_FACE);
+ LLGLEnable blend(GL_BLEND);
glh::matrix4f mat = copy_matrix(gGLModelView);
- LLStrider<LLVector3> vert;
- mDeferredVB->getVertexStrider(vert);
-
- vert[0].set(-1,1,0);
- vert[1].set(-1,-3,0);
- vert[2].set(3,1,0);
-
- setupHWLights(NULL); //to set mSun/MoonDir;
+ LLStrider<LLVector3> vert;
+ mDeferredVB->getVertexStrider(vert);
+
+ vert[0].set(-1, 1, 0);
+ vert[1].set(-1, -3, 0);
+ vert[2].set(3, 1, 0);
+
+ setupHWLights(NULL); // to set mSun/MoonDir;
glh::vec4f tc(mSunDir.mV);
- mat.mult_matrix_vec(tc);
- mTransformedSunDir.set(tc.v);
+ mat.mult_matrix_vec(tc);
+ mTransformedSunDir.set(tc.v);
glh::vec4f tc_moon(mMoonDir.mV);
mat.mult_matrix_vec(tc_moon);
mTransformedMoonDir.set(tc_moon.v);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
- if (RenderDeferredSSAO || RenderShadowDetail > 0)
- {
+ if (RenderDeferredSSAO || RenderShadowDetail > 0)
+ {
deferred_light_target->bindTarget();
- { //paint shadow/SSAO light map (direct lighting lightmap)
- LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW);
+ { // paint shadow/SSAO light map (direct lighting lightmap)
+ LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW);
bindDeferredShader(gDeferredSunProgram, deferred_light_target);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- glClearColor(1,1,1,1);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ glClearColor(1, 1, 1, 1);
deferred_light_target->clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0,0,0,0);
+ glClearColor(0, 0, 0, 0);
glh::matrix4f inv_trans = get_current_modelview().inverse().transpose();
- const U32 slice = 32;
- F32 offset[slice*3];
- for (U32 i = 0; i < 4; i++)
- {
- for (U32 j = 0; j < 8; j++)
- {
- glh::vec3f v;
- v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
- v.normalize();
- inv_trans.mult_matrix_vec(v);
- v.normalize();
- offset[(i*8+j)*3+0] = v.v[0];
- offset[(i*8+j)*3+1] = v.v[2];
- offset[(i*8+j)*3+2] = v.v[1];
- }
- }
+ const U32 slice = 32;
+ F32 offset[slice * 3];
+ for (U32 i = 0; i < 4; i++)
+ {
+ for (U32 j = 0; j < 8; j++)
+ {
+ glh::vec3f v;
+ v.set_value(sinf(6.284f / 8 * j), cosf(6.284f / 8 * j), -(F32) i);
+ v.normalize();
+ inv_trans.mult_matrix_vec(v);
+ v.normalize();
+ offset[(i * 8 + j) * 3 + 0] = v.v[0];
+ offset[(i * 8 + j) * 3 + 1] = v.v[2];
+ offset[(i * 8 + j) * 3 + 2] = v.v[1];
+ }
+ }
- gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
- gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_light_target->getWidth(), deferred_light_target->getHeight());
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
-
- unbindDeferredShader(gDeferredSunProgram);
- }
+ gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
+ gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES,
+ deferred_light_target->getWidth(),
+ deferred_light_target->getHeight());
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+
+ unbindDeferredShader(gDeferredSunProgram);
+ }
deferred_light_target->flush();
- }
-
- if (RenderDeferredSSAO)
- { //soften direct lighting lightmap
- LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW);
- //blur lightmap
+ }
+
+ if (RenderDeferredSSAO)
+ { // soften direct lighting lightmap
+ LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW);
+ // blur lightmap
screen_target->bindTarget();
- glClearColor(1,1,1,1);
+ glClearColor(1, 1, 1, 1);
screen_target->clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0,0,0,0);
-
- bindDeferredShader(gDeferredBlurLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- LLVector3 go = RenderShadowGaussian;
- const U32 kern_length = 4;
- F32 blur_size = RenderShadowBlurSize;
- F32 dist_factor = RenderShadowBlurDistFactor;
+ glClearColor(0, 0, 0, 0);
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = 0.f;
+ bindDeferredShader(gDeferredBlurLightProgram);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ LLVector3 go = RenderShadowGaussian;
+ const U32 kern_length = 4;
+ F32 blur_size = RenderShadowBlurSize;
+ F32 dist_factor = RenderShadowBlurDistFactor;
- LLVector3 gauss[32]; // xweight, yweight, offset
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
- }
+ LLVector3 gauss[32]; // xweight, yweight, offset
+
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
+
+ gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
+ gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
- gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
- gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
- gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length/2.f - 0.5f));
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
-
screen_target->flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ unbindDeferredShader(gDeferredBlurLightProgram);
bindDeferredShader(gDeferredBlurLightProgram, screen_target);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
deferred_light_target->bindTarget();
- gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
+ gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
deferred_light_target->flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
- }
+ unbindDeferredShader(gDeferredBlurLightProgram);
+ }
- stop_glerror();
- gGL.popMatrix();
- stop_glerror();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- stop_glerror();
- gGL.popMatrix();
- stop_glerror();
+ stop_glerror();
+ gGL.popMatrix();
+ stop_glerror();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ stop_glerror();
+ gGL.popMatrix();
+ stop_glerror();
screen_target->bindTarget();
- // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
- glClearColor(0,0,0,0);
+ // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+ glClearColor(0, 0, 0, 0);
screen_target->clear(GL_COLOR_BUFFER_BIT);
-
- if (RenderDeferredAtmospheric)
- { //apply sunlight contribution
- LLGLSLShader& soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
- LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS);
- bindDeferredShader(soften_shader);
+ if (RenderDeferredAtmospheric)
+ { // apply sunlight contribution
+ LLGLSLShader &soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
+
+ LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS);
+ bindDeferredShader(soften_shader);
- LLEnvironment& environment = LLEnvironment::instance();
+ LLEnvironment &environment = LLEnvironment::instance();
soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
- {
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
- //full screen blit
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ // full screen blit
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
- }
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ }
- { //render non-deferred geometry (fullbright, alpha, etc)
- LLGLDisable blend(GL_BLEND);
- LLGLDisable stencil(GL_STENCIL_TEST);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
+ }
- gPipeline.pushRenderTypeMask();
-
- gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::RENDER_TYPE_WL_SKY,
- LLPipeline::END_RENDER_TYPES);
-
-
- renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
- gPipeline.popRenderTypeMask();
- }
+ { // render non-deferred geometry (fullbright, alpha, etc)
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
- bool render_local = RenderLocalLights;
-
- if (render_local)
- {
- gGL.setSceneBlendType(LLRender::BT_ADD);
- std::list<LLVector4> fullscreen_lights;
- LLDrawable::drawable_list_t spot_lights;
- LLDrawable::drawable_list_t fullscreen_spot_lights;
+ gPipeline.pushRenderTypeMask();
- for (U32 i = 0; i < 2; i++)
- {
- mTargetShadowSpotLight[i] = NULL;
- }
+ gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_CLOUDS,
+ LLPipeline::RENDER_TYPE_WL_SKY,
+ LLPipeline::END_RENDER_TYPES);
- std::list<LLVector4> light_colors;
+ renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
+ gPipeline.popRenderTypeMask();
+ }
- LLVertexBuffer::unbind();
+ bool render_local = RenderLocalLights;
- {
- bindDeferredShader(gDeferredLightProgram);
-
- if (mCubeVB.isNull())
- {
- mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
- }
+ if (render_local)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+ std::list<LLVector4> fullscreen_lights;
+ LLDrawable::drawable_list_t spot_lights;
+ LLDrawable::drawable_list_t fullscreen_spot_lights;
- mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
- {
- LLDrawable* drawablep = *iter;
-
- LLVOVolume* volume = drawablep->getVOVolume();
- if (!volume)
- {
- continue;
- }
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
- if (volume->isAttachment())
- {
- if (!sRenderAttachedLights)
- {
- continue;
- }
- }
+ std::list<LLVector4> light_colors;
+
+ LLVertexBuffer::unbind();
+
+ {
+ bindDeferredShader(gDeferredLightProgram);
+
+ if (mCubeVB.isNull())
+ {
+ mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+ }
+
+ mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- const LLViewerObject *vobj = drawablep->getVObj();
- if (vobj)
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ // mNearbyLights already includes distance calculation and excludes muted avatars.
+ // It is calculated from mLights
+ // mNearbyLights also provides fade value to gracefully fade-out out of range lights
+ for (light_set_t::iterator iter = mNearbyLights.begin(); iter != mNearbyLights.end(); ++iter)
+ {
+ LLDrawable * drawablep = iter->drawable;
+ LLVOVolume * volume = drawablep->getVOVolume();
+ if (!volume)
+ {
+ continue;
+ }
+
+ if (volume->isAttachment())
{
- LLVOAvatar *av = vobj->getAvatar();
- if (av && (av->isTooComplex() || av->isInMuteList()))
+ if (!sRenderAttachedLights)
{
continue;
}
}
- const LLVector3 position = drawablep->getPositionAgent();
- if (dist_vec(position, LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip + volume->getLightRadius())
+ LLVector4a center;
+ center.load3(drawablep->getPositionAgent().mV);
+ const F32 *c = center.getF32ptr();
+ F32 s = volume->getLightRadius() * 1.5f;
+
+ // send light color to shader in linear space
+ LLColor3 col = volume->getLightLinearColor();
+
+ if (col.magVecSquared() < 0.001f)
{
continue;
}
- LLVector4a center;
- center.load3(position.mV);
- const F32* c = center.getF32ptr();
- F32 s = volume->getLightRadius()*1.5f;
-
- //send light color to shader in linear space
- LLColor3 col = volume->getLightLinearColor();
-
- if (col.magVecSquared() < 0.001f)
- {
- continue;
- }
+ if (s <= 0.001f)
+ {
+ continue;
+ }
- if (s <= 0.001f)
- {
- continue;
- }
+ LLVector4a sa;
+ sa.splat(s);
+ if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
+ {
+ continue;
+ }
- LLVector4a sa;
- sa.splat(s);
- if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
- {
- continue;
- }
+ sVisibleLightCount++;
- sVisibleLightCount++;
-
- if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
- camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
- camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
- camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
- camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
- camera->getOrigin().mV[2] < c[2] - s - 0.2f)
- { //draw box if camera is outside box
- if (render_local)
- {
- if (volume->isLightSpotlight())
- {
- drawablep->getVOVolume()->updateSpotLightPriority();
- spot_lights.push_back(drawablep);
- continue;
- }
-
- LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS);
- gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
- gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
- gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+ if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
+ camera->getOrigin().mV[1] > c[1] + s + 0.2f || camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
+ camera->getOrigin().mV[2] > c[2] + s + 0.2f || camera->getOrigin().mV[2] < c[2] - s - 0.2f)
+ { // draw box if camera is outside box
+ if (render_local)
+ {
+ if (volume->isLightSpotlight())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS);
+ gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
+ gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
+ gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF));
- gGL.syncMatrices();
-
- mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
- stop_glerror();
- }
- }
- else
- {
- if (volume->isLightSpotlight())
- {
- drawablep->getVOVolume()->updateSpotLightPriority();
- fullscreen_spot_lights.push_back(drawablep);
- continue;
- }
+ gGL.syncMatrices();
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
-
- fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s));
+ mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
+ stop_glerror();
+ }
+ }
+ else
+ {
+ if (volume->isLightSpotlight())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ fullscreen_spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s));
light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF)));
- }
- }
- unbindDeferredShader(gDeferredLightProgram);
- }
+ }
+ }
- if (!spot_lights.empty())
- {
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- bindDeferredShader(gDeferredSpotLightProgram);
+ // Bookmark comment to allow searching for mSpecialRenderMode == 3 (avatar edit mode),
+ // prev site of appended deferred character light, removed by SL-13522 09/20
- mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ unbindDeferredShader(gDeferredLightProgram);
+ }
- gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+ if (!spot_lights.empty())
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ bindDeferredShader(gDeferredSpotLightProgram);
- for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
- {
- LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
- LLDrawable* drawablep = *iter;
+ mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+ gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- LLVOVolume* volume = drawablep->getVOVolume();
+ for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
+ LLDrawable *drawablep = *iter;
- LLVector4a center;
- center.load3(drawablep->getPositionAgent().mV);
- const F32* c = center.getF32ptr();
- F32 s = volume->getLightRadius()*1.5f;
+ LLVOVolume *volume = drawablep->getVOVolume();
- sVisibleLightCount++;
+ LLVector4a center;
+ center.load3(drawablep->getPositionAgent().mV);
+ const F32 *c = center.getF32ptr();
+ F32 s = volume->getLightRadius() * 1.5f;
- setupSpotLight(gDeferredSpotLightProgram, drawablep);
-
- //send light color to shader in linear space
+ sVisibleLightCount++;
+
+ setupSpotLight(gDeferredSpotLightProgram, drawablep);
+
+ // send light color to shader in linear space
LLColor3 col = volume->getLightLinearColor();
-
- gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
- gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
- gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+
+ gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
+ gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
+ gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF));
- gGL.syncMatrices();
-
- mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
- }
- gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- unbindDeferredShader(gDeferredSpotLightProgram);
- }
+ gGL.syncMatrices();
+
+ mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
+ }
+ gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredSpotLightProgram);
+ }
- //reset mDeferredVB to fullscreen triangle
- mDeferredVB->getVertexStrider(vert);
- vert[0].set(-1,1,0);
- vert[1].set(-1,-3,0);
- vert[2].set(3,1,0);
+ // reset mDeferredVB to fullscreen triangle
+ mDeferredVB->getVertexStrider(vert);
+ vert[0].set(-1, 1, 0);
+ vert[1].set(-1, -3, 0);
+ vert[2].set(3, 1, 0);
- {
- LLGLDepthTest depth(GL_FALSE);
+ {
+ LLGLDepthTest depth(GL_FALSE);
- //full screen blit
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ // full screen blit
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
- U32 count = 0;
+ U32 count = 0;
- const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT;
- LLVector4 light[max_count];
- LLVector4 col[max_count];
+ const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT;
+ LLVector4 light[max_count];
+ LLVector4 col[max_count];
- F32 far_z = 0.f;
+ F32 far_z = 0.f;
- while (!fullscreen_lights.empty())
- {
- LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS);
- light[count] = fullscreen_lights.front();
- fullscreen_lights.pop_front();
- col[count] = light_colors.front();
- light_colors.pop_front();
-
- far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z);
- count++;
- if (count == max_count || fullscreen_lights.empty())
- {
- U32 idx = count-1;
- bindDeferredShader(gDeferredMultiLightProgram[idx]);
- gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
- gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
- gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
- gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
- far_z = 0.f;
- count = 0;
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- unbindDeferredShader(gDeferredMultiLightProgram[idx]);
- }
- }
-
- bindDeferredShader(gDeferredMultiSpotLightProgram);
+ while (!fullscreen_lights.empty())
+ {
+ LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS);
+ light[count] = fullscreen_lights.front();
+ fullscreen_lights.pop_front();
+ col[count] = light_colors.front();
+ light_colors.pop_front();
+
+ far_z = llmin(light[count].mV[2] - light[count].mV[3], far_z);
+ count++;
+ if (count == max_count || fullscreen_lights.empty())
+ {
+ U32 idx = count - 1;
+ bindDeferredShader(gDeferredMultiLightProgram[idx]);
+ gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
+ gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat *) light);
+ gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat *) col);
+ gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
+ far_z = 0.f;
+ count = 0;
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ unbindDeferredShader(gDeferredMultiLightProgram[idx]);
+ }
+ }
- gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+ bindDeferredShader(gDeferredMultiSpotLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
- {
- LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
- LLDrawable* drawablep = *iter;
-
- LLVOVolume* volume = drawablep->getVOVolume();
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- LLVector3 center = drawablep->getPositionAgent();
- F32* c = center.mV;
- F32 light_size_final = volume->getLightRadius()*1.5f;
- F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF);
+ for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+ {
+ LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
+ LLDrawable *drawablep = *iter;
+ LLVOVolume *volume = drawablep->getVOVolume();
+ LLVector3 center = drawablep->getPositionAgent();
+ F32 * c = center.mV;
+ F32 light_size_final = volume->getLightRadius() * 1.5f;
+ F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF);
- sVisibleLightCount++;
+ sVisibleLightCount++;
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
-
- setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
- //send light color to shader in linear space
+ setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+ // send light color to shader in linear space
LLColor3 col = volume->getLightLinearColor();
-
- gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+
+ gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final);
- gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+ gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, light_falloff_final);
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- }
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
- gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- unbindDeferredShader(gDeferredMultiSpotLightProgram);
+ gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredMultiSpotLightProgram);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
- }
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ }
+ }
- gGL.setColorMask(true, true);
- }
+ gGL.setColorMask(true, true);
+ }
screen_target->flush();
- //gamma correct lighting
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ // gamma correct lighting
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
- {
- LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+ {
+ LLGLDepthTest depth(GL_FALSE, GL_FALSE);
- LLVector2 tc1(0,0);
- LLVector2 tc2((F32) screen_target->getWidth()*2,
- (F32) screen_target->getHeight()*2);
+ LLVector2 tc1(0, 0);
+ LLVector2 tc2((F32) screen_target->getWidth() * 2, (F32) screen_target->getHeight() * 2);
screen_target->bindTarget();
- // Apply gamma correction to the frame here.
- gDeferredPostGammaCorrectProgram.bind();
- //mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- S32 channel = 0;
- channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screen_target->getUsage());
- if (channel > -1)
- {
+ // Apply gamma correction to the frame here.
+ gDeferredPostGammaCorrectProgram.bind();
+ // mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ S32 channel = 0;
+ channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screen_target->getUsage());
+ if (channel > -1)
+ {
screen_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
- }
-
+ }
+
gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screen_target->getWidth(), screen_target->getHeight());
-
- F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
- gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
+ F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+
+ gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1, -1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1, 3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3, -1);
+
+ gGL.end();
+
gGL.getTexUnit(channel)->unbind(screen_target->getUsage());
- gDeferredPostGammaCorrectProgram.unbind();
+ gDeferredPostGammaCorrectProgram.unbind();
screen_target->flush();
- }
+ }
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
screen_target->bindTarget();
- { //render non-deferred geometry (alpha, fullbright, glow)
- LLGLDisable blend(GL_BLEND);
- LLGLDisable stencil(GL_STENCIL_TEST);
-
- pushRenderTypeMask();
- andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
- LLPipeline::RENDER_TYPE_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_VOLUME,
- LLPipeline::RENDER_TYPE_GLOW,
- LLPipeline::RENDER_TYPE_BUMP,
- LLPipeline::RENDER_TYPE_PASS_SIMPLE,
- LLPipeline::RENDER_TYPE_PASS_ALPHA,
- LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_BUMP,
- LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
- LLPipeline::RENDER_TYPE_PASS_GLOW,
- LLPipeline::RENDER_TYPE_PASS_GRASS,
- LLPipeline::RENDER_TYPE_PASS_SHINY,
- LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
- LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
- LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
- END_RENDER_TYPES);
-
- renderGeomPostDeferred(*LLViewerCamera::getInstance());
- popRenderTypeMask();
- }
+ { // render non-deferred geometry (alpha, fullbright, glow)
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+
+ pushRenderTypeMask();
+ andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
+ LLPipeline::RENDER_TYPE_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_VOLUME,
+ LLPipeline::RENDER_TYPE_GLOW,
+ LLPipeline::RENDER_TYPE_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_GLOW,
+ LLPipeline::RENDER_TYPE_PASS_GRASS,
+ LLPipeline::RENDER_TYPE_PASS_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+ LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+ LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
+ LLPipeline::RENDER_TYPE_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
+ END_RENDER_TYPES);
+
+ renderGeomPostDeferred(*LLViewerCamera::getInstance());
+ popRenderTypeMask();
+ }
- {
- //render highlights, etc.
- renderHighlights();
- mHighlightFaces.clear();
+ {
+ // render highlights, etc.
+ renderHighlights();
+ mHighlightFaces.clear();
- renderDebug();
+ renderDebug();
- LLVertexBuffer::unbind();
+ LLVertexBuffer::unbind();
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ gObjectList.resetObjectBeacons();
gSky.addSunMoonBeacons();
- }
- }
+ }
+ }
- screen_target->flush();
+ screen_target->flush();
}
void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
@@ -9291,7 +9288,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
gPipeline.pushRenderTypeMask();
- glh::matrix4f projection = get_current_projection();
+ glh::matrix4f saved_modelview = get_current_modelview();
+ glh::matrix4f saved_projection = get_current_projection();
glh::matrix4f mat;
S32 detail = RenderReflectionDetail;
@@ -9330,8 +9328,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
//disable occlusion culling for reflection map for now
LLPipeline::sUseOcclusion = 0;
- glh::matrix4f current = get_current_modelview();
-
if (!camera_is_underwater)
{ //generate planar reflection map
@@ -9340,15 +9336,10 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
- glh::matrix4f mat;
- camera.getOpenGLTransform(mat.m);
-
- glh::matrix4f scal;
- scal.set_scale(glh::vec3f(1, 1, -1));
- mat = scal * mat;
+ mat.set_scale(glh::vec3f(1, 1, -1));
+ mat.set_translate(glh::vec3f(0,0,water_height*2.f));
+ mat = saved_modelview * mat;
- // convert from CFR to OGL coord sys...
- mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
mReflectionModelView = mat;
@@ -9357,6 +9348,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
+ glh::vec3f origin(0, 0, 0);
+ glh::matrix4f inv_mat = mat.inverse();
+ inv_mat.mult_matrix_vec(origin);
+
+ camera.setOrigin(origin.v);
+
glCullFace(GL_FRONT);
if (LLDrawPoolWater::sNeedsReflectionUpdate)
@@ -9401,7 +9398,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
if (detail < 3)
{
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, END_RENDER_TYPES);
if (detail < 2)
{
clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
@@ -9409,7 +9406,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
}
}
- LLGLUserClipPlane clip_plane(plane, mReflectionModelView, projection);
+ LLGLUserClipPlane clip_plane(plane, mReflectionModelView, saved_projection);
LLGLDisable cull(GL_CULL_FACE);
updateCull(camera, mReflectedObjects, -water_clip, &plane);
stateSort(camera, mReflectedObjects);
@@ -9423,7 +9420,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.popMatrix();
- set_current_modelview(current);
+ set_current_modelview(saved_modelview);
}
//LLPipeline::sUseOcclusion = occlusion;
@@ -9479,7 +9476,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
//clip out geometry on the same side of water as the camera w/ enough margin to not include the water geo itself,
// but not so much as to clip out parts of avatars that should be seen under the water in the distortion map
LLPlane plane(-pnorm, water_dist);
- LLGLUserClipPlane clip_plane(plane, current, projection);
+ LLGLUserClipPlane clip_plane(plane, saved_modelview, saved_projection);
gGL.setColorMask(true, true);
mWaterDis.clear();
@@ -10116,6 +10113,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLPipeline::RENDER_TYPE_BUMP,
LLPipeline::RENDER_TYPE_VOLUME,
LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
LLPipeline::RENDER_TYPE_TREE,
LLPipeline::RENDER_TYPE_TERRAIN,
LLPipeline::RENDER_TYPE_WATER,
@@ -10909,7 +10907,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
if (visually_muted || too_complex)
{
- andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+ andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
+ END_RENDER_TYPES);
}
else
{
@@ -10932,6 +10932,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
LLPipeline::RENDER_TYPE_ALPHA_MASK,
LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
LLPipeline::RENDER_TYPE_INVISIBLE,
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 68ce3fe88d..52fd51cd80 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -139,7 +139,7 @@ public:
void resetVertexBuffers(LLDrawable* drawable);
void generateImpostor(LLVOAvatar* avatar);
void bindScreenToTexture();
- void renderBloom(bool for_snapshot, F32 zoom_factor = 1.f, int subfield = 0);
+ void renderFinalize();
void init();
void cleanup();
@@ -409,6 +409,7 @@ public:
static bool getRenderHighlights();
static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay
+ static void updateRenderTransparentWater();
static void updateRenderBump();
static void updateRenderDeferred();
static void refreshCachedSettings();
@@ -453,6 +454,7 @@ public:
RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP,
RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS,
RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
+ RENDER_TYPE_CONTROL_AV = LLDrawPool::POOL_CONTROL_AV, // Animesh
RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER,
@@ -577,6 +579,7 @@ public:
static bool sAutoMaskAlphaDeferred;
static bool sAutoMaskAlphaNonDeferred;
static bool sDisableShaders; // if true, rendering will be done without shaders
+ static bool sRenderTransparentWater;
static bool sRenderBump;
static bool sBakeSunlight;
static bool sNoAlpha;
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index 8587243791..ff2d8b4943 100755
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -155,7 +155,7 @@ BEGIN
VALUE "FileDescription", "Second Life"
VALUE "FileVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}"
VALUE "InternalName", "Second Life"
- VALUE "LegalCopyright", "Copyright � 2001, Linden Research, Inc."
+ VALUE "LegalCopyright", "Copyright (c) 2020, Linden Research, Inc."
VALUE "OriginalFilename", "SecondLife.exe"
VALUE "ProductName", "Second Life"
VALUE "ProductVersion", "${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION}"
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index e0da7f5d9e..e1cf708094 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -42,6 +42,9 @@
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
diff --git a/indra/newview/skins/default/textures/containers/TabTop_Right_Flashing.png b/indra/newview/skins/default/textures/containers/TabTop_Right_Flashing.png
new file mode 100644
index 0000000000..fd13bb699d
--- /dev/null
+++ b/indra/newview/skins/default/textures/containers/TabTop_Right_Flashing.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 7325d836d2..a875c4e848 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -634,6 +634,7 @@ with the same filename but different name
<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" />
diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
index 3c0428b2b0..b7ac181dd4 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
@@ -60,8 +60,7 @@ objektet.
</text>
<button label="Køb nu" name="buy_btn"/>
<button label="Annullér" name="cancel_btn"/>
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
Kan ikke købe
- </text>
- <button label="Fortsæt til web" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/da/menu_cof_attachment.xml b/indra/newview/skins/default/xui/da/menu_cof_attachment.xml
index 9d7fc0f223..37e9351ab5 100644
--- a/indra/newview/skins/default/xui/da/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/da/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Berør" name="touch_attach" />
+ <menu_item_call label="Redigér" name="edit_item" />
<menu_item_call label="Tag af" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/da/menu_inventory.xml b/indra/newview/skins/default/xui/da/menu_inventory.xml
index f9bdf36f1f..ba96d6dca1 100644
--- a/indra/newview/skins/default/xui/da/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/da/menu_inventory.xml
@@ -78,6 +78,7 @@
<menu_item_call label="Tag på" name="Wearable And Object Wear"/>
<menu label="Vedhæft" name="Attach To"/>
<menu label="Vedhæft til HUD" name="Attach To HUD"/>
+ <menu_item_call label="Berør" name="Attachment Touch" />
<menu_item_call label="Redigér" name="Wearable Edit"/>
<menu_item_call label="Tilføj" name="Wearable Add"/>
<menu_item_call label="Tag af" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml
index 63f4b0b388..67adf74bcd 100644
--- a/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/da/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Erstat" name="wear_replace"/>
<menu_item_call label="Tag på" name="wear_wear"/>
<menu_item_call label="Tilføj" name="wear_add"/>
+ <menu_item_call label="Berør" name="touch" />
<menu_item_call label="Tag af" name="take_off_or_detach"/>
<menu_item_call label="Tag af" name="detach"/>
<context_menu label="Vedhæft til" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/da/menu_wearing_gear.xml b/indra/newview/skins/default/xui/da/menu_wearing_gear.xml
index 515a15b287..ff58cd68b2 100644
--- a/indra/newview/skins/default/xui/da/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/da/menu_wearing_gear.xml
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu name="Gear Wearing">
- <menu_item_call label="Redigér sæt" name="edit"/>
+ <menu_item_call label="Berør" name="touch"/>
+ <menu_item_call label="Redigér" name="edit_item"/>
+ <menu_item_call label="Redigér sæt" name="edit_outfit"/>
<menu_item_call label="Tag af" name="takeoff"/>
</menu>
diff --git a/indra/newview/skins/default/xui/da/menu_wearing_tab.xml b/indra/newview/skins/default/xui/da/menu_wearing_tab.xml
index c0db7b6842..adaac35f68 100644
--- a/indra/newview/skins/default/xui/da/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/da/menu_wearing_tab.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Berør" name="touch_attach"/>
+ <menu_item_call label="Redigér" name="edit_item"/>
<menu_item_call label="Tag af" name="take_off"/>
<menu_item_call label="Tag af" name="detach"/>
- <menu_item_call label="Redigér sæt" name="edit"/>
+ <menu_item_call label="Redigér sæt" name="edit_outfit"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index 65926c088c..eb94df1cad 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -59,8 +59,7 @@
</text>
<button label="Jetzt kaufen" name="buy_btn"/>
<button label="Abbrechen" name="cancel_btn"/>
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
Kaufabbruch
- </text>
- <button label="Weiter zur Kontoseite" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
index b818a7d480..81b093b8c2 100644
--- a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Mehrere Texturen
</text>
- <radio_group name="mode_selection">
- <radio_item label="Inventar" name="inventory" value="0"/>
- <radio_item label="Lokal" name="local" value="1"/>
- <radio_item label="Backen" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Größe: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Inventar" name="inventory" value="0"/>
+ <combo_box.item label="Lokal" name="local" value="1"/>
+ </combo_box>
<button label="Standard" label_selected="Standard" name="Default"/>
<button label="Leer" label_selected="Leer" name="Blank"/>
<button label="Keine" label_selected="Keine" name="None"/>
diff --git a/indra/newview/skins/default/xui/de/menu_cof_attachment.xml b/indra/newview/skins/default/xui/de/menu_cof_attachment.xml
index 05d3dfca9d..7c7da58866 100644
--- a/indra/newview/skins/default/xui/de/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/de/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Berühren" name="touch_attach" />
+ <menu_item_call label="Bearbeiten" name="edit_item" />
<menu_item_call label="Abnehmen" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml
index 84cded77ce..743b8b2073 100644
--- a/indra/newview/skins/default/xui/de/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/de/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="Anziehen" name="Wearable And Object Wear"/>
<menu label="Anhängen an" name="Attach To"/>
<menu label="An HUD hängen" name="Attach To HUD"/>
+ <menu_item_call label="Berühren" name="Attachment Touch" />
<menu_item_call label="Bearbeiten" name="Wearable Edit"/>
<menu_item_call label="Hinzufügen" name="Wearable Add"/>
<menu_item_call label="Ausziehen" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml
index 283e454a06..e4c2c88f11 100644
--- a/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/de/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Ersetzen" name="wear_replace"/>
<menu_item_call label="Anziehen" name="wear_wear"/>
<menu_item_call label="Hinzufügen" name="wear_add"/>
+ <menu_item_call label="Berühren" name="touch" />
<menu_item_call label="Ausziehen / Abnehmen" name="take_off_or_detach"/>
<menu_item_call label="Abnehmen" name="detach"/>
<context_menu label="Anhängen an" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/de/menu_wearing_gear.xml b/indra/newview/skins/default/xui/de/menu_wearing_gear.xml
index dacf898b6a..6cb0d095e7 100644
--- a/indra/newview/skins/default/xui/de/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/de/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Outfit bearbeiten" name="edit"/>
+ <menu_item_call label="Berühren" name="touch"/>
+ <menu_item_call label="Bearbeiten" name="edit_item"/>
+ <menu_item_call label="Outfit bearbeiten" name="edit_outfit"/>
<menu_item_call label="Ausziehen" name="takeoff"/>
<menu_item_call label="Outfitliste in Zwischenablage kopieren" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_wearing_tab.xml b/indra/newview/skins/default/xui/de/menu_wearing_tab.xml
index 61002b3dad..c729ef6b00 100644
--- a/indra/newview/skins/default/xui/de/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/de/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Berühren" name="touch_attach"/>
<menu_item_call label="Ausziehen" name="take_off"/>
<menu_item_call label="Abnehmen" name="detach"/>
- <menu_item_call label="Outfit bearbeiten" name="edit"/>
+ <menu_item_call label="Outfit bearbeiten" name="edit_outfit"/>
<menu_item_call label="Bearbeiten" name="edit_item"/>
<menu_item_call label="Original anzeigen" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index d16815c0f4..359a835630 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -266,6 +266,10 @@ Möchten Sie den ausgewählten Einwohnern Änderungsrechte gewähren?
Möchten Sie den ausgewählten Einwohnern die Änderungsrechte entziehen?
<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ Ein Gruppenname muss zwischen [MIN_LEN] und [MAX_LEN] Zeichen lang sein.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
Gruppe konnte nicht erstellt werden.
[MESSAGE]
@@ -366,7 +370,7 @@ Fortfahren?
Sie haben nicht genug L$, um dieser Gruppe beizutreten.
</notification>
<notification name="CreateGroupCost">
- Die Gründung dieser Gruppe kostet 100 L$.
+ Die Erstellung dieser Gruppe kostet L$[COST].
Gruppen müssen mehr als ein Mitglied haben oder sie werden gelöscht.
Bitte laden Sie innerhalb von 48 Stunden Mitglieder in Ihre Gruppe ein.
<usetemplate canceltext="Abbrechen" name="okcancelbuttons" notext="Abbrechen" yestext="Gruppe für 100 L$ erstellen"/>
@@ -508,6 +512,9 @@ Um Medien nur auf einer Fläche einzufügen, wählen Sie „Oberfläche auswähl
<notification name="ErrorEncodingSnapshot">
Fehler beim Erstellen des Fotos!
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Du brauchst L$[COST], um diesen Artikel hochzuladen.
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Es kostet L$[COST], um ein Foto in Ihrem Inventar zu speichern. Sie können entweder L$ kaufen oder das Foto auf Ihrem Computer speichern.
</notification>
@@ -1753,11 +1760,14 @@ Diese Gruppe verlassen?
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- Die Gruppenbegrenzung für Basiskonten ist [MAX_BASIC]; für
-[https://secondlife.com/premium/ Premium-]Konten ist sie [MAX_PREMIUM].
-Wenn Sie ein Downgrade Ihres Kontos durchgeführt haben, müssen Sie das Gruppenlimit unter [MAX_BASIC] bringen, bevor sich weitere Personen registrieren können.
-
-[https://secondlife.com/my/account/membership.php Noch heute upgraden!]
+ Einwohner mit Basic-Mitgliedschaft können bis zu [MAX_BASIC] Gruppen beitreten.
+Premium-Mitgliedschaften erlauben bis zu [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Mehr Informationen oder Upgrade]
+ <usetemplate name="okbutton" yestext="Schließen"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ Einwohner mit Basic-Mitgliedschaft können bis zu [MAX_BASIC] Gruppen beitreten.
+Premium-Mitgliedschaften erlauben bis zu [MAX_PREMIUM]. Premium-Plus-Mitgliedschaften
+erlauben bis zu [MAX_PREMIUM_PLUS]. [https://secondlife.com/my/account/membership.php? Mehr Informationen oder Upgrade]
<usetemplate name="okbutton" yestext="Schließen"/>
</notification>
<notification name="KickUser">
@@ -3320,6 +3330,22 @@ Diese werden für ein paar Sekunden sicherheitshalber gesperrt.
Sie wurden vom Moderator stummgeschaltet.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ Leider konnten wir für diese Sitzung keine Informationen zu den Leistungen erhalten. Dies sollte in einer normalen Produktionsumgebung nicht passieren. Kontaktiere bitte den Support. Diese Sitzung wird nicht normal laufen, und wir empfehlen, die Sitzung neu zu starten.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Dadurch werden [COUNT] Artikel zu einem Gesamtpreis von L$[COST] hochgeladen. Möchtest du mit dem Hochladen fortfahren?
+ <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Hochladen"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ Ausgewählte Dateien können nicht per Bulk-Upload hochgeladen werden.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Einige der ausgewählten Dateien können nicht per Bulk-Upload hochgeladen werden.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
Das Hochladen kostet [PRICE] L$. Möchten Sie fortfahren?
<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Hochladen"/>
diff --git a/indra/newview/skins/default/xui/de/panel_people.xml b/indra/newview/skins/default/xui/de/panel_people.xml
index 1eb3d4d1b9..81de679429 100644
--- a/indra/newview/skins/default/xui/de/panel_people.xml
+++ b/indra/newview/skins/default/xui/de/panel_people.xml
@@ -18,7 +18,7 @@ Sie suchen nach Leuten? Verwenden Sie die [secondlife:///app/worldmap Karte].
<string name="no_groups_msg" value="Suchen Sie nach Gruppen? Versuchen Sie es mit der [secondlife:///app/search/groups Suche]."/>
<string name="MiniMapToolTipMsg" value="[REGION](Doppelklicken, um Karte zu öffnen; Umschalttaste gedrückt halten und ziehen, um zu schwenken)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Doppelklicken, um zu teleportieren; Umschalttaste gedrückt halten und ziehen, um zu schwenken)"/>
- <string name="GroupCountWithInfo" value="Sie gehören [COUNT] Gruppen an und können [REMAINING] weiteren beitreten. [secondlife:/// Möchten Sie noch mehr?]"/>
+ <string name="GroupCountWithInfo" value="Du gehörst zu [COUNT] Gruppen, und kannst [REMAINING] weiteren beitreten. [secondlife:/// Erhöhe dein Limit]"/>
<tab_container name="tabs">
<panel label="IN DER NÄHE" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@ Sie suchen nach Leuten? Verwenden Sie die [secondlife:///app/worldmap Karte].
<dnd_button name="minus_btn" tool_tip="Ausgewählte Gruppe verlassen"/>
</panel>
<text name="groupcount">
- Sie gehören [COUNT] Gruppen an und können [REMAINING] weiteren beitreten.
+ Du gehörst zu [COUNT] Gruppen, und kannst [REMAINING] weiteren beitreten.
</text>
</panel>
<panel label="AKTUELL" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
index e0aa9fe4a9..16fdb69509 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml
@@ -32,10 +32,10 @@
</text>
<check_box initial_value="true" label="Freunde immer darstellen" name="AlwaysRenderFriends"/>
<button label="Ausnahmen..." name="RenderExceptionsButton"/>
- <button label="Einstellungen als Voreinstellung speichern..." name="PrefSaveButton"/>
- <button label="Voreinstellung laden..." name="PrefLoadButton"/>
+ <button label="Einstellungen als Voreinstellung speichern" name="PrefSaveButton" width="235" left="5"/>
+ <button label="Voreinstellung laden" name="PrefLoadButton" width="120"/>
min_val=&quot;0.125&quot;
- <button label="Voreinstellung löschen..." name="PrefDeleteButton"/>
- <button label="Auf empfohlene Einstellungen zurücksetzen" name="Defaults"/>
+ <button label="Voreinstellung löschen" name="PrefDeleteButton" width="130"/>
+ <button label="Auf empfohlene Einstellungen zurücksetzen" name="Defaults" width="248"/>
<button label="Erweiterte Einstellungen..." name="AdvancedSettings"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_setup.xml b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
index 1435b7f87d..a8509cabac 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
@@ -35,5 +35,5 @@
<text name="Proxy Settings:">
Proxy-Einstellungen:
</text>
- <button label="Proxy-Einstellungen ändern" label_selected="Durchsuchen" name="set_proxy"/>
+ <button label="Proxy-Einstellungen ändern" label_selected="Durchsuchen" name="set_proxy" width="160"/>
</panel>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 7db76ec552..43327c132d 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -1645,11 +1645,14 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich unter http://suppo
<string name="MarketplaceUpdating">
Aktualisierung läuft...
</string>
+ <string name="UploadFeeInfo">
+ Die Gebühr richtet sich nach deiner Abonnementstufe. Bei höheren Stufen werden niedrigere Gebühren erhoben. [https://secondlife.com/my/account/membership.php? Mehr erfahren]
+ </string>
<string name="Open landmarks">
- Landmarken öffnen
+ Wegweiser öffnen
</string>
<string name="Unconstrained">
- Variabel
+ Unbegrenzt
</string>
<string name="no_transfer" value=" (kein Transferieren)"/>
<string name="no_modify" value=" (kein Bearbeiten)"/>
@@ -5096,6 +5099,15 @@ Bitte überprüfen Sie http://status.secondlifegrid.net, um herauszufinden, ob e
<string name="Chat" value=" Chat:">
Chat
</string>
+ <string name="BaseMembership">
+ Basis
+ </string>
+ <string name="PremiumMembership">
+ Premium
+ </string>
+ <string name="Premium PlusMembership">
+ Premium Plus
+ </string>
<string name="DeleteItems">
Ausgewählte Objekte löschen?
</string>
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 a1dd179765..b2d9e53039 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -123,8 +123,8 @@
No parcel selected.
</panel.string>
<panel.string name="time_stamp_template">
- [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
- </panel.string>
+ [wkday,datetime,slt] [mth,datetime,slt] [day,datetime,slt] [hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt] [year,datetime,slt]
+ </panel.string>
<text
type="string"
length="1"
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 553c5d51d0..061af1b67c 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -13,6 +13,10 @@
name="buy_currency">
Buy L$ [LINDENS] for approx. [LOCALAMOUNT]
</floater.string>
+ <floater.string
+ name="info_cannot_buy">
+ Unable to Buy
+ </floater.string>
<icon
height="215"
image_name="Linden_Dollar_Background"
@@ -286,42 +290,4 @@ Re-enter amount to see the latest exchange rate.
left_pad="10"
name="cancel_btn"
width="90"/>
- <icon
- height="215"
- image_name="Linden_Dollar_Alert"
- layout="topleft"
- left="0"
- name="error_background"
- top="15"
- use_draw_context_alpha="false"
- width="350"/>
- <text
- type="string"
- font="SansSerifHuge"
- left="165"
- width="360"
- height="25"
- top="25"
- name="info_cannot_buy">
- Unable to Buy
- </text>
- <text
- type="string"
- width="176"
- height="125"
- top="60"
- left="165"
- word_wrap="true"
- follows="bottom|right"
- name="cannot_buy_message">
- </text>
- <button
- follows="bottom|left"
- height="20"
- label="Continue to the Web"
- layout="topleft"
- left="170"
- name="error_web"
- top="200"
- width="160"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml
index 3daff1a132..773d9aafc9 100644
--- a/indra/newview/skins/default/xui/en/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml
@@ -120,8 +120,8 @@
Try saving image as 24 bit Targa (.tga).
</text>
<check_box
- control_name="LosslessJ2CUpload"
enabled="false"
+ initial_value="false"
follows="bottom|left"
height="16"
label="Use lossless compression"
diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml
index 63334e2b24..802a6649c8 100644
--- a/indra/newview/skins/default/xui/en/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/en/floater_inspect.xml
@@ -13,7 +13,7 @@
width="400">
<floater.string
name="timeStamp">
- [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ [wkday,datetime,slt] [mth,datetime,slt] [day,datetime,slt] [hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt] [year,datetime,slt]
</floater.string>
<scroll_list
bottom="268"
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 5a86eb06fb..02a21764ce 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -2,15 +2,16 @@
<floater
can_close="true"
can_drag_on_left="false"
- can_minimize="false"
- can_resize="false"
- height="480"
- min_height="480"
+ can_minimize="true"
+ can_resize="true"
+ height="625"
+ min_height="625"
width="980"
min_width="980"
name="Model Preview"
title="UPLOAD MODEL"
- help_topic="upload_model" >
+ help_topic="upload_model"
+ legacy_header_height="25">
<string name="status_idle"></string>
<string name="status_parse_error">Error: Dae parsing issue - see log for details.</string>
@@ -33,19 +34,27 @@
<string name="mesh_status_missing_lod">Missing required level of detail.</string>
<string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string>
<string name="phys_status_vertex_limit_exceeded">Some physical hulls exceed vertex limitations.</string>
+ <string name="phys_status_degenerate_triangles">The physics mesh too dense remove the small thin triangles (see preview)</string>
<string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->
<string name="decomposing">Analyzing...</string>
<string name="simplifying">Simplifying...</string>
<string name="tbd">TBD</string>
+
+ <!-- Warnings and info from model loader-->
+ <string name="TooManyJoint">Skinning disabled due to too many joints: [JOINTS], maximum: [MAX]</string>
+ <string name="UnrecognizedJoint">Rigged to unrecognized joint name [NAME]</string>
+ <string name="UnknownJoints">Skinning disabled due to [COUNT] unknown joints</string>
+ <string name="ModelLoaded">Model [MODEL_NAME] loaded</string>
+ <string name="IncompleteTC">Texture coordinates data is not complete.</string>
-<panel
- follows="top|left"
- height="455"
- layout="topleft"
- left="3"
- name="left_panel"
- top_pad="10"
- width="630">
+ <panel
+ follows="top|left"
+ height="595"
+ layout="topleft"
+ left="3"
+ name="left_panel"
+ top_pad="25"
+ width="635">
<panel
follows="all"
height="50"
@@ -76,12 +85,16 @@
</panel>
<tab_container
follows="top|left"
- top_pad="15"
+ top_pad="10"
left="0"
- height="300"
+ height="330"
width="635"
name="import_tab"
- tab_position="top">
+ tab_position="top"
+ enable_tabs_flashing="true"
+ tabs_flashing_color="MenuItemFlashBgColor">
+ <last_tab
+ tab_top_image_flash="TabTop_Right_Flashing"/> <!-- for log tab -->
<!-- LOD PANEL -->
<panel
help_topic="upload_model_lod"
@@ -92,12 +105,12 @@
<view_border
bevel_style="none"
follows="top|left"
- height="275"
+ height="306"
layout="topleft"
left="3"
name="lod_tab_border"
top_pad="0"
- width="629" />
+ width="628" />
<text
follows="left|top"
height="18"
@@ -688,7 +701,7 @@
left="10"
name="lod_tab_border"
top_pad="20"
- width="605" />
+ width="614" />
<check_box
follows="top|left"
height="15"
@@ -730,12 +743,12 @@
<view_border
bevel_style="none"
follows="top|left"
- height="275"
+ height="306"
layout="topleft"
left="3"
name="physics_tab_border"
top_pad="0"
- width="619"/>
+ width="628"/>
<panel
bg_alpha_color="0 0 0 0"
bg_opaque_color="0 0 0 0.3"
@@ -755,8 +768,9 @@
name="first_step_name"
text_color="White"
top_pad="0"
- width="210">
- Step 1: Level of Detail
+ width="210"
+ valign="center">
+ Step 1: Pick a physics model :
</text>
<combo_box
follows="left|top"
@@ -798,7 +812,7 @@
layout="topleft"
left="18"
name="physics_tab_border"
- top_pad="15"
+ top_pad="10"
width="589"/>
<panel
bg_alpha_color="0 0 0 0"
@@ -807,7 +821,7 @@
follows="top|left"
left="18"
name="physics analysis"
- top_pad="15"
+ top_pad="10"
visible="true"
width="589">
<text
@@ -819,7 +833,7 @@
name="method_label"
text_color="White"
top_pad="0">
- Step 2: Analyze
+ Step 2: Convert to hulls (optional)
</text>
<text
follows="top|left"
@@ -905,7 +919,7 @@
layout="topleft"
left="18"
name="physics_tab_border"
- top_pad="15"
+ top_pad="10"
width="589"/>
<panel
bg_alpha_color="0 0 0 0"
@@ -914,7 +928,7 @@
height="66"
left="18"
name="physics simplification"
- top_pad="15"
+ top_pad="10"
width="589">
<text
text_color="White"
@@ -1013,7 +1027,7 @@
layout="topleft"
left="18"
name="physics_tab_border"
- top_pad="15"
+ top_pad="10"
width="589"/>
<panel
bg_alpha_color="0 0 0 0"
@@ -1075,10 +1089,9 @@
follows="left|top"
height="19"
layout="topleft"
- left_pad="5"
- top_delta="0"
+ top_pad="5"
name="physics message"
- width="270">
+ width="589">
<icon
follows="left|top"
height="16"
@@ -1093,7 +1106,7 @@
layout="topleft"
left_pad="2"
name="physics_status_message_text"
- width="252"
+ width="573"
top_delta="3"/>
</panel>
</panel>
@@ -1105,12 +1118,12 @@
<view_border
bevel_style="none"
follows="top|left"
- height="275"
+ height="306"
layout="topleft"
left="3"
name="border"
top_pad="0"
- width="619"/>
+ width="628"/>
<text
follows="top|left"
height="16"
@@ -1157,75 +1170,211 @@
label_text.text_color="White"
left="20"
top_pad="20"/>
- <view_border
- bevel_style="none"
- follows="top|left"
- height="0"
- layout="topleft"
- name="border"
- top_pad="20"
- width="579"/>
- <text
- follows="top|left"
- height="15"
- left="20"
- name="include_label"
- text_color="White"
- top_pad="20"
- width="150">
- For avatar models only:
- </text>
- <check_box
- follows="top|left"
- height="15"
- label="Include skin weight"
- label_text.text_color="White"
- name="upload_skin"
- top_pad="15"/>
- <check_box
- follows="top|left"
- height="15"
- label="Include joint positions"
- label_text.text_color="White"
- name="upload_joints"
- top_pad="15"/>
- <check_box
- follows="top|left"
- height="15"
- label="Lock scale if joint position defined"
- label_text.text_color="White"
- name="lock_scale_if_joint_position"
- top_pad="15"/>
- <text
- follows="top|left"
- height="15"
- layout="topleft"
- left="220"
- name="pelvis_offset_label"
- text_color="White"
- top="134"
- width="200">
- Z offset (raise or lower avatar):
- </text>
- <spinner
- follows="top|left"
- height="20"
- min_val="-3.00"
- max_val="3.0"
- name="pelvis_offset"
- top_pad="10"
- value="0.0"
- width="80"/>
</panel>
+ <panel
+ label="Overrides"
+ layout="topleft"
+ name="rigging_panel"
+ title="Rigging">
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="306"
+ layout="topleft"
+ left="3"
+ name="avatar_tab_border"
+ top_pad="0"
+ width="628" />
+ <check_box
+ follows="top|left"
+ height="15"
+ label="Include skin weight"
+ label_text.text_color="White"
+ name="upload_skin"
+ top="8"
+ left="20"/>
+ <check_box
+ follows="top|left"
+ height="15"
+ label="Include joint positions"
+ label_text.text_color="White"
+ name="upload_joints"
+ left_delta="0"
+ top_pad="7"/>
+ <check_box
+ follows="top|left"
+ height="15"
+ label="Lock scale if joint position defined"
+ label_text.text_color="White"
+ name="lock_scale_if_joint_position"
+ top_pad="7"/>
+ <text
+ follows="top|left"
+ height="15"
+ layout="topleft"
+ left="220"
+ name="pelvis_offset_label"
+ text_color="White"
+ top="8"
+ width="200">
+ Z offset (raise or lower avatar):
+ </text>
+ <spinner
+ follows="top|left"
+ height="20"
+ min_val="-3.00"
+ max_val="3.0"
+ name="pelvis_offset"
+ top_pad="10"
+ value="0.0"
+ width="80"/>
+ <text
+ follows="top|left"
+ height="17"
+ left="425"
+ name="skin_too_many_joints"
+ text_color="Orange"
+ top="7"
+ width="195"
+ word_wrap="true">
+ Too many skinned joints
+ </text>
+ <text
+ follows="top|left"
+ height="32"
+ left="425"
+ name="skin_unknown_joint"
+ text_color="Orange"
+ top="8"
+ width="195"
+ word_wrap="true">
+ Model has an unknown joint(s)
+ </text>
+ <text
+ layout="topleft"
+ follows="top|left"
+ height="15"
+ left="20"
+ name="joints_descr"
+ top="73"
+ width="150">
+ Joints:
+ </text>
+ <scroll_list
+ layout="topleft"
+ follows="top|left"
+ name="joints_list"
+ column_padding="0"
+ draw_heading="false"
+ draw_stripes="false"
+ commit_on_selection_change="true"
+ heading_height="23"
+ height="199"
+ left_delta="0"
+ top_pad="0"
+ width="200"/>
+ <text
+ layout="topleft"
+ follows="top|left"
+ height="15"
+ left_delta="0"
+ name="conflicts_description"
+ top_pad="2"
+ width="200">
+ [CONFLICTS] conflicts in [JOINTS_COUNT] joints
+ </text>
+ <text
+ layout="topleft"
+ follows="top|left"
+ height="15"
+ left_pad="5"
+ name="pos_overrides_descr"
+ top="73"
+ width="300">
+ Position overrides for joint '[JOINT]':
+ </text>
+ <scroll_list
+ layout="topleft"
+ follows="top|left"
+ name="pos_overrides_list"
+ column_padding="0"
+ draw_heading="true"
+ draw_stripes="false"
+ heading_height="23"
+ height="100"
+ left_delta="0"
+ top_pad="0"
+ width="385">
+ <scroll_list.columns
+ label="Model"
+ name="model_name"
+ relative_width="0.49" />
+ <scroll_list.columns
+ label="X"
+ name="axis_x"
+ relative_width="0.17" />
+ <scroll_list.columns
+ label="Y"
+ name="axis_y"
+ relative_width="0.17" />
+ <scroll_list.columns
+ label="Z"
+ name="axis_z"
+ relative_width="0.17" />
+ </scroll_list>
+ </panel>
+ <panel
+ label="Log"
+ layout="topleft"
+ name="logs_panel"
+ title="Log">
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="289"
+ layout="topleft"
+ left="3"
+ name="log_tab_border"
+ top_pad="0"
+ width="628" />
+ <text_editor
+ type="string"
+ length="1"
+ embedded_items="false"
+ follows="top|left"
+ font="SansSerif"
+ ignore_tab="false"
+ layout="topleft"
+ height="289"
+ left="4"
+ top="0"
+ right="-1"
+ max_length="65536"
+ name="log_text"
+ parse_urls="true"
+ spellcheck="false"
+ read_only="true"
+ word_wrap="true">
+ </text_editor>
+ <check_box
+ control_name="ImporterDebug"
+ follows="top|left"
+ top_pad="9"
+ left="6"
+ width="70"
+ label="Enable detailed logging"
+ name="verbose_logging"/>
+ </panel>
</tab_container>
<panel
- follows="top|left"
- height="80"
- layout="top|left"
- left="0"
+ follows="top|left|bottom"
+ layout="topleft"
+ height="195"
+ left="4"
+ border="true"
name="weights_and_warning_panel"
top_pad="3"
- width="625">
+ width="629">
<button
follows="top|left"
label="Calculate weights &amp; fee"
@@ -1265,10 +1414,10 @@
label_color="White"
layout="topleft"
name="reset_btn"
- right="-2"
+ right="-5"
top="3"
height="20"
- width="275"/>
+ width="265"/>
<!-- ========== WEIGHTS ==========-->
<text
follows="top|left"
@@ -1287,7 +1436,7 @@
left_pad="0"
name="prim_weight"
top_delta="0"
- width="120"
+ width="130"
word_wrap="true">
Land impact: [EQ]
</text>
@@ -1297,7 +1446,7 @@
left_pad="0"
name="download_weight"
top_delta="0"
- width="100"
+ width="130"
word_wrap="true">
Download: [ST]
</text>
@@ -1307,7 +1456,7 @@
layout="topleft"
left_pad="0"
name="physics_weight"
- width="90"
+ width="130"
word_wrap="true">
Physics: [PH]
</text>
@@ -1317,19 +1466,150 @@
layout="topleft"
left_pad="0"
name="server_weight"
- width="83"
+ width="130"
word_wrap="true">
Server: [SIM]
</text>
- <!-- ========== NOTE MESSAGE ========== -->
+ <!-- =========== Cost breakdown ======== -->
+ <panel
+ border="true"
+ top_pad="5"
+ layout="topleft"
+ left="6"
+ name="price_breakdown_panel"
+ width="120"
+ height="100">
+ <text
+ layout="topleft"
+ left="3">
+ Price Breakdown
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="3"
+ name="price_breakdown_border"
+ top_pad="5"
+ width="110"/>
+ <text
+ height="80"
+ top_pad="5"
+ layout="topleft"
+ left="3"
+ name="price_breakdown_labels"
+ width="70"
+ word_wrap="false">
+Download:
+Physics:
+Instances:
+Textures:
+Model:
+ </text>
+ <text
+ height="80"
+ top_delta="0"
+ layout="topleft"
+ halign="right"
+ left_pad="0"
+ name="price_breakdown"
+ width="40"
+ word_wrap="false">
+[STREAMING]
+[PHYSICS]
+[INSTANCES]
+[TEXTURES]
+[MODEL]
+ </text>
+ </panel>
+ <!--
+ Streaming breakdown numbers are available but not fully understood
+ uncommenting the following sections will display the numbers for debugging purposes
+ <text
+ height="80"
+ top_delta="0"
+ layout="topleft"
+ left="130"
+ name="streaming_breakdown_labels"
+ width="65"
+ word_wrap="true">
+Streaming/Download:
+High:
+Medium:
+Low:
+Lowest:
+ </text>
<text
+ height="80"
+ top_delta="0"
+ layout="topleft"
+ left_pad="0"
+ name="streaming_breakdown"
+ width="95"
+ word_wrap="true">
+[STR_TOTAL]
+[STR_HIGH]
+[STR_MED]
+[STR_LOW]
+[STR_LOWEST]
+ </text>-->
+ <panel
+ border="true"
+ layout="topleft"
+ left_pad="265"
+ name="physics_costs_panel"
+ width="120"
+ height="100">
+ <text
+ layout="topleft"
+ left="3">
+ Physics Costs
+ </text>
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="3"
+ name="price_breakdown_border"
+ top_pad="5"
+ width="110"/>
+ <text
+ height="80"
+ top_pad="5"
+ layout="topleft"
+ left="5"
+ name="physics_breakdown_labels"
+ width="65">
+Base Hull:
+Mesh:
+Analysed:
+ </text>
+ <text
+ height="80"
+ top_delta="0"
+ layout="topleft"
+ left_pad="0"
+ name="physics_breakdown"
+ width="40"
+ halign="right"
+ word_wrap="false"
+ visible="true">
+[PCH]
+[PM]
+[PHU]
+ </text>-->
+ </panel>
+ <!-- ========== NOTE MESSAGE ========== -->
+ <text
font="SansSerif"
layout="topleft"
left="6"
name="warning_title"
- top_pad="10"
+ top_pad="5"
text_color="DrYellow"
- visible="false"
+ visible="true"
width="40">
NOTE:
</text>
@@ -1340,44 +1620,51 @@
left_pad="1"
name="warning_message"
parse_urls="true"
- top_delta="2"
+ top_delta="1"
wrap="true"
width="462"
- visible="false">
+ visible="true">
You dont have rights to upload mesh models. [[VURL] Find out how] to get certified.
+ </text>
+ <text
+ text_color="Yellow"
+ layout="topleft"
+ top_pad="-2"
+ left="6"
+ name="status">
+[STATUS]
</text>
- <text text_color="Yellow" layout="topleft" top_delta="20" left="6" name="status">[STATUS]</text>
-
</panel>
-</panel>
-
-<text
- follows="left|top"
- layout="topleft"
- left="640"
- name="lod_label"
- text_color="White"
- top="13"
- height="15"
- width="290">
- Preview:
- </text>
-<panel
- border="true"
- bevel_style="none"
- follows="top|left"
- name="preview_panel"
- top_pad="4"
- width="290"
- height="290"/>
-
-<panel
- follows="all"
- height="130"
- layout="topleft"
- name="right_panel"
- top_pad="5"
- width="340">
+ </panel>
+
+ <text
+ follows="left|top"
+ layout="topleft"
+ left="640"
+ name="lod_label"
+ text_color="White"
+ top="29"
+ height="15"
+ width="290">
+ Preview:
+ </text>
+ <panel
+ follows="all"
+ layout="topleft"
+ border="true"
+ bevel_style="none"
+ name="preview_panel"
+ top_pad="4"
+ width="325"
+ height="408"/>
+ <panel
+ follows="right|bottom"
+ can_resize="false"
+ height="140"
+ layout="topleft"
+ name="right_panel"
+ top_pad="5"
+ width="340">
<combo_box
top_pad="3"
follows="left|top"
@@ -1386,10 +1673,10 @@
name="preview_lod_combo"
width="150"
tool_tip="LOD to view in preview render">
- <combo_item name="high"> High </combo_item>
- <combo_item name="medium"> Medium </combo_item>
- <combo_item name="low"> Low </combo_item>
- <combo_item name="lowest"> Lowest </combo_item>
+ <combo_item name="high"> High </combo_item>
+ <combo_item name="medium"> Medium </combo_item>
+ <combo_item name="low"> Low </combo_item>
+ <combo_item name="lowest"> Lowest </combo_item>
</combo_box>
<text
follows="top|left"
@@ -1436,11 +1723,21 @@
</check_box>
<check_box
follows="top|left"
+ label="Joint position overrides"
+ label_text.text_color="White"
+ word_wrap="down"
+ width="130"
+ layout="topleft"
+ name="show_joint_overrides"
+ top_pad="8">
+ </check_box>
+ <check_box
+ follows="top|left"
label="Joints"
label_text.text_color="White"
layout="topleft"
name="show_joint_positions"
- top_pad="8">
+ top_pad="17">
</check_box>
<text
follows="top|left"
@@ -1460,5 +1757,5 @@
max_val="3.0"
height="20"
width="150"/>
-</panel>
+ </panel>
</floater>
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 e93568a87e..e282f1b179 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
@@ -596,7 +596,10 @@
left="420"
name="TransparentWater"
top_delta="16"
- width="300" />
+ width="300">
+ <check_box.commit_callback
+ function="Pref.RenderOptionUpdate" />
+ </check_box>
<check_box
control_name="RenderObjectBump"
diff --git a/indra/newview/skins/default/xui/en/floater_script_debug.xml b/indra/newview/skins/default/xui/en/floater_script_debug.xml
index cd88048d6b..6c49cfa1a8 100644
--- a/indra/newview/skins/default/xui/en/floater_script_debug.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_debug.xml
@@ -17,5 +17,6 @@
name="Preview Tabs"
tab_position="bottom"
top="16"
- width="448" />
+ width="448"
+ enable_tabs_flashing="true"/>
</multi_floater>
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index a52d0a95d6..3a66911389 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -48,42 +48,28 @@
</text>
<!-- mode selector -->
- <radio_group
+ <combo_box
control_name="mode_selection"
height="20"
layout="topleft"
- left="0"
- top_pad="80"
+ left="6"
+ top_pad="77"
name="mode_selection"
- follows="left|top">
- <radio_item
+ follows="left|top"
+ width="120">
+ <combo_box.item
label="Inventory"
name="inventory"
- top_delta="20"
- layout="topleft"
- height="16"
- left="0"
- value="0"
- width="70" />
- <radio_item
+ value="0" />
+ <combo_box.item
label="Local"
- left_pad="0"
- layout="topleft"
- top_delta="0"
- height="16"
name="local"
- value="1"
- width="50" />
- <radio_item
+ value="1" />
+ <combo_box.item
label="Bake"
- left_pad="0"
- layout="topleft"
- top_delta="0"
- height="16"
name="bake"
- value="2"
- width="50" />
- </radio_group>
+ value="2" />
+ </combo_box>
<!-- -->
<text
@@ -92,21 +78,9 @@
follows="left|top"
height="14"
layout="topleft"
- left_delta="12"
+ left="8"
name="size_lbl"
top_pad="4">
- Size:
- </text>
-
- <text
- type="string"
- length="1"
- follows="left|top"
- height="14"
- layout="topleft"
- left_delta="0"
- name="unknown"
- top_pad="4">
[DIMENSIONS]
</text>
<!-- middle: inventory mode -->
@@ -149,8 +123,8 @@
image_selected="eye_button_active.tga"
image_unselected="eye_button_inactive.tga"
layout="topleft"
- left_delta="-80"
- top_delta="-10"
+ left="18"
+ top_delta="-23"
name="Pipette"
width="28" />
<text
@@ -329,7 +303,7 @@ layout="topleft"
label="OK"
label_selected="OK"
layout="topleft"
- left="95"
+ left="176"
top="-30"
name="Select"
width="100" />
@@ -352,5 +326,5 @@ layout="topleft"
left="6"
name="apply_immediate_check"
top_delta="0"
- width="120" />
+ width="150" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index 76df0abdfd..d88c267a95 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -12,6 +12,7 @@
<file>msyh.ttc</file>
<file load_collection="true">Cambria.ttc</file>
<file>malgun.ttf</file>
+ <file>micross.ttf</file>
</os>
<os name="Mac">
<file>ヒラギノ角ゴシック W3.ttc</file>
@@ -25,6 +26,7 @@
<file>华文细黑.ttf</file>
<file>PingFang.ttc</file>
<file>STIXGeneral.otf</file>
+ <file>Thonburi.ttc</file>
</os>
</font>
diff --git a/indra/newview/skins/default/xui/en/menu_cof_attachment.xml b/indra/newview/skins/default/xui/en/menu_cof_attachment.xml
index c402100fb1..3f545c936d 100644
--- a/indra/newview/skins/default/xui/en/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/en/menu_cof_attachment.xml
@@ -3,6 +3,26 @@
layout="topleft"
name="COF Attachment">
<menu_item_call
+ label="Touch"
+ layout="topleft"
+ name="touch_attach">
+ <on_click
+ function="Attachment.Touch" />
+ <on_enable
+ function="Attachment.OnEnable"
+ parameter="touch" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit_item">
+ <on_click
+ function="Attachment.Edit" />
+ <on_enable
+ function="Attachment.OnEnable"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
label="Detach"
layout="topleft"
name="detach">
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 9aa84c1bac..eda9739976 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -810,14 +810,6 @@
<menu_item_separator
layout="topleft"
name="Wearable And Object Separator"/>
- <menu_item_call
- label="Detach From Yourself"
- layout="topleft"
- name="Detach From Yourself">
- <menu_item_call.on_click
- function="Inventory.DoToSelected"
- parameter="detach" />
- </menu_item_call>
<!-- COMMENTED OUT for DEV-32347 -->
<!--
<menu_item_call
@@ -846,6 +838,14 @@
layout="topleft"
name="Attach To HUD" />
<menu_item_call
+ label="Touch"
+ layout="topleft"
+ name="Attachment Touch">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="touch" />
+ </menu_item_call>
+ <menu_item_call
label="Edit"
layout="topleft"
name="Wearable Edit">
@@ -862,6 +862,14 @@
parameter="wear_add" />
</menu_item_call>
<menu_item_call
+ label="Detach From Yourself"
+ layout="topleft"
+ name="Detach From Yourself">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="detach" />
+ </menu_item_call>
+ <menu_item_call
label="Take Off"
layout="topleft"
name="Take Off">
diff --git a/indra/newview/skins/default/xui/en/menu_script_chiclet.xml b/indra/newview/skins/default/xui/en/menu_script_chiclet.xml
index db29d9cebc..49e52ebb8d 100644
--- a/indra/newview/skins/default/xui/en/menu_script_chiclet.xml
+++ b/indra/newview/skins/default/xui/en/menu_script_chiclet.xml
@@ -16,4 +16,12 @@
function="ScriptChiclet.Action"
parameter="end" />
</menu_item_call>
+ <menu_item_call
+ label="Close All Dialogs"
+ layout="topleft"
+ name="Close All">
+ <menu_item_call.on_click
+ function="ScriptChiclet.Action"
+ parameter="close all" />
+ </menu_item_call>
</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 873b95926b..5fa1847d1b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1733,6 +1733,16 @@ function="World.EnvPreset"
parameter="character" />
</menu_item_check>
<menu_item_check
+ label="Animeshes"
+ name="Rendering Type Control Avatar">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="controlAV" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="controlAV" />
+ </menu_item_check>
+ <menu_item_check
label="Surface Patch"
name="Rendering Type Surface Patch"
shortcut="control|alt|shift|5">
diff --git a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml
index aa56b4ba63..cb429812e2 100644
--- a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml
@@ -23,6 +23,18 @@
function="Wearable.Add" />
</menu_item_call>
<menu_item_call
+ label="Touch"
+ layout="topleft"
+ name="touch"
+ on_click.function="Attachment.Touch"
+ />
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit"
+ on_click.function="Wearable.Edit"
+ />
+ <menu_item_call
label="Take Off / Detach"
layout="topleft"
name="take_off_or_detach">
@@ -52,13 +64,6 @@
function="Clothing.TakeOff" />
</menu_item_call>
<menu_item_call
- label="Edit"
- layout="topleft"
- name="edit">
- <on_click
- function="Wearable.Edit" />
- </menu_item_call>
- <menu_item_call
label="Item Profile"
layout="topleft"
name="object_profile">
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
index 0e858ccf10..57b20dfda9 100644
--- a/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearing_gear.xml
@@ -4,11 +4,24 @@
visible="false"
name="Gear Wearing">
<menu_item_call
- label="Edit Outfit"
+ label="Touch"
+ layout="topleft"
+ name="touch">
+ <on_click
+ function="Gear.TouchAttach" />
+ <on_enable
+ function="Gear.OnEnable"
+ parameter="touch_attach" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
layout="topleft"
- name="edit">
+ name="edit_item">
<on_click
- function="Gear.Edit" />
+ function="Gear.EditItem" />
+ <on_enable
+ function="Gear.OnEnable"
+ parameter="edit_item" />
</menu_item_call>
<menu_item_call
label="Take Off"
@@ -20,6 +33,14 @@
function="Gear.OnEnable"
parameter="take_off" />
</menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Edit Outfit"
+ layout="topleft"
+ name="edit_outfit">
+ <on_click
+ function="Gear.EditOutfit" />
+ </menu_item_call>
<menu_item_call
label="Copy outfit list to clipboard"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
index 75c1de24aa..b8e2b44884 100644
--- a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml
@@ -3,6 +3,20 @@
layout="topleft"
name="Wearing">
<menu_item_call
+ label="Touch"
+ layout="topleft"
+ name="touch_attach">
+ <on_click
+ function="Wearing.TouchAttach" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit"
+ layout="topleft"
+ name="edit_item">
+ <on_click
+ function="Wearing.EditItem" />
+ </menu_item_call>
+ <menu_item_call
label="Take Off"
layout="topleft"
name="take_off">
@@ -23,16 +37,9 @@
<menu_item_call
label="Edit Outfit"
layout="topleft"
- name="edit">
+ name="edit_outfit">
<on_click
- function="Wearing.Edit" />
- </menu_item_call>
- <menu_item_call
- label="Edit"
- layout="topleft"
- name="edit_item">
- <on_click
- function="Wearing.EditItem" />
+ function="Wearing.EditOutfit" />
</menu_item_call>
<menu_item_call
label="Show Original"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 32ae56e3af..29d570de64 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1343,6 +1343,18 @@ You must agree to the Second Life Terms and Conditions, Privacy Policy, and Term
<notification
icon="alertmodal.tga"
+ name="CouldNotBuyCurrency"
+ type="alertmodal">
+[TITLE]
+[MESSAGE]
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CouldNotPutOnOutfit"
type="alertmodal">
Could not put on outfit.
@@ -3174,7 +3186,7 @@ Do you want to remove multiple friends from your Friends list?
type="alertmodal">
Are you sure you want to delete all scripted objects owned by
** [AVATAR_NAME] **
-on all others land in this sim?
+on all others land in this region?
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
@@ -3188,7 +3200,7 @@ on all others land in this sim?
type="alertmodal">
Are you sure you want to DELETE ALL scripted objects owned by
** [AVATAR_NAME] **
-on ALL LAND in this sim?
+on ALL LAND in this region?
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
@@ -3202,7 +3214,7 @@ on ALL LAND in this sim?
type="alertmodal">
Are you sure you want to DELETE ALL objects (scripted or not) owned by
** [AVATAR_NAME] **
-on ALL LAND in this sim?
+on ALL LAND in this region?
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
@@ -3680,6 +3692,17 @@ Could not teleport to [SLURL] as it's on a different grid ([GRID]) than the curr
</notification>
<notification icon="alertmodal.tga"
+ name="GeneralCertificateErrorShort"
+ type="alertmodal">
+Could not connect to the server.
+[REASON]
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification icon="alertmodal.tga"
name="GeneralCertificateError"
type="alertmodal">
Could not connect to the server.
@@ -9545,6 +9568,12 @@ Do you wish to continue?
yestext="OK"/>
</notification>
+ <global name="UnsupportedShaderRequirements">
+You do not appear to meet the hardware requirements for [APP_NAME]. [APP_NAME] requires OpenGL 2.0 or later shader support. If this is the case, you may want to make sure that you have the latest drivers for your graphics card, and service packs and patches for your operating system.
+
+If you continue to have problems, please visit the [SUPPORT_SITE].
+ </global>
+
<global name="UnsupportedGLRequirements">
You do not appear to have the proper hardware requirements for [APP_NAME]. [APP_NAME] requires an OpenGL graphics card that has multitexture support. If this is the case, you may want to make sure that you have the latest drivers for your graphics card, and service packs and patches for your operating system.
@@ -10267,7 +10296,7 @@ Unable to add script!
name="AssetServerTimeoutObjReturn"
type="notify">
<tag>fail</tag>
-Asset server didn't respond in a timely fashion. Object returned to sim.
+Asset server didn't respond in a timely fashion. Object returned to the region.
</notification>
<notification
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index 13986c4030..7935d66aee 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -41,7 +41,7 @@
</string>
<string
name="acquired_date">
- [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ [wkday,datetime,slt] [mth,datetime,slt] [day,datetime,slt] [hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt] [year,datetime,slt]
</string>
<!-- Texture names for rating icons -->
<string
@@ -95,7 +95,7 @@
<panel
bg_alpha_color="DkGray2"
follows="left|top|right"
- height="630"
+ height="654"
layout="topleft"
left="0"
min_height="300"
@@ -112,35 +112,56 @@
name="logo"
top="10"
width="290" />
+ <!-- texture picker has an empty label section, compensate for it with negative top_pad-->
<text
follows="left|top|right"
font="SansSerifLarge"
height="14"
layout="topleft"
left="10"
- name="region_title"
+ top_pad="-10"
+ width="280"
+ name="parcel_title"
text_color="white"
- top_pad="10"
use_ellipses="true"
- value="SampleRegion"
- width="280" />
+ value="SampleParcel, Name Long" />
<text
follows="left|top|right"
height="14"
layout="topleft"
left="10"
- name="parcel_title"
- top_pad="10"
+ top_pad="9"
+ width="280"
+ name="region_title"
+ use_ellipses="true">
+ Region: [REGIONAMEPOS]
+ </text>
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="parcel_owner_label"
+ top_pad="7"
+ value="Owner:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="parcel_owner"
+ top_delta="0"
use_ellipses="true"
- value="SampleParcel, Name Long (145, 228, 26)"
- width="280" />
+ value="TempOwner"
+ width="215" />
<expandable_text
follows="left|top|right"
height="50"
layout="topleft"
left="10"
name="description"
- top_pad="10"
+ top_pad="7"
value="Du waltz die spritz"
width="280" />
<icon
@@ -163,19 +184,38 @@
width="268" />
<panel
follows="left|top|right"
- height="55"
+ height="81"
layout="topleft"
left="10"
name="landmark_info_panel"
top_pad="10"
width="290">
+ <view_border
+ bevel_style="none"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ left="0"
+ name="lod_tab_border"
+ top_pad="5"
+ width="290" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="0"
+ name="this_landmark"
+ top_pad="8"
+ width="90">
+ This landmark:
+ </text>
<text
follows="left|top"
height="15"
layout="topleft"
left="0"
name="owner_label"
- top_pad="10"
+ top_pad="8"
value="Owner:"
width="90" />
<text
@@ -237,9 +277,13 @@
top_pad="10"
value="Title:"
width="290" />
- <text
+ <line_editor
+ text_readonly_color="white"
+ enabled="false"
+ use_bg_color="true"
+ bg_color="DkGray0"
parse_urls="false"
- follows="left|top"
+ follows="left|top|right"
height="22"
layout="topleft"
left="0"
@@ -269,7 +313,7 @@
value="My notes:"
width="290" />
<text_editor
- bg_readonly_color="DkGray2"
+ bg_readonly_color="DkGray0"
follows="all"
height="75"
layout="topleft"
@@ -300,6 +344,17 @@
name="folder_combo"
top_pad="5"
width="200" />
+ <button
+ follows="bottom|left|right"
+ height="23"
+ label="Edit"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="edit_btn"
+ tool_tip="Edit landmark information"
+ top_pad="-42"
+ width="100" />
</panel>
</panel>
</scroll_container>
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index eeb930485e..6c8cc9d39a 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -30,7 +30,6 @@
tab_height="30"
tab_position="top"
halign="center"
- hide_scroll_arrows="true"
top="8"
width="315">
<panel
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index 0dd75b1b55..36b7b0501b 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -200,7 +200,7 @@
<panel
bg_alpha_color="DkGray2"
follows="left|top|right|bottom"
- height="580"
+ height="597"
layout="topleft"
left="0"
min_height="300"
@@ -277,32 +277,25 @@
height="14"
layout="topleft"
left="10"
- name="region_title"
- text_color="white"
top_pad="5"
+ width="290"
+ name="parcel_title"
+ text_color="white"
use_ellipses="true"
- value="SampleRegion"
- width="290" />
+ value="SampleParcel" />
<text
parse_urls="false"
follows="left|top|right"
height="14"
layout="topleft"
left="10"
- name="parcel_title"
- top_pad="4"
- use_ellipses="true"
- value="SampleParcel, Name Long (145, 228, 26)"
- width="285" />
- <expandable_text
- follows="left|top"
- height="50"
- layout="topleft"
- left="5"
- name="description"
- top_pad="10"
- value="Du waltz die spritz"
- width="285" />
+ top_pad="5"
+ width="285"
+ name="region_title"
+ text_color="White"
+ use_ellipses="true">
+ Region: [REGIONAMEPOS]
+ </text>
<text
follows="left|top"
height="14"
@@ -310,20 +303,28 @@
left="10"
name="owner_label"
text_color="White"
- top_pad="0"
+ top_pad="2"
value="Owner:"
- width="90" />
- <!--TODO: HOOK THIS NAME UP WITH AN INSPECTOR -->
+ width="80" />
<text
follows="left|top|right"
height="14"
layout="topleft"
- left_pad="1"
- name="owner_value"
+ left_pad="0"
+ name="parcel_owner"
top_delta="0"
value="Alex Superduperlongenamenton"
use_ellipses="true"
width="200" />
+ <expandable_text
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left="5"
+ name="description"
+ top_pad="10"
+ value="Du waltz die spritz"
+ width="285" />
<icon
follows="top|left"
height="16"
@@ -331,7 +332,7 @@
layout="topleft"
left="10"
name="maturity_icon"
- top_delta="0"
+ top_pad="0"
width="18" />
<text
follows="left|top|right"
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 7d171490e8..1f32ae53ba 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -82,6 +82,7 @@ background_visible="true"
layout="topleft"
mouse_opaque="false"
name="bottom_bar_ls0"
+ animate="false"
left="4"
orientation="horizontal"
top="0"
@@ -150,8 +151,32 @@ background_visible="true"
width="85" />
</layout_panel>
</layout_stack>
- </layout_panel>
-
+ </layout_panel>
+ <!--*********************** Options button ***********************-->
+ <layout_panel
+ follows="bottom|right"
+ height="23"
+ layout="bottomleft"
+ left_pad="0"
+ mouse_opaque="false"
+ visible="false"
+ name="lp_options"
+ auto_resize="false"
+ width="23">
+ <menu_button
+ follows="bottom|right"
+ height="23"
+ image_disabled="ComboButton_UpOff"
+ image_unselected="ComboButton_UpOff"
+ image_selected="ComboButton_UpSelected"
+ layout="topleft"
+ mouse_opaque="false"
+ name="overflow_btn"
+ tool_tip="Show additional options"
+ top="0"
+ left="0"
+ width="23" />
+ </layout_panel>
<layout_panel
follows="bottom|left|right"
height="23"
@@ -159,69 +184,9 @@ background_visible="true"
left_pad="0"
mouse_opaque="false"
name="lp2"
- auto_resize="true"
+ auto_resize="true"
width="116">
-
- <!--*********************** Edit, Options buttons ***********************-->
-
- <layout_stack
- follows="bottom|left|right"
- height="23"
- layout="topleft"
- mouse_opaque="false"
- name="bottom_bar_ls3"
- left="0"
- orientation="horizontal"
- top="0"
- width="113">
-
- <layout_panel
- follows="bottom|left|right"
- height="23"
- layout="bottomleft"
- left_pad="0"
- mouse_opaque="false"
- name="edit_btn_lp"
- auto_resize="true"
- width="84">
- <button
- follows="bottom|left|right"
- height="23"
- label="Edit"
- layout="topleft"
- left="1"
- mouse_opaque="false"
- name="edit_btn"
- tool_tip="Edit landmark information"
- top="0"
- width="83" />
- </layout_panel>
-
- <layout_panel
- follows="bottom|right"
- height="23"
- layout="bottomleft"
- left_pad="0"
- mouse_opaque="false"
- name="overflow_btn_lp"
- auto_resize="true"
- width="24">
- <menu_button
- follows="bottom|right"
- height="23"
- image_disabled="ComboButton_UpOff"
- image_unselected="ComboButton_UpOff"
- image_selected="ComboButton_UpSelected"
- layout="topleft"
- mouse_opaque="false"
- name="overflow_btn"
- tool_tip="Show additional options"
- top="0"
- left="1"
- width="23" />
- </layout_panel>
- </layout_stack>
-
+
<!--*********************** Profile button ***********************-->
<layout_stack
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index ece6c95080..c023cb036e 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -52,7 +52,7 @@
</check_box>
<check_box
- control_name="VoiceCallsFriendsOnly"
+ enabled="false"
height="16"
label="Only friends and groups can call or IM me"
layout="topleft"
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 c2defdd772..65b9a64111 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -514,12 +514,12 @@
follows="left|top"
height="23"
is_toggle="true"
- label="Input/Output devices"
+ label="Voice Input/Output devices"
layout="topleft"
left="20"
top_pad="6"
name="device_settings_btn"
- width="190">
+ width="230">
</button>
<panel
layout="topleft"
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 bec793bbee..6f82a0efa1 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
@@ -203,10 +203,10 @@
Ice Level:
</text>
<slider
- decimal_digits="1"
+ decimal_digits="3"
follows="left|top"
height="14"
- increment="0.1"
+ increment="0.001"
initial_value="0"
left_delta="5"
top_delta="20"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index 2a1eb425ed..1777a0db05 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -32,7 +32,7 @@ width="333">
top="5"
follows="left|top|right"
layout="topleft"
- width="303"
+ width="307"
height="33"
name="panel_currentlook"
>
@@ -118,14 +118,14 @@ width="333">
name="Filter"
search_button_visible="true"
top_pad="10"
- width="303" />
+ width="307" />
<panel
class="panel_outfits_inventory"
filename="panel_outfits_inventory.xml"
name="panel_outfits_inventory"
height="493"
min_height="410"
- width="320"
+ width="325"
visible="false"
left="0"
tab_group="1"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
index acb6f5b42a..9a68479d05 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -33,7 +33,7 @@
</panel.string>
<panel.string
name="acquiredDate">
- [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ [wkday,datetime,slt] [mth,datetime,slt] [day,datetime,slt] [hour,datetime,slt]:[min,datetime,slt]:[second,datetime,slt] [year,datetime,slt]
</panel.string>
<panel.string
name="origin_inventory">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1bfac6aeb7..f9f12e7f5c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -28,7 +28,7 @@
<string name="BuildConfig">Build Configuration [BUILD_CONFIG]</string>
<string name="AboutPosition">
-You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(global coordinates [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -107,7 +107,9 @@ Voice Server Version: [VOICE_VERSION]
<string name="CertExpired">The certificate returned by the Grid appears to be expired. Please check your system clock, or contact your Grid administrator.</string>
<string name="CertKeyUsage">The certificate returned by the server could not be used for SSL. Please contact your Grid administrator.</string>
<string name="CertBasicConstraints">Too many certificates were in the servers Certificate chain. Please contact your Grid administrator.</string>
+ <string name="CertInvalid">Could not load certificate. Please contact your Grid administrator.</string>
<string name="CertInvalidSignature">The certificate signature returned by the Grid server could not be verified. Please contact your Grid administrator.</string>
+ <string name="CertAllocationFailure">Failed to allocate openssl memory for certificate.</string>
<string name="LoginFailedNoNetwork">Network error: Could not establish connection, please check your network connection.</string>
<string name="LoginFailed">Login failed.</string>
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index dbff3fcf0e..086150dd57 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,8 +60,7 @@ no el objeto.
</text>
<button label="Comprar ahora" name="buy_btn"/>
<button label="Cancelar" name="cancel_btn"/>
- <text name="info_cannot_buy" left="150" font="SansSerifBig">
+ <floater.string name="info_cannot_buy">
No se pudo hacer la compra
- </text>
- <button label="Ir a la web" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
index 2e409ef69c..a77dd99af0 100644
--- a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Texturas múltiples
</text>
- <radio_group name="mode_selection">
- <radio_item label="Inventario" name="inventory" value="0"/>
- <radio_item label="Local" name="local" value="1"/>
- <radio_item label="Hornear" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Tamaño: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Inventario" name="inventory" value="0"/>
+ <combo_box.item label="Local" name="local" value="1"/>
+ </combo_box>
<button label="Por defecto" label_selected="Por defecto" name="Default" width="84"/>
<button label="Blanca" label_selected="Blanca" name="Blank"/>
<button label="Ninguna" label_selected="Ninguna" left="90" name="None"/>
diff --git a/indra/newview/skins/default/xui/es/menu_cof_attachment.xml b/indra/newview/skins/default/xui/es/menu_cof_attachment.xml
index 7541530601..65e31c0654 100644
--- a/indra/newview/skins/default/xui/es/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/es/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Tocar" name="touch_attach" />
+ <menu_item_call label="Editar" name="edit_item" />
<menu_item_call label="Quitar" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/es/menu_inventory.xml b/indra/newview/skins/default/xui/es/menu_inventory.xml
index c426158d3e..d855d6f04f 100644
--- a/indra/newview/skins/default/xui/es/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/es/menu_inventory.xml
@@ -104,6 +104,7 @@
<menu_item_call label="Ponerme" name="Wearable And Object Wear"/>
<menu label="Anexar a" name="Attach To"/>
<menu label="Anexar como HUD" name="Attach To HUD"/>
+ <menu_item_call label="Tocar" name="Attachment Touch" />
<menu_item_call label="Editar" name="Wearable Edit"/>
<menu_item_call label="Añadir" name="Wearable Add"/>
<menu_item_call label="Quitarse" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/es/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/es/menu_wearable_list_item.xml
index 4bffa689e7..cb68ad39a4 100644
--- a/indra/newview/skins/default/xui/es/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/es/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Reemplazar" name="wear_replace"/>
<menu_item_call label="Ponerme" name="wear_wear"/>
<menu_item_call label="Añadir" name="wear_add"/>
+ <menu_item_call label="Tocar" name="touch" />
<menu_item_call label="Quitarme / Quitar" name="take_off_or_detach"/>
<menu_item_call label="Quitar" name="detach"/>
<context_menu label="Anexar a" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/es/menu_wearing_gear.xml b/indra/newview/skins/default/xui/es/menu_wearing_gear.xml
index ec13f99a01..01d1b16b58 100644
--- a/indra/newview/skins/default/xui/es/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/es/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Editar el vestuario" name="edit"/>
+ <menu_item_call label="Tocar" name="touch"/>
+ <menu_item_call label="Editar" name="edit_item"/>
+ <menu_item_call label="Editar el vestuario" name="edit_outfit"/>
<menu_item_call label="Quitarme" name="takeoff"/>
<menu_item_call label="Copiar la lista del vestuario al portapapeles" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/es/menu_wearing_tab.xml b/indra/newview/skins/default/xui/es/menu_wearing_tab.xml
index 637a14cf5b..54a7d9b92c 100644
--- a/indra/newview/skins/default/xui/es/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/es/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Tocar" name="touch_attach"/>
<menu_item_call label="Quitarme" name="take_off"/>
<menu_item_call label="Quitar" name="detach"/>
- <menu_item_call label="Editar el vestuario" name="edit"/>
+ <menu_item_call label="Editar el vestuario" name="edit_outfit"/>
<menu_item_call label="Editar" name="edit_item"/>
<menu_item_call label="Mostrar original" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 86e3b5d38b..c7750320d5 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -265,6 +265,10 @@ La inicialización del mercado ha fallado por un error del sistema o de la red.
¿Quieres revocar los derechos de modificación a los residentes seleccionados?
<usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ El nombre de un grupo debe contener entre [MIN_LEN] y [MAX_LEN] caracteres.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
No se ha podido crear el grupo.
[MESSAGE]
@@ -356,7 +360,7 @@ Si no quieres que este rol siga teniendo dichas capacidades, deshabilítalas inm
No tienes dinero suficiente para entrar.
</notification>
<notification name="CreateGroupCost">
- Crear este grupo te costará 100 L$.
+ Crear este grupo costará L$[COST].
Los grupos necesitan más de un miembro. Si no, son borrados permanentemente.
Por favor, invita a miembros en las próximas 48 horas.
<usetemplate canceltext="Cancelar" name="okcancelbuttons" notext="Cancelar" yestext="Crear un grupo por 100 L$"/>
@@ -498,6 +502,9 @@ debes estar dentro de ella.
<notification name="ErrorEncodingSnapshot">
Error al codificar la foto.
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Necesitas L$[COST] para subir este objeto.
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Necesitas [COST] L$ para guardar una foto en el inventario. Puedes comprar L$ o bien guardar la foto en tu equipo.
</notification>
@@ -1745,11 +1752,14 @@ Haz clic en OK para instalar.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- El límite de grupos para las cuentas básicas es de [MAX_BASIC], y para
-las cuentas [https://secondlife.com/premium/ Premium] es de [MAX_PREMIUM].
-Si has bajado la categoría de tu cuenta, tendrás que estar por debajo del límite de [MAX_BASIC] grupos para poder apuntarte a más grupos.
-
-[https://secondlife.com/my/account/membership.php Cámbiate hoy a Premium]
+ Los residentes con membresías Básicas pueden unirse a hasta [MAX_BASIC] grupos.
+Las membresías Premium permiten hasta [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Aprende más al respecto o mejora tu membresía]
+ <usetemplate name="okbutton" yestext="Cerrar"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ Los residentes con membresías Básicas pueden unirse a hasta [MAX_BASIC] cinco grupos.
+Las membresías Premium permiten hasta [MAX_PREMIUM]. Las membresías Premium Plus permiten
+hasta [MAX_PREMIUM_PLUS]. [https://secondlife.com/my/account/membership.php? Aprende más al respecto o mejora tu membresía]
<usetemplate name="okbutton" yestext="Cerrar"/>
</notification>
<notification name="KickUser">
@@ -3304,6 +3314,22 @@ Por tu seguridad, serán bloqueadas durante unos segundos.
Un moderador ha silenciado tu voz.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ Desafortunadamente no fuimos capaces de obtener información sobre los beneficios para esta sesión. Esto no debería suceder en un espacio de producción normal. Por favor contacte con soporte. Esta sesión no funcionara normalmente y recomendamos reiniciar.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Esto subirá [COUNT] objetos por un costo total de L$[COST]. ¿Deseas continuar con la subida?
+ <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Subir"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ Los archivos seleccionados no pueden ser subidos en grupo.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Algunos de los archivos seleccionados no pueden ser subidos en grupo.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
Esta carga te costará [PRECIO] L$. ¿Deseas continuar?
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Subir"/>
diff --git a/indra/newview/skins/default/xui/es/panel_people.xml b/indra/newview/skins/default/xui/es/panel_people.xml
index 909743c325..73b9af3665 100644
--- a/indra/newview/skins/default/xui/es/panel_people.xml
+++ b/indra/newview/skins/default/xui/es/panel_people.xml
@@ -18,7 +18,7 @@
<string name="no_groups_msg" value="¿Buscas grupos en que participar? Prueba la [secondlife:///app/search/groups Búsqueda]."/>
<string name="MiniMapToolTipMsg" value="[REGION](Pulsa dos veces para abrir el mapa, pulsa mayús y arrastra para obtener una panorámica)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Pulsa dos veces para teleportarte, pulsa mayús y arrastra para obtener una panorámica)"/>
- <string name="GroupCountWithInfo" value="Perteneces a [COUNT] grupos y puedes unirte a [REMAINING] más. [secondlife:/// ¿Quieres más?]"/>
+ <string name="GroupCountWithInfo" value="Perteneces a [COUNT] grupos y puedes unirte a [REMAINING] más. [secondlife:/// Incrementa tu límite]"/>
<tab_container name="tabs">
<panel label="CERCANA" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@
<dnd_button name="minus_btn" tool_tip="Dejar el grupo seleccionado"/>
</panel>
<text name="groupcount">
- Formas parte de [COUNT] grupos y puedes unirte a [REMAINING] más.
+ Perteneces a [COUNT] grupos y puedes unirte a [REMAINING] más.
</text>
</panel>
<panel label="RECIENTE" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml
index 007101b8fe..0ba676898f 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_advanced.xml
@@ -28,5 +28,5 @@
<check_box label="Mostrar la selección de cuadrícula al iniciar sesión" name="show_grid_selection_check"/>
<check_box label="Mostrar el menú Avanzado" name="show_advanced_menu_check"/>
<check_box label="Mostrar el menú Desarrollar" name="show_develop_menu_check"/>
- <button label="Permisos de creación predeterminados" name="default_creation_permissions"/>
+ <button label="Permisos de creación predeterminados" name="default_creation_permissions" width="235"/>
</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml
index 816c698548..47815d0296 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_graphics1.xml
@@ -32,10 +32,10 @@
</text>
<check_box initial_value="true" label="Renderizar siempre los amigos" name="AlwaysRenderFriends"/>
<button label="Excepciones..." name="RenderExceptionsButton"/>
- <button label="Guardar configuración como valor predefinido..." name="PrefSaveButton"/>
- <button label="Cargar predefinido..." name="PrefLoadButton"/>
+ <button label="Guardar configuración como valor predefinido" name="PrefSaveButton" width="260" left="5"/>
+ <button label="Cargar predefinido" name="PrefLoadButton" left_pad="7"/>
min_val=&quot;0.125&quot;
- <button label="Eliminar predefinido..." name="PrefDeleteButton"/>
- <button label="Restablecer la configuración recomendada" name="Defaults"/>
+ <button label="Eliminar predefinido" name="PrefDeleteButton" width="117" left_pad="7"/>
+ <button label="Restablecer la configuración recomendada" name="Defaults" width="248"/>
<button label="Configuración avanzada..." name="AdvancedSettings"/>
</panel>
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index af66907f8d..f5e7d0bf4e 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -1628,11 +1628,14 @@ Si sigues recibiendo el mismo mensaje, solicita ayuda al personal de asistencia
<string name="MarketplaceUpdating">
actualizando...
</string>
+ <string name="UploadFeeInfo">
+ Las tasas se basan en tu nivel de suscripción. Niveles más altos tienen tasas más bajas. [https://secondlife.com/my/account/membership.php? Aprende más al respecto]
+ </string>
<string name="Open landmarks">
- Abrir hitos
+ Abrir puntos destacados
</string>
<string name="Unconstrained">
- Sin restricciones
+ Sin Restricciones
</string>
<string name="no_transfer" value="(no transferible)"/>
<string name="no_modify" value="(no modificable)"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index c295172abf..55b0d1825a 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,8 +60,7 @@ le Lindex...
</text>
<button label="Acheter" name="buy_btn"/>
<button label="Annuler" name="cancel_btn"/>
- <text name="info_cannot_buy" left="160" width="200">
+ <floater.string name="info_cannot_buy" left="160" width="200">
Achat impossible
- </text>
- <button label="Accéder au Web" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
index 2925727b48..a4de7954c5 100644
--- a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Textures multiples
</text>
- <radio_group name="mode_selection">
- <radio_item label="Inventaire" name="inventory" value="0"/>
- <radio_item label="Local" name="local" value="1"/>
- <radio_item label="Figer" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Taille : [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Inventaire" name="inventory" value="0"/>
+ <combo_box.item label="Local" name="local" value="1"/>
+ </combo_box>
<button label="Défaut" label_selected="Défaut" name="Default" width="60"/>
<button label="Vierge" label_selected="Vierge" name="Blank" width="60"/>
<button label="Aucune" label_selected="Aucune" left="68" name="None" width="60"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_cof_attachment.xml b/indra/newview/skins/default/xui/fr/menu_cof_attachment.xml
index a4ead48b6b..32bc564d72 100644
--- a/indra/newview/skins/default/xui/fr/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/fr/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Toucher" name="touch_attach" />
+ <menu_item_call label="Modifier" name="edit_item" />
<menu_item_call label="Détacher" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_inventory.xml b/indra/newview/skins/default/xui/fr/menu_inventory.xml
index f81723e6cf..5d66d0998b 100644
--- a/indra/newview/skins/default/xui/fr/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="Porter" name="Wearable And Object Wear"/>
<menu label="Attacher à" name="Attach To"/>
<menu label="Attacher au HUD " name="Attach To HUD"/>
+ <menu_item_call label="Toucher" name="Attachment Touch" />
<menu_item_call label="Modifier" name="Wearable Edit"/>
<menu_item_call label="Ajouter" name="Wearable Add"/>
<menu_item_call label="Enlever" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/fr/menu_wearable_list_item.xml
index 187cb4bcd2..a222de298f 100644
--- a/indra/newview/skins/default/xui/fr/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/fr/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Remplacer" name="wear_replace"/>
<menu_item_call label="Porter" name="wear_wear"/>
<menu_item_call label="Ajouter" name="wear_add"/>
+ <menu_item_call label="Toucher" name="touch" />
<menu_item_call label="Enlever / Détacher" name="take_off_or_detach"/>
<menu_item_call label="Détacher" name="detach"/>
<context_menu label="Attacher à" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_wearing_gear.xml b/indra/newview/skins/default/xui/fr/menu_wearing_gear.xml
index c3d9d908b0..90b5ece574 100644
--- a/indra/newview/skins/default/xui/fr/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/fr/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Modifier la tenue" name="edit"/>
+ <menu_item_call label="Toucher" name="touch"/>
+ <menu_item_call label="Modifier" name="edit_item"/>
+ <menu_item_call label="Modifier la tenue" name="edit_outfit"/>
<menu_item_call label="Enlever" name="takeoff"/>
<menu_item_call label="Copier la liste de la tenue dans le presse-papiers" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_wearing_tab.xml b/indra/newview/skins/default/xui/fr/menu_wearing_tab.xml
index 5a7193a7cc..af115b956e 100644
--- a/indra/newview/skins/default/xui/fr/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/fr/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Toucher" name="touch_attach"/>
<menu_item_call label="Enlever" name="take_off"/>
<menu_item_call label="Détacher" name="detach"/>
- <menu_item_call label="Modifier la tenue" name="edit"/>
+ <menu_item_call label="Modifier la tenue" name="edit_outfit"/>
<menu_item_call label="Modifier" name="edit_item"/>
<menu_item_call label="Afficher l’original" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index 41e4ad13f9..e84de375d8 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -266,6 +266,10 @@ Souhaitez-vous accorder des droits d&apos;édition aux résidents sélectionnés
Souhaitez-vous retirer les droits d&apos;édition aux résidents selectionnés ?
<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ Un nom de groupe doit être compris entre [MIN_LEN] et [MAX_LEN] caractères.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
Impossible de créer le groupe.
[MESSAGE]
@@ -359,7 +363,7 @@ Souhaitez-vous continuer ?
Vous n&apos;avez pas suffisamment de L$ pour rejoindre ce groupe.
</notification>
<notification name="CreateGroupCost">
- La création de ce groupe coûte 100 L$.
+ La création de ce groupe coûtera L$[COST].
Les groupes doivent comporter plus d&apos;un membre, sinon ils sont supprimés.
Veuillez inviter des membres d&apos;ici 48 heures.
<usetemplate canceltext="Annuler" name="okcancelbuttons" notext="Annuler" yestext="Créer un groupe pour 100 L$"/>
@@ -500,6 +504,9 @@ Pour ne placer le média que sur une seule face, choisissez Sélectionner une fa
<notification name="ErrorEncodingSnapshot">
Erreur d&apos;encodage de la photo.
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Vous avez besoin de L$[COST] pour charger cet élément.
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Il vous faut [COST] L$ pour enregistrer une photo dans votre inventaire. Vous pouvez acheter des L$ ou enregistrer la photo sur votre ordinateur.
</notification>
@@ -1736,11 +1743,14 @@ Quitter le groupe ?
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- Le nombre de groupes maximum est [MAX_BASIC] pour les comptes basiques et
-[MAX_PREMIUM] pour les comptes [https://secondlife.com/premium/ premium].
-Si vous avez rétrogradé votre compte, vous devez réduire votre nombre de groupes pour passer sous le nombre de groupes maximum ([MAX_BASIC]) avant de pouvoir en rejoindre d’autres.
-
-[https://secondlife.com/my/account/membership.php Mettez à niveau dès aujourd’hui !]
+ Les résidents ayant une adhésion de base peuvent s'inscrire à [MAX_BASIC] groupes maximum.
+Les adhésions premium permettent jusqu'à [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? En savoir plus ou actualiser]
+ <usetemplate name="okbutton" yestext="Fermer"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ Les résidents ayant une adhésion de base peuvent s'inscrire à [MAX_BASIC] groupes maximum.
+Les adhésions premium permettent jusqu'à [MAX_PREMIUM]. Les adhésions à Premium Plus permettent
+jusqu'à [MAX_PREMIUM_PLUS]. [https://secondlife.com/my/account/membership.php? En savoir plus ou actualiser]
<usetemplate name="okbutton" yestext="Fermer"/>
</notification>
<notification name="KickUser">
@@ -3304,6 +3314,22 @@ Elles vont être bloquées pendant quelques secondes pour votre sécurité.
Le modérateur ignore vos paroles.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ Malheureusement, nous n'avons pas pu obtenir d'informations sur les avantages pour cette session. Cela ne devrait pas se produire dans un environnement de production normal. Veuillez contacter le service d'assistance. Cette session ne fonctionnera pas normalement et nous vous recommandons de recommencer.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Ceci permettra de charger [COUNT] éléments pour un coût total de L$[COST]. Souhaitez-vous poursuivre le téléchargement ?
+ <usetemplate name="okcancelbuttons" notext="Annuler" yestext="Charger"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ Les fichiers sélectionnés ne peuvent pas être téléchargés en masse.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Certains des fichiers sélectionnés ne peuvent pas être téléchargés en masse.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
Ce chargement coûtera [PRICE] L$. Continuer ?
<usetemplate name="okcancelbuttons" notext="Annuler" yestext="Charger"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_people.xml b/indra/newview/skins/default/xui/fr/panel_people.xml
index 95cd13eb94..3be6bae52a 100644
--- a/indra/newview/skins/default/xui/fr/panel_people.xml
+++ b/indra/newview/skins/default/xui/fr/panel_people.xml
@@ -18,7 +18,7 @@ Pour rechercher des résidents avec qui passer du temps, utilisez [secondlife://
<string name="no_groups_msg" value="Vous souhaitez trouver des groupes à rejoindre ? Utilisez [secondlife:///app/search/groups Rechercher]."/>
<string name="MiniMapToolTipMsg" value="[REGION](Carte : double-clic ; Panoramique : Maj + faire glisser)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Téléportation : double-clic ; Panoramique : Maj + faire glisser)"/>
- <string name="GroupCountWithInfo" value="Vous appartenez à [COUNT] groupes, et pouvez en rejoindre [REMAINING] autres. [secondlife:/// Vous en voulez plus ?]"/>
+ <string name="GroupCountWithInfo" value="Vous appartenez à [COUNT] groupes et pouvez rejoindre [REMAINING] autres groupes. [secondlife:/// Augmentez votre limite]"/>
<tab_container name="tabs">
<panel label="PRÈS DE VOUS" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@ Pour rechercher des résidents avec qui passer du temps, utilisez [secondlife://
<dnd_button name="minus_btn" tool_tip="Quitter le groupe sélectionné"/>
</panel>
<text name="groupcount">
- Vous appartenez à [COUNT] groupes, et pouvez en rejoindre [REMAINING] autres.
+ Vous appartenez à [COUNT] groupes et pouvez rejoindre [REMAINING] autres groupes.
</text>
</panel>
<panel label="RÉCENT" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml
index 7117ace7e1..46d6305290 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_graphics1.xml
@@ -32,10 +32,10 @@
</text>
<check_box initial_value="true" label="Toujours effectuer le rendu des amis" name="AlwaysRenderFriends"/>
<button label="Exceptions..." name="RenderExceptionsButton"/>
- <button label="Enregistrer les paramètres comme préréglage..." name="PrefSaveButton"/>
- <button label="Charger un préréglage..." name="PrefLoadButton"/>
+ <button label="Enregistrer les paramètres comme préréglage" name="PrefSaveButton" width="260" />
+ <button label="Charger un préréglage" name="PrefLoadButton" width="132"/>
min_val=&quot;0,125&quot;
- <button label="Supprimer un préréglage..." name="PrefDeleteButton"/>
- <button label="Réinitialiser les paramètres recommandés" name="Defaults"/>
+ <button label="Supprimer un préréglage" name="PrefDeleteButton" width="148" top_delta="30" left_pad="-220"/>
+ <button label="Réinitialiser les paramètres recommandés" name="Defaults" width="255" top_delta="35"/>
<button label="Paramètres avancés" name="AdvancedSettings"/>
</panel>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 6d40ab4bc9..f26eac545a 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -1646,11 +1646,14 @@ Si vous continuez de recevoir ce message, contactez l’assistance Second Life
<string name="MarketplaceUpdating">
mise à jour...
</string>
+ <string name="UploadFeeInfo">
+ Les frais dépendent de votre niveau d'abonnement. Les niveaux supérieurs sont soumis à des frais moins élevés. [https://secondlife.com/my/account/membership.php? En savoir plus]
+ </string>
<string name="Open landmarks">
- Ouvrir les repères
+ Points de repère ouverts
</string>
<string name="Unconstrained">
- Sans contraintes
+ Sans contrainte
</string>
<string name="no_transfer" value=" (pas de transfert)"/>
<string name="no_modify" value=" (pas de modification)"/>
@@ -5097,6 +5100,15 @@ Veuillez vous reporter à http://status.secondlifegrid.net afin de déterminer s
<string name="Chat" value=" Chat :">
Chat
</string>
+ <string name="BaseMembership">
+ Base
+ </string>
+ <string name="PremiumMembership">
+ Premium
+ </string>
+ <string name="Premium PlusMembership">
+ Premium Plus
+ </string>
<string name="DeleteItems">
Supprimer les articles sélectionnés ?
</string>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 53a2057455..522d26373e 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,8 +60,7 @@ l&apos;oggetto.
</text>
<button label="Acquista" name="buy_btn"/>
<button label="Annulla" name="cancel_btn"/>
- <text name="info_cannot_buy" left="160" font="SansSerifBig">
+ <floater.string name="info_cannot_buy" left="160" font="SansSerifBig">
Non in grado di acquistare
- </text>
- <button label="Continua sul Web" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
index 2e4644cef3..f857bfe49f 100644
--- a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Texture multiple
</text>
- <radio_group name="mode_selection">
- <radio_item label="Inventario" name="inventory" value="0"/>
- <radio_item label="Locale" name="local" value="1"/>
- <radio_item label="Effettua il bake" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Dimensioni: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Inventario" name="inventory" value="0"/>
+ <combo_box.item label="Locale" name="local" value="1"/>
+ </combo_box>
<button label="Default" label_selected="Default" name="Default"/>
<button label="Vuoto" label_selected="Vuoto" name="Blank"/>
<button label="Niente" label_selected="Niente" name="None"/>
diff --git a/indra/newview/skins/default/xui/it/menu_cof_attachment.xml b/indra/newview/skins/default/xui/it/menu_cof_attachment.xml
index 699490c8f1..8861cc726f 100644
--- a/indra/newview/skins/default/xui/it/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/it/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Tocca" name="touch_attach" />
+ <menu_item_call label="Modifica" name="edit_item" />
<menu_item_call label="Stacca" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/it/menu_inventory.xml b/indra/newview/skins/default/xui/it/menu_inventory.xml
index 84ec7c4bd4..d2fbcafe97 100644
--- a/indra/newview/skins/default/xui/it/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/it/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="Indossa" name="Wearable And Object Wear"/>
<menu label="Attacca a" name="Attach To"/>
<menu label="Attacca all&apos;HUD" name="Attach To HUD"/>
+ <menu_item_call label="Tocca" name="Attachment Touch" />
<menu_item_call label="Modifica" name="Wearable Edit"/>
<menu_item_call label="Aggiungi" name="Wearable Add"/>
<menu_item_call label="Togli" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/it/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/it/menu_wearable_list_item.xml
index c9a02d8a86..23abdd7bf2 100644
--- a/indra/newview/skins/default/xui/it/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/it/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Sostituisci" name="wear_replace"/>
<menu_item_call label="Indossa" name="wear_wear"/>
<menu_item_call label="Aggiungi" name="wear_add"/>
+ <menu_item_call label="Tocca" name="touch" />
<menu_item_call label="Togli / Stacca" name="take_off_or_detach"/>
<menu_item_call label="Stacca" name="detach"/>
<context_menu label="Attacca a" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/it/menu_wearing_gear.xml b/indra/newview/skins/default/xui/it/menu_wearing_gear.xml
index de25f88aca..2f3a2aea43 100644
--- a/indra/newview/skins/default/xui/it/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/it/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Modifica vestiario" name="edit"/>
+ <menu_item_call label="Tocca" name="touch"/>
+ <menu_item_call label="Modifica" name="edit_item"/>
+ <menu_item_call label="Modifica vestiario" name="edit_outfit"/>
<menu_item_call label="Togli" name="takeoff"/>
<menu_item_call label="Copia gruppo vestiti negli Appunti" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/it/menu_wearing_tab.xml b/indra/newview/skins/default/xui/it/menu_wearing_tab.xml
index ec375e5240..08b56888a3 100644
--- a/indra/newview/skins/default/xui/it/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/it/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Tocca" name="touch_attach"/>
<menu_item_call label="Togli" name="take_off"/>
<menu_item_call label="Stacca" name="detach"/>
- <menu_item_call label="Modifica vestiario" name="edit"/>
+ <menu_item_call label="Modifica vestiario" name="edit_outfit"/>
<menu_item_call label="Modifica" name="edit_item"/>
<menu_item_call label="Mostra originale" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index a63b027349..1c43013255 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -266,6 +266,10 @@ Vuoi concedere i diritti di modifica ai residenti selezionati?
Vuoi revocare i permessi di modifica dati ai residenti selezionati?
<usetemplate name="okcancelbuttons" notext="No" yestext="Si"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ Il nome di un gruppo deve essere compreso tra [MIN_LEN] e [MAX_LEN] caratteri.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
Non è possibile creare il gruppo.
[MESSAGE]
@@ -360,7 +364,7 @@ Vuoi continuare?
Non hai abbastanza L$ per iscriverti a questo gruppo.
</notification>
<notification name="CreateGroupCost">
- La creazione di questo gruppo costerà L$ 100.
+ La creazione di questo gruppo ti costerà [COST]L$.
I gruppi devono avere più di un partecipante, o saranno eliminati definitivamente.
Invita altri partecipanti entro le prossime 48 ore.
<usetemplate canceltext="Annulla" name="okcancelbuttons" notext="Annulla" yestext="Crea un gruppo per L$ 100"/>
@@ -501,6 +505,9 @@ Per collocare il media su una sola faccia, scegli Seleziona faccia, clicca su un
<notification name="ErrorEncodingSnapshot">
Errore nella codifica della fotografia.
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Ti serviranno [COST]L$ per caricare questo articolo.
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Hai bisogno di L$ [COST] per salvare una foto nel tuo inventario. Puoi acquistare L$ o salvare la foto sul tuo computer.
</notification>
@@ -1740,11 +1747,14 @@ Vuoi cancellare quell&apos;elemento?
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- Il numero massimo di gruppi per gli account Basic è [MAX_BASIC] e
-per gli account [https://secondlife.com/premium/ Premium] è [MAX_PREMIUM].
-Se hai ridotto il livello del tuo account, dovrai essere iscritto a meno di [MAX_BASIC] gruppi prima di poter iscriverti a un nuovo gruppo.
-
-[https://secondlife.com/my/account/membership.php Passa a un livello superiore oggi stesso!]
+ I residenti con un'iscrizione Base possono aderire fino a [MAX_BASIC] gruppi.
+Le iscrizioni Premium consentono fino a [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Per saperne di più o per l'aggiornamento]
+ <usetemplate name="okbutton" yestext="Chiudi"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ I residenti con un'iscrizione Base possono aderire fino a [MAX_BASIC] gruppi.
+Le iscrizioni Premium consentono fino a [MAX_PREMIUM]. Le iscrizioni Premium Plus
+consentono fino a [MAX_PREMIUM_PLUS]. [https://secondlife.com/my/account/membership.php? Per saperne di più o per l'aggiornamento]
<usetemplate name="okbutton" yestext="Chiudi"/>
</notification>
<notification name="KickUser">
@@ -3306,6 +3316,22 @@ Per sicurezza, verranno bloccati per alcuni secondi.
La tua voce è stata interrotta dal moderatore.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ Purtroppo non siamo stati in grado di ottenere informazioni utili per questa sessione. Questo non dovrebbe accadere in un normale ambiente di produzione. Si prega di contattare il supporto. Questa sessione non funzionerà correttamente, si consiglia di riavviare.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Questo caricherà [COUNT] oggetti a un costo totale di [COST]L$. Vuoi continuare con il caricamento?
+ <usetemplate name="okcancelbuttons" notext="Annulla" yestext="Carica"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ I file selezionati non possono essere caricati.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Alcuni dei file selezionati non possono essere caricati.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
Questo caricamento costerà L$[PRICE]. Continuare con il caricamento?
<usetemplate name="okcancelbuttons" notext="Annulla" yestext="Carica"/>
diff --git a/indra/newview/skins/default/xui/it/panel_people.xml b/indra/newview/skins/default/xui/it/panel_people.xml
index 38a03fb4d2..3df2368ae0 100644
--- a/indra/newview/skins/default/xui/it/panel_people.xml
+++ b/indra/newview/skins/default/xui/it/panel_people.xml
@@ -18,7 +18,7 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa
<string name="no_groups_msg" value="Stai cercando gruppi di cui far parte? Prova [secondlife:///app/search/groups Cerca]."/>
<string name="MiniMapToolTipMsg" value="[REGION](Fai doppio clic per aprire la Mappa, premi il tasto Maiusc e trascina per la panoramica)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Fai doppio clic per teleportarti, premi il tasto Maiusc e trascina per la panoramica)"/>
- <string name="GroupCountWithInfo" value="Fai parte di [COUNT] gruppi e puoi iscriverti a [REMAINING] altri. [secondlife:/// Ne vuoi altri?]"/>
+ <string name="GroupCountWithInfo" value="Fai parte di [COUNT] gruppi e puoi ancora unirti a [REMAINING] gruppi. [secondlife:/// Aumenta il tuo limite]"/>
<tab_container name="tabs">
<panel label="NELLE VICINANZE" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa
<dnd_button name="minus_btn" tool_tip="Lascia il gruppo selezionato"/>
</panel>
<text name="groupcount">
- Fai parte di [COUNT] gruppi e puoi iscriverti a [REMAINING] altri.
+ Fai parte di [COUNT] gruppi e puoi ancora unirti a [REMAINING] gruppi.
</text>
</panel>
<panel label="RECENTE" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml
index f3ca9fafb3..c7739b8472 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml
@@ -32,10 +32,10 @@
</text>
<check_box initial_value="true" label="Esegui sempre il rendering degli amici" name="AlwaysRenderFriends"/>
<button label="Eccezioni..." name="RenderExceptionsButton"/>
- <button label="Salva impostazioni come valori predefiniti..." name="PrefSaveButton"/>
- <button label="Carica valore predefinito..." name="PrefLoadButton"/>
+ <button label="Salva impostazioni come valori predefiniti" name="PrefSaveButton" width="240" left="4"/>
+ <button label="Carica valore predefinito" name="PrefLoadButton" width="145" left_pad="7"/>
min_val=&quot;0.125&quot;
- <button label="Elimina valore predefinito..." name="PrefDeleteButton"/>
+ <button label="Elimina valore predefinito" name="PrefDeleteButton" width="148" left_pad="7"/>
<button label="Ripristina impostazioni consigliate" name="Defaults"/>
<button label="Impostazioni avanzate..." name="AdvancedSettings"/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
index aa3ff53f4a..c9d90539e1 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_setup.xml
@@ -35,5 +35,5 @@
<text name="Proxy Settings:">
Impostazioni proxy:
</text>
- <button label="Regola impostazioni proxy" label_selected="Sfoglia" name="set_proxy"/>
+ <button label="Regola impostazioni proxy" label_selected="Sfoglia" name="set_proxy" width="160"/>
</panel>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index ca486f832e..f0466cea81 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -1636,11 +1636,14 @@ Se continui a ricevere questo messaggio, contatta l&apos;assistenza Second Life
<string name="MarketplaceUpdating">
in aggiornamento...
</string>
+ <string name="UploadFeeInfo">
+ Il costo si basa sul tuo livello di iscrizione. Più alto è il livello, più basso è il costo. [https://secondlife.com/my/account/membership.php? Scopri di più]
+ </string>
<string name="Open landmarks">
- Apri luoghi di riferimento
+ Luoghi aperti
</string>
<string name="Unconstrained">
- Libero
+ Senza limitazioni
</string>
<string name="no_transfer" value="(nessun trasferimento)"/>
<string name="no_modify" value="(nessuna modifica)"/>
@@ -5012,6 +5015,15 @@ Consulta la pagina http://status.secondlifegrid.net per determinare se il proble
<string name="Chat" value="Chat :">
Chat
</string>
+ <string name="BaseMembership">
+ Base
+ </string>
+ <string name="PremiumMembership">
+ Premium
+ </string>
+ <string name="Premium PlusMembership">
+ Premium Plus
+ </string>
<string name="DeleteItems">
Cancellare gli elementi selezionati?
</string>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index a472f163e3..ac2db917cc 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -59,8 +59,7 @@
</text>
<button label="購入する" name="buy_btn"/>
<button label="取り消し" name="cancel_btn"/>
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
購入できません
- </text>
- <button label="Web サイトに移動" name="error_web" width="140"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
index 05e7bfefd2..1221702e9b 100644
--- a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
複数のテクスチャ
</text>
- <radio_group name="mode_selection">
- <radio_item label="インベントリ" name="inventory" value="0"/>
- <radio_item label="ローカル" name="local" value="1"/>
- <radio_item label="構築(ベーク)" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- サイズ: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="インベントリ" name="inventory" value="0"/>
+ <combo_box.item label="ローカル" name="local" value="1"/>
+ </combo_box>
<button label="デフォルト" label_selected="デフォルト" name="Default"/>
<button label="ブランク" label_selected="ブランク" name="Blank"/>
<button label="なし" label_selected="なし" name="None"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_cof_attachment.xml b/indra/newview/skins/default/xui/ja/menu_cof_attachment.xml
index e786d02e40..aa07b9476e 100644
--- a/indra/newview/skins/default/xui/ja/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/ja/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="触る" name="touch_attach" />
+ <menu_item_call label="編集" name="edit_item" />
<menu_item_call label="取り外す" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_inventory.xml b/indra/newview/skins/default/xui/ja/menu_inventory.xml
index ec16f1cf17..7f68c18e0b 100644
--- a/indra/newview/skins/default/xui/ja/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/ja/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="装着" name="Wearable And Object Wear"/>
<menu label="装着先" name="Attach To"/>
<menu label="HUD 装着先" name="Attach To HUD"/>
+ <menu_item_call label="触る" name="Attachment Touch" />
<menu_item_call label="編集" name="Wearable Edit"/>
<menu_item_call label="追加" name="Wearable Add"/>
<menu_item_call label="取り外す" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/ja/menu_wearable_list_item.xml
index c402fa0b6d..02029230ba 100644
--- a/indra/newview/skins/default/xui/ja/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/ja/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="交換" name="wear_replace"/>
<menu_item_call label="装着" name="wear_wear"/>
<menu_item_call label="追加" name="wear_add"/>
+ <menu_item_call label="触る" name="touch" />
<menu_item_call label="取り外す" name="take_off_or_detach"/>
<menu_item_call label="取り外す" name="detach"/>
<context_menu label="装着:" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_wearing_gear.xml b/indra/newview/skins/default/xui/ja/menu_wearing_gear.xml
index 5334042dc9..48aac2ed05 100644
--- a/indra/newview/skins/default/xui/ja/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/ja/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="アウトフットの編集" name="edit"/>
+ <menu_item_call label="触る" name="touch"/>
+ <menu_item_call label="編集" name="edit_item"/>
+ <menu_item_call label="アウトフットの編集" name="edit_outfit"/>
<menu_item_call label="取り外す" name="takeoff"/>
<menu_item_call label="アウトフィットのリストをクリップボードにコピー" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_wearing_tab.xml b/indra/newview/skins/default/xui/ja/menu_wearing_tab.xml
index bf8e72e457..8c331bc008 100644
--- a/indra/newview/skins/default/xui/ja/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/ja/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="触る" name="touch_attach"/>
<menu_item_call label="取り外す" name="take_off"/>
<menu_item_call label="取り外す" name="detach"/>
- <menu_item_call label="アウトフットの編集" name="edit"/>
+ <menu_item_call label="アウトフットの編集" name="edit_outfit"/>
<menu_item_call label="編集" name="edit_item"/>
<menu_item_call label="オリジナルを表示" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 96a5cb741a..a66552d3fe 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -266,6 +266,10 @@
選択した住人から変更権限を取り下げますか?
<usetemplate name="okcancelbuttons" notext="いいえ" yestext="はい"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ グループ名は [MIN_LEN] ~ [MAX_LEN] 文字である必要があります。
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
グループを作成できません。
[MESSAGE]
@@ -367,7 +371,7 @@
L$ が不足しているのでこのグループに参加することができません。
</notification>
<notification name="CreateGroupCost">
- このグループを作るには L$ 100 かかります。
+ このグループ作成にかかる費用:L$[COST]
一人ではグループにならないので、永久に削除されてしまいます。
48 時間以内にメンバーを勧誘し、入会してもらってください。
<usetemplate canceltext="キャンセル" name="okcancelbuttons" notext="キャンセル" yestext="L$100 でグループを作成"/>
@@ -518,6 +522,9 @@ L$ が不足しているのでこのグループに参加することができ
<notification name="ErrorEncodingSnapshot">
スナップショットのエンコード化でエラーが出ました!
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ このアイテムをアップロードするためには L$[COST] が必要です。
+ </notification>
<notification name="ErrorPhotoCannotAfford">
インベントリに写真を保存するには L$[COST] が必要です。L$ を購入するか、代わりに写真をっコンピュータに保存できます。
</notification>
@@ -1773,11 +1780,14 @@ https://secondlife.com/support/downloads/ からダウンロードしてくだ
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- ベースアカウントのグループ制限は [MAX_BASIC]、[https://secondlife.com/premium/ プレミアム] アカウントの
-グループ制限は [MAX_PREMIUM] です。
-アカウントをダウングレードした場合、さらにグループに参加する前に、下の [MAX_BASIC] グループ制限を取得する必要があります。
-
-[https://secondlife.com/my/account/membership.php 今すぐアップグレード!]
+ ベーシック会員の住民は、最大 [MAX_BASIC] グループまで参加することができます。
+プレミアム会員は、最大 [MAX_PREMIUM] まで可能です。[https://secondlife.com/my/account/membership.php? 詳細、またはアップグレード]
+ <usetemplate name="okbutton" yestext="閉じる"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ ベーシック会員の住民は、最大 [MAX_BASIC] グループまで参加することができます。
+プレミアム会員は、最大 [MAX_PREMIUM] まで可能です。プレミアムプラス会員は、最大 [MAX_PREMIUM_PLUS] まで可能です。
+[https://secondlife.com/my/account/membership.php? 詳細、またはアップグレード]
<usetemplate name="okbutton" yestext="閉じる"/>
</notification>
<notification name="KickUser">
@@ -3349,6 +3359,22 @@ M キーを押して変更します。
モデレーターがあなたのボイスをミュートしました。
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ 残念ながら、このセッションのベネフィット情報を得ることができませんでした。通常のプロダクション環境で起こることではありません。サポートまでご連絡ください。このセッションは通常通りに作動しませんので、再スタートをお薦めします
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ 合計 L$[COST] で [COUNT] アイテムがアップロードされます。 アップロードを続けますか?
+ <usetemplate name="okcancelbuttons" notext="取り消し" yestext="アップロード"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ 選択したファイルは、まとめてアップロードできません。
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ 選択したファイルのいくつかは、まとめてアップロードできません。
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
このアップロードは L$[PRICE] のコストがかかります。アップロードを続けますか?
<usetemplate name="okcancelbuttons" notext="取り消し" yestext="アップロード"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_people.xml b/indra/newview/skins/default/xui/ja/panel_people.xml
index 5fc4b57a08..0a295855d0 100644
--- a/indra/newview/skins/default/xui/ja/panel_people.xml
+++ b/indra/newview/skins/default/xui/ja/panel_people.xml
@@ -18,7 +18,7 @@
<string name="no_groups_msg" value="グループをお探しですか? [secondlife:///app/search/groups 検索] をお試しください。"/>
<string name="MiniMapToolTipMsg" value="[地域](ダブルクリックで地図を開く。Shift‐ドラッグで水平・垂直移動)"/>
<string name="AltMiniMapToolTipMsg" value="[地域](ダブルクリックでテレポート。Shift‐ドラッグで水平・垂直移動)"/>
- <string name="GroupCountWithInfo" value="あなたは [COUNT] グループに属しているので、まだ [REMAINING] 参加できます。[secondlife:/// 詳細]"/>
+ <string name="GroupCountWithInfo" value="あなたは現在、[COUNT] グループに属しています。あと [REMAINING] グループに参加することができます。[secondlife:/// 上限を増やす]"/>
<tab_container name="tabs">
<panel label="近く" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@
<dnd_button name="minus_btn" tool_tip="選択したグループから脱退"/>
</panel>
<text name="groupcount">
- あなたは[COUNT]グループに属しているので、まだ[REMAINING]参加できます。
+ あなたは現在、[COUNT] グループに属しています。あと [REMAINING] グループに参加することができます。
</text>
</panel>
<panel label="最新" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 3f46376595..52d6fb0c2b 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -1644,11 +1644,14 @@ support@secondlife.com にお問い合わせください。
<string name="MarketplaceUpdating">
アップデート中...
</string>
+ <string name="UploadFeeInfo">
+ 料金はサブスクリプションのレベルにより異なります。レベルが高いほど、料金が下がります。[https://secondlife.com/my/account/membership.php? 詳細]
+ </string>
<string name="Open landmarks">
- ランドマークを開く
+ オープン ランドマーク
</string>
<string name="Unconstrained">
- 非拘束
+ アンコンストレインド(制約なし)
</string>
<string name="no_transfer" value=" (再販・プレゼント不可)"/>
<string name="no_modify" value=" (編集不可)"/>
@@ -5095,6 +5098,15 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
<string name="Chat" value=" チャット:">
チャット
</string>
+ <string name="BaseMembership">
+ ベース
+ </string>
+ <string name="PremiumMembership">
+ プレミアム
+ </string>
+ <string name="Premium PlusMembership">
+ プレミアムプラス
+ </string>
<string name="DeleteItems">
選択したアイテムを削除しますか
</string>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
index 72167e0d3c..a1d703a15a 100644
--- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
@@ -50,8 +50,7 @@
</text>
<button label="Kup teraz" name="buy_btn" />
<button label="Anuluj" name="cancel_btn" />
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
Nie można kupić
- </text>
- <button label="Odwiedź stronę WWW" name="error_web" />
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml
index 8ac158b462..2425213160 100644
--- a/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/pl/floater_texture_ctrl.xml
@@ -9,13 +9,10 @@
<text name="Multiple">
Wiele tekstur
</text>
- <radio_group name="mode_selection">
- <radio_item label="Szafa" name="inventory" />
- <radio_item label="Lokalna" name="local" />
- </radio_group>
- <text name="unknown">
- Rozm.: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Szafa" name="inventory" />
+ <combo_box.item label="Lokalna" name="local" />
+ </combo_box>
<button label="Domyślna" label_selected="Domyślna" name="Default" />
<button label="Pusta" label_selected="Pusta" name="Blank" />
<button label="Przezrocz." label_selected="Przezrocz." name="None" />
diff --git a/indra/newview/skins/default/xui/pl/menu_cof_attachment.xml b/indra/newview/skins/default/xui/pl/menu_cof_attachment.xml
index add2d59998..f5fbf5c0c1 100644
--- a/indra/newview/skins/default/xui/pl/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/pl/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Dotknij" name="touch_attach" />
+ <menu_item_call label="Edytuj" name="edit_item" />
<menu_item_call label="Odłącz" name="detach" />
</context_menu>
diff --git a/indra/newview/skins/default/xui/pl/menu_inventory.xml b/indra/newview/skins/default/xui/pl/menu_inventory.xml
index 0edb680b16..1aeffc58b7 100644
--- a/indra/newview/skins/default/xui/pl/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/pl/menu_inventory.xml
@@ -85,6 +85,7 @@
<menu_item_call label="Załóż" name="Wearable And Object Wear" />
<menu label="Dołącz do" name="Attach To" />
<menu label="Dołącz do HUD-a" name="Attach To HUD" />
+ <menu_item_call label="Dotknij" name="Attachment Touch" />
<menu_item_call label="Edytuj" name="Wearable Edit" />
<menu_item_call label="Dodaj/dołącz" name="Wearable Add" />
<menu_item_call label="Zdejmij" name="Take Off" />
diff --git a/indra/newview/skins/default/xui/pl/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/pl/menu_wearable_list_item.xml
index 260b86cb07..b0ef8e4393 100644
--- a/indra/newview/skins/default/xui/pl/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/pl/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Zastąp" name="wear_replace" />
<menu_item_call label="Załóż" name="wear_wear" />
<menu_item_call label="Dodaj" name="wear_add" />
+ <menu_item_call label="Dotknij" name="touch" />
<menu_item_call label="Zdejmij/Odłącz" name="take_off_or_detach" />
<menu_item_call label="Odłącz" name="detach" />
<context_menu label="Dołącz do" name="wearable_attach_to" />
diff --git a/indra/newview/skins/default/xui/pl/menu_wearing_gear.xml b/indra/newview/skins/default/xui/pl/menu_wearing_gear.xml
index 73138b2cf7..c129448adc 100644
--- a/indra/newview/skins/default/xui/pl/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/pl/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Edytuj strój" name="edit" />
+ <menu_item_call label="Dotknij" name="touch"/>
+ <menu_item_call label="Edytuj" name="edit_item"/>
+ <menu_item_call label="Edytuj strój" name="edit_outfit" />
<menu_item_call label="Zdejmij" name="takeoff" />
<menu_item_call label="Kopiuj listę przedmiotów stroju do schowka" name="copy" />
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/pl/menu_wearing_tab.xml b/indra/newview/skins/default/xui/pl/menu_wearing_tab.xml
index 09c82da427..188f77a3bb 100644
--- a/indra/newview/skins/default/xui/pl/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/pl/menu_wearing_tab.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<context_menu name="Wearing">
+ <menu_item_call label="Dotknij" name="touch_attach"/>
+ <menu_item_call label="Edytuj" name="edit_item"/>
<menu_item_call label="Zdejmij" name="take_off" />
<menu_item_call label="Odłącz" name="detach" />
- <menu_item_call label="Edytuj strój" name="edit" />
+ <menu_item_call label="Edytuj strój" name="edit_outfit" />
</context_menu>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index 513400954b..c740b90472 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -59,8 +59,7 @@
</text>
<button label="Comprar já!" name="buy_btn"/>
<button label="Fechar" name="cancel_btn"/>
- <text name="info_cannot_buy" font="SansSerifBig">
+ <floater.string name="info_cannot_buy">
Transação incompleta
- </text>
- <button label="Prosseguir para a web" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
index d06c16d8c8..d3eec114e2 100644
--- a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Multiplas texturas
</text>
- <radio_group name="mode_selection">
- <radio_item label="Inventário" name="inventory" value="0"/>
- <radio_item label="Local" name="local" value="1"/>
- <radio_item label="Assar" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Tamanho: [DIMENSÕES]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Inventário" name="inventory" value="0"/>
+ <combo_box.item label="Local" name="local" value="1"/>
+ </combo_box>
<button label="Padrão" label_selected="Padrão" name="Default"/>
<button label="Branco" label_selected="Branco" name="Blank"/>
<button label="Nenhum" label_selected="Nenhum" name="None"/>
diff --git a/indra/newview/skins/default/xui/pt/menu_cof_attachment.xml b/indra/newview/skins/default/xui/pt/menu_cof_attachment.xml
index 527e3af3c9..5072b54f06 100644
--- a/indra/newview/skins/default/xui/pt/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/pt/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Tocar" name="touch_attach" />
+ <menu_item_call label="Editar" name="edit_item" />
<menu_item_call label="Separar" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml
index 78a0482dee..363ed43986 100644
--- a/indra/newview/skins/default/xui/pt/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="Vestir" name="Wearable And Object Wear"/>
<menu label="Anexar a" name="Attach To"/>
<menu label="Anexar ao HUD" name="Attach To HUD"/>
+ <menu_item_call label="Tocar" name="Attachment Touch" />
<menu_item_call label="Editar" name="Wearable Edit"/>
<menu_item_call label="Adicionar" name="Wearable Add"/>
<menu_item_call label="Tirar" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/pt/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/pt/menu_wearable_list_item.xml
index 2487f6779f..2d16736277 100644
--- a/indra/newview/skins/default/xui/pt/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/pt/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Trocar" name="wear_replace"/>
<menu_item_call label="Vestir" name="wear_wear"/>
<menu_item_call label="Adicionar" name="wear_add"/>
+ <menu_item_call label="Tocar" name="touch" />
<menu_item_call label="Tirar / Separar" name="take_off_or_detach"/>
<menu_item_call label="Separar" name="detach"/>
<context_menu label="Colocar em" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/pt/menu_wearing_gear.xml b/indra/newview/skins/default/xui/pt/menu_wearing_gear.xml
index 75dca703cb..bc24ffcdd9 100644
--- a/indra/newview/skins/default/xui/pt/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/pt/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Editar look" name="edit"/>
+ <menu_item_call label="Tocar" name="touch"/>
+ <menu_item_call label="Editar" name="edit_item"/>
+ <menu_item_call label="Editar look" name="edit_outfit"/>
<menu_item_call label="Tirar" name="takeoff"/>
<menu_item_call label="Copiar lista do look para a área de transferência" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_wearing_tab.xml b/indra/newview/skins/default/xui/pt/menu_wearing_tab.xml
index 42aa386215..d00fd9ae28 100644
--- a/indra/newview/skins/default/xui/pt/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/pt/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Tocar" name="touch_attach"/>
<menu_item_call label="Tirar" name="take_off"/>
<menu_item_call label="Tirar" name="detach"/>
- <menu_item_call label="Editar look" name="edit"/>
+ <menu_item_call label="Editar look" name="edit_outfit"/>
<menu_item_call label="Editar" name="edit_item"/>
<menu_item_call label="Mostrar original" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index 35f65a59bc..bd1185bdd2 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -265,6 +265,10 @@ Deseja conceder direitos de modificação para os residentes selecionados?
Você quer revogar os direitos de edição para os residentes selecionados?
<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ O nome do grupo deve conter entre [MIN_LEN] e [MAX_LEN] caracteres.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
Não foi possível criar um grupo.
[MESSAGE]
@@ -359,7 +363,7 @@ Deseja continuar?
Você não tem L$ suficientes para associar-se a este grupo.
</notification>
<notification name="CreateGroupCost">
- Criar este grupo custa L$100.
+ Criar este grupo custará L$[COST].
Grupos ser formados por mais de um membro, caso contrário serão definitivamente excluídos.
Convite outros membros dentro de 48 horas.
<usetemplate canceltext="Cancelar" name="okcancelbuttons" notext="Cancelar" yestext="Criar grupo por L$100"/>
@@ -498,6 +502,9 @@ Para colocar a mídia em só uma face, selecione Selecionar face e clique na fac
<notification name="ErrorEncodingSnapshot">
Erro ao codificar a foto.
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Você precisa de L$[COST] para fazer o upload deste item.
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Você precisa de L$ [COST] para salvar uma foto em seu inventário. Você pode comprar L$ ou salvar a foto em seu computador.
</notification>
@@ -1729,13 +1736,16 @@ Deseja prosseguir?
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- O limite de grupos para as contas básicas é [MAX_BASIC] e para as contas [https://secondlife.com/premium/ premium],
-é [MAX_PREMIUM].
-Se você fizer downgrade de sua conta, precisará ficar abaixo do limite de grupos [MAX_BASIC] antes de entrar em mais.
-
-[https://secondlife.com/my/account/membership.php Faça o upgrade hoje!]
+ Residentes com o plano Básico podem participar de até [MAX_BASIC] grupos.
+O plano Premium permite até [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Saiba mais ou faça um upgrade]
<usetemplate name="okbutton" yestext="Fechar"/>
</notification>
+ <notification name="GroupLimitInfoPlus">
+ Residentes com o plano Básico podem participar de até [MAX_BASIC] grupos.
+O plano Premium permite até [MAX_PREMIUM]. O plano Premium Plus permite até [MAX_PREMIUM_PLUS].
+[https://secondlife.com/my/account/membership.php? Saiba mais ou faça um upgrade]
+ <usetemplate name="okbutton" yestext="Fechar"/>
+ </notification>
<notification name="KickUser">
Chutar este residente com qual mensagem?
<form name="form">
@@ -3292,6 +3302,22 @@ Para sua segurança, os SLurls serão bloqueados por alguns instantes.
Sua voz foi silenciada pelo moderador.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ Infelizmente, não conseguimos obter as informações de benefícios para esta sessão. Isto não deveria ocorrer em um ambiente de produção normal. Por favor, contate o suporte. Esta sessão não funcionará normalmente e recomendamos que você reinicie.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Será feito o upload de [COUNT] itens, com um custo total de L$[COST]. Você deseja prosseguir com o upload?
+ <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Carregar"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ Não é possível fazer o upload dos arquivos selecionados de uma vez só.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Não é possível fazer o upload de alguns dos arquivos selecionados de uma vez só.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
O carregamento custa L$[PRICE]. Deseja prosseguir?
<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Carregar"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_people.xml b/indra/newview/skins/default/xui/pt/panel_people.xml
index fce170110e..2ef01841c5 100644
--- a/indra/newview/skins/default/xui/pt/panel_people.xml
+++ b/indra/newview/skins/default/xui/pt/panel_people.xml
@@ -18,7 +18,7 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa-
<string name="no_groups_msg" value="À procura de grupos interessantes? Tente fazer uma [secondlife:///app/search/groups Busca]."/>
<string name="MiniMapToolTipMsg" value="[REGION](Clique duas vezes para abrir o mapa, shift+arraste para a visão pan)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Clique duas vezes para teletransportar, shift+arraste para a visão pan)"/>
- <string name="GroupCountWithInfo" value="Você pertence a [COUNT] grupos e pode entrar em mais [REMAINING]. [secondlife:/// Quer mais?]"/>
+ <string name="GroupCountWithInfo" value="Você faz parte de [COUNT] grupos e pode participar de mais [REMAINING]. [secondlife:/// Aumente o seu limite]"/>
<tab_container name="tabs">
<panel label="PROXIMIDADE" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@ Em busca de alguém para conversar? Procure no [secondlife:///app/worldmap Mapa-
<dnd_button name="minus_btn" tool_tip="Sair do grupo selecionado"/>
</panel>
<text name="groupcount">
- Você pertence a [COUNT] grupos e pode entrar em mais [REMAINING].
+ Você faz parte de [COUNT] grupos e pode participar de mais [REMAINING].
</text>
</panel>
<panel label="RECENTE" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml
index a0f4ea4ed5..d387c4c869 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_graphics1.xml
@@ -33,10 +33,10 @@ rápido
</text>
<check_box initial_value="true" label="Sempre renderizar amigos" name="AlwaysRenderFriends"/>
<button label="Exceções..." name="RenderExceptionsButton"/>
- <button label="Salvar configurações como predefinição..." name="PrefSaveButton"/>
- <button label="Carregar predefinição..." name="PrefLoadButton"/>
+ <button label="Salvar configurações como predefinição" name="PrefSaveButton" width="235" left="5"/>
+ <button label="Carregar predefinição" name="PrefLoadButton" width="130" left_pad="8"/>
min_val=&quot;0.125&quot;
- <button label="Excluir predefinição..." name="PrefDeleteButton"/>
- <button label="Redefinir para configurações recomendadas" left="110" name="Defaults"/>
+ <button label="Excluir predefinição" name="PrefDeleteButton" width="122" left_pad="8"/>
+ <button label="Redefinir para configurações recomendadas" name="Defaults" width="255"/>
<button label="Configurações avançadas..." name="AdvancedSettings"/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
index 03536f28c3..56fc225bc0 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_setup.xml
@@ -35,5 +35,5 @@
<text name="Proxy Settings:">
Configurações de proxy:
</text>
- <button label="Ajustar configurações de proxy" label_selected="Procurar" name="set_proxy"/>
+ <button label="Ajustar configurações de proxy" label_selected="Procurar" name="set_proxy" width="180"/>
</panel>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 6b86c4330c..ee982b5b22 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -1596,11 +1596,14 @@ Se você continuar a receber essa mensagem, entre em contato com o suporte do Se
<string name="MarketplaceUpdating">
atualizando...
</string>
+ <string name="UploadFeeInfo">
+ A taxa é baseada em seu nível de inscrição. Níveis mais altos possuem taxas mais baixas. [https://secondlife.com/my/account/membership.php? Saiba mais]
+ </string>
<string name="Open landmarks">
- Marcos abertos
+ Marcos em aberto
</string>
<string name="Unconstrained">
- Sem limites
+ Ilimitado
</string>
<string name="no_transfer" value="(não transferível)"/>
<string name="no_modify" value="(não modificável)"/>
@@ -4971,6 +4974,9 @@ Visite http://status.secondlifegrid.net para saber se foi detectado um problema
<string name="Chat" value="Bate papo">
Bate-papo
</string>
+ <string name="BaseMembership">
+ Básico
+ </string>
<string name="DeleteItems">
Excluir itens selecionados?
</string>
diff --git a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
index 87e8bd524e..ef55ce58d4 100644
--- a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
@@ -59,8 +59,7 @@
</text>
<button label="Приобрести" name="buy_btn"/>
<button label="Отмена" name="cancel_btn"/>
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
Нельзя купить
- </text>
- <button label="Продолжить в Интернете" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml
index c56657b86b..d4323e5c34 100644
--- a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Несколько текстур
</text>
- <radio_group name="mode_selection">
- <radio_item label="Инвентарь" name="inventory" value="0"/>
- <radio_item label="Локально" name="local" value="1"/>
- <radio_item label="Зафиксировать" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Размер: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Инвентарь" name="inventory" value="0"/>
+ <combo_box.item label="Локально" name="local" value="1"/>
+ </combo_box>
<button label="По умолчанию" label_selected="По умолчанию" name="Default"/>
<button label="Очистить" label_selected="Очистить" name="Blank"/>
<button label="Нет" label_selected="Нет" name="None"/>
diff --git a/indra/newview/skins/default/xui/ru/menu_cof_attachment.xml b/indra/newview/skins/default/xui/ru/menu_cof_attachment.xml
index 72d1bc52b5..bc60188e2d 100644
--- a/indra/newview/skins/default/xui/ru/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/ru/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Коснуться" name="touch_attach" />
+ <menu_item_call label="Изменить" name="edit_item" />
<menu_item_call label="Отсоединить" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_inventory.xml b/indra/newview/skins/default/xui/ru/menu_inventory.xml
index 05cccebafc..0f63324e90 100644
--- a/indra/newview/skins/default/xui/ru/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/ru/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="Надеть" name="Wearable And Object Wear"/>
<menu label="Присоединить к" name="Attach To"/>
<menu label="Присоединить к данным в игре" name="Attach To HUD"/>
+ <menu_item_call label="Коснуться" name="Attachment Touch" />
<menu_item_call label="Изменить" name="Wearable Edit"/>
<menu_item_call label="Добавить" name="Wearable Add"/>
<menu_item_call label="Снять" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/ru/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/ru/menu_wearable_list_item.xml
index 2832e17b7d..caef7db458 100644
--- a/indra/newview/skins/default/xui/ru/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/ru/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Заменить" name="wear_replace"/>
<menu_item_call label="Надеть" name="wear_wear"/>
<menu_item_call label="Добавить" name="wear_add"/>
+ <menu_item_call label="Коснуться" name="touch" />
<menu_item_call label="Снять / отсоединить" name="take_off_or_detach"/>
<menu_item_call label="Отсоединить" name="detach"/>
<context_menu label="Присоединить" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/ru/menu_wearing_gear.xml b/indra/newview/skins/default/xui/ru/menu_wearing_gear.xml
index c2351fbfff..01491b9694 100644
--- a/indra/newview/skins/default/xui/ru/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/ru/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Изменить костюм" name="edit"/>
+ <menu_item_call label="Коснуться" name="touch"/>
+ <menu_item_call label="Изменить" name="edit_item"/>
+ <menu_item_call label="Изменить костюм" name="edit_outfit"/>
<menu_item_call label="Снять" name="takeoff"/>
<menu_item_call label="Копировать список костюмов в буфер обмена" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_wearing_tab.xml b/indra/newview/skins/default/xui/ru/menu_wearing_tab.xml
index 1e32090c2a..e68b67bb33 100644
--- a/indra/newview/skins/default/xui/ru/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/ru/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Коснуться" name="touch_attach"/>
<menu_item_call label="Снять" name="take_off"/>
<menu_item_call label="Отсоединить" name="detach"/>
- <menu_item_call label="Изменить костюм" name="edit"/>
+ <menu_item_call label="Изменить костюм" name="edit_outfit"/>
<menu_item_call label="Изменить" name="edit_item"/>
<menu_item_call label="Показать оригинал" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index 517c4db278..bfcda798be 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -266,6 +266,10 @@
Отобрать у выбранных жителей права на изменение?
<usetemplate name="okcancelbuttons" notext="Нет" yestext="Да"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ Название группы может содержать от [MIN_LEN] до [MAX_LEN] символов.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UnableToCreateGroup">
Невозможно создать группу.
[MESSAGE]
@@ -360,7 +364,7 @@
У вас не хватает L$ для вступления.
</notification>
<notification name="CreateGroupCost">
- Создание этой группы стоит L$100.
+ Создание этой группы стоит L$[COST].
В группе должно быть более одного участника, иначе она будет удалена.
Пригласите участников в ближайшие 48 часов.
<usetemplate canceltext="Отмена" name="okcancelbuttons" notext="Отмена" yestext="Создать группу за L$100"/>
@@ -500,6 +504,9 @@
<notification name="ErrorEncodingSnapshot">
Ошибка при кодировке снимка.
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Чтобы загрузить этот предмет, вам нужно L$[COST].
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Требуется L$[COST] для сохранения фото в вашем инвентаре. Купите L$ или сохраните фото на компьютере.
</notification>
@@ -1612,22 +1619,22 @@
[DOWNLOAD_PATH].
</notification>
<notification name="RequiredUpdate">
- Для входа необходима версия \[VERSION].
+ Для входа необходима версия [VERSION].
Скачайте обновление с веб-сайта https://secondlife.com/support/downloads/
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="PauseForUpdate">
- Для входа необходима версия \[VERSION].
+ Для входа необходима версия [VERSION].
Нажмите OK для загрузки и установки.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="OptionalUpdateReady">
- Версия \[VERSION] загружена и готова к установке.
+ Версия [VERSION] загружена и готова к установке.
Нажмите OK для установки.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="PromptOptionalUpdate">
- Версия \[VERSION] загружена и готова к установке.
+ Версия [VERSION] загружена и готова к установке.
Продолжить?
<usetemplate canceltext="Не сейчас" name="yesnocancelbuttons" notext="Пропустить" yestext="Установить"/>
</notification>
@@ -1738,11 +1745,14 @@
<usetemplate name="okbutton" yestext="OK"/>
</notification>
<notification name="GroupLimitInfo">
- Максимальное число групп для пользователя базового аккаунта составляет [MAX_BASIC],
-а для [https://secondlife.com/premium/ премиум]-аккаунта – [MAX_PREMIUM].
-Чтобы вступать в новые группы после возврата к базовому аккаунту, вам придется выйти из части групп, чтобы их общее число было меньше [MAX_BASIC].
-
-[https://secondlife.com/my/account/membership.php Перейдите на премиум-членство!]
+ Резиденты с Базовым аккаунтом могут присоединиться к [MAX_BASIC] группам.
+Премиум аккаунт разрешает до [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Узнайте больше или расширьте свой аккаунт]
+ <usetemplate name="okbutton" yestext="Закрыть"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ Резиденты с Базовым аккаунтом могут присоединиться к [MAX_BASIC] группам.
+Премиум аккаунт разрешает до [MAX_PREMIUM]. Премиум Плюс аккаунт разрешает до [MAX_PREMIUM_PLUS].
+[https://secondlife.com/my/account/membership.php? Узнайте больше или расширьте свой аккаунт]
<usetemplate name="okbutton" yestext="Закрыть"/>
</notification>
<notification name="KickUser">
@@ -3303,6 +3313,22 @@
Ваш голос заглушен модератором.
<usetemplate name="okbutton" yestext="OK"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ К сожалению, в этой сессии мы не смогли получить информацию о преимуществах аккаунта. Такое не должно происходить в нормально работающей среде. Пожалуйста, свяжитесь со службой поддержки. Эта сессия работает некорректно, поэтому мы рекомендуем вам перезапустить программу.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Этим действием загружается [COUNT] предметов на общую стоимость L$[COST]. Вы хотите продолжить загрузку?
+ <usetemplate name="okcancelbuttons" notext="Отмена" yestext="Загрузить"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ Выбранные файлы не могут быть загружены группой.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Некоторые из выбранных файлов не могут быть загружены группой.
+ <usetemplate name="okbutton" yestext="OK"/>
+ </notification>
<notification name="UploadCostConfirmation">
Эта передача будет стоить L$[PRICE]. Продолжить передачу?
<usetemplate name="okcancelbuttons" notext="Отмена" yestext="Передать"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_people.xml b/indra/newview/skins/default/xui/ru/panel_people.xml
index 0fdc06fb32..0812eb7433 100644
--- a/indra/newview/skins/default/xui/ru/panel_people.xml
+++ b/indra/newview/skins/default/xui/ru/panel_people.xml
@@ -18,7 +18,7 @@
<string name="no_groups_msg" value="Ищете группу, чтобы присоединиться к ней? Воспользуйтесь [secondlife:///app/search/groups поиском]."/>
<string name="MiniMapToolTipMsg" value="[REGION](Двойной щелчок открывает карту, shift+перетягивание – обзор)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Двойной щелчок – телепортация, shift+перетягивание – обзор)"/>
- <string name="GroupCountWithInfo" value="Вы входите в [COUNT] групп и можете присоединиться еще к [REMAINING]. [secondlife:/// Хотите еще?]"/>
+ <string name="GroupCountWithInfo" value="Вы состоите в [COUNT] группах, и можете присоединиться еще к [REMAINING]. [secondlife:/// Расширить свои лимиты]"/>
<tab_container name="tabs">
<panel label="РЯДОМ" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@
<dnd_button name="minus_btn" tool_tip="Покинуть выбранную группу"/>
</panel>
<text name="groupcount">
- Вы входите в [COUNT] групп и можете присоединиться еще к [REMAINING].
+ Вы состоите в [COUNT] группах, и можете присоединиться еще к [REMAINING].
</text>
</panel>
<panel label="НЕДАВНИЕ" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/ru/panel_preferences_advanced.xml
index dd0cf8e172..79d5cb7960 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_advanced.xml
@@ -28,5 +28,5 @@
<check_box label="Выбор сетки при входе" name="show_grid_selection_check"/>
<check_box label="Показывать расширенное меню" name="show_advanced_menu_check"/>
<check_box label="Показать меню разработчика" name="show_develop_menu_check"/>
- <button label="Стандартные разрешения на создание" name="default_creation_permissions"/>
+ <button label="Стандартные разрешения на создание" name="default_creation_permissions" width="235"/>
</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml
index 4524fb4d43..f392a1f0b7 100644
--- a/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_graphics1.xml
@@ -32,7 +32,7 @@
</text>
<check_box initial_value="true" label="Всегда рисовать друзей" name="AlwaysRenderFriends"/>
<button label="Исключения..." name="RenderExceptionsButton"/>
- <button label="Сохранить настройки как пресет..." name="PrefSaveButton"/>
+ <button label="Сохранить настройки как пресет..." name="PrefSaveButton" width="210"/>
<button label="Загрузить пресет..." name="PrefLoadButton"/>
min_val=&quot;0,125&quot;
<button label="Удалить пресет..." name="PrefDeleteButton"/>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index edcf9d3e00..e9592a0476 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -1643,11 +1643,14 @@ support@secondlife.com.
<string name="MarketplaceUpdating">
обновление...
</string>
+ <string name="UploadFeeInfo">
+ Тариф зависит от типа вашей подписки. Тарифы для владельцев расширенных пакетов меньше. [https://secondlife.com/my/account/membership.php? Узнать больше]
+ </string>
<string name="Open landmarks">
- Открыть закладки
+ Открыть сохраненные локации
</string>
<string name="Unconstrained">
- Без ограничения
+ Без ограничений
</string>
<string name="no_transfer" value="(не передается)"/>
<string name="no_modify" value="(не изменяется)"/>
@@ -5091,6 +5094,15 @@ support@secondlife.com.
<string name="Chat">
Чат
</string>
+ <string name="BaseMembership">
+ Базовый
+ </string>
+ <string name="PremiumMembership">
+ Премиум
+ </string>
+ <string name="Premium PlusMembership">
+ Премиум Плюс
+ </string>
<string name="DeleteItems">
Удалить выбранные объекты?
</string>
diff --git a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
index d90985dcff..33c4b2287f 100644
--- a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
@@ -59,8 +59,7 @@
</text>
<button label="Şimdi Satın Al" name="buy_btn"/>
<button label="İptal" name="cancel_btn"/>
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
Satın Alınamıyor
- </text>
- <button label="Web&apos;e devam et" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml
index 1a16709127..0389cdcbe5 100644
--- a/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
Birden çok doku
</text>
- <radio_group name="mode_selection">
- <radio_item label="Envanter" name="inventory" value="0"/>
- <radio_item label="Yerel" name="local" value="1"/>
- <radio_item label="Kurut" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- Büyüklük: [DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="Envanter" name="inventory" value="0"/>
+ <combo_box.item label="Yerel" name="local" value="1"/>
+ </combo_box>
<button label="Varsayılan" label_selected="Varsayılan" name="Default"/>
<button label="Boş" label_selected="Boş" name="Blank"/>
<button label="Hiçbiri" label_selected="Hiçbiri" name="None"/>
diff --git a/indra/newview/skins/default/xui/tr/menu_cof_attachment.xml b/indra/newview/skins/default/xui/tr/menu_cof_attachment.xml
index d57c43f6c1..82c9b286bb 100644
--- a/indra/newview/skins/default/xui/tr/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/tr/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="Dokun" name="touch_attach" />
+ <menu_item_call label="Düzenle" name="edit_item" />
<menu_item_call label="Ayır" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_inventory.xml b/indra/newview/skins/default/xui/tr/menu_inventory.xml
index d5e4113feb..ce85c437cb 100644
--- a/indra/newview/skins/default/xui/tr/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/tr/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="Giy" name="Wearable And Object Wear"/>
<menu label="Şuna Ekle:" name="Attach To"/>
<menu label="BÜG&apos;e Ekle" name="Attach To HUD"/>
+ <menu_item_call label="Dokun" name="Attachment Touch" />
<menu_item_call label="Düzenle" name="Wearable Edit"/>
<menu_item_call label="Ekle" name="Wearable Add"/>
<menu_item_call label="Çıkar" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/tr/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/tr/menu_wearable_list_item.xml
index 448202df87..486f76a29a 100644
--- a/indra/newview/skins/default/xui/tr/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/tr/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="Değiştir" name="wear_replace"/>
<menu_item_call label="Giy" name="wear_wear"/>
<menu_item_call label="Ekle" name="wear_add"/>
+ <menu_item_call label="Dokun" name="touch" />
<menu_item_call label="Çıkar / Ayır" name="take_off_or_detach"/>
<menu_item_call label="Ayır" name="detach"/>
<context_menu label="Şuna ekle" name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/tr/menu_wearing_gear.xml b/indra/newview/skins/default/xui/tr/menu_wearing_gear.xml
index 438e580cd3..1594cf3afb 100644
--- a/indra/newview/skins/default/xui/tr/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/tr/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="Dış Görünümü Düzenle" name="edit"/>
+ <menu_item_call label="Dokun" name="touch"/>
+ <menu_item_call label="Düzenle" name="edit_item"/>
+ <menu_item_call label="Dış Görünümü Düzenle" name="edit_outfit"/>
<menu_item_call label="Çıkar" name="takeoff"/>
<menu_item_call label="Dış görünüm listesini panoya kopyala" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_wearing_tab.xml b/indra/newview/skins/default/xui/tr/menu_wearing_tab.xml
index 1db95c17e1..56397c8628 100644
--- a/indra/newview/skins/default/xui/tr/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/tr/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="Dokun" name="touch_attach"/>
<menu_item_call label="Çıkar" name="take_off"/>
<menu_item_call label="Ayır" name="detach"/>
- <menu_item_call label="Dış Görünümü Düzenle" name="edit"/>
+ <menu_item_call label="Dış Görünümü Düzenle" name="edit_outfit"/>
<menu_item_call label="Düzenle" name="edit_item"/>
<menu_item_call label="Orijinali Göster" name="show_original"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml
index b7593322e3..5403a78f22 100644
--- a/indra/newview/skins/default/xui/tr/notifications.xml
+++ b/indra/newview/skins/default/xui/tr/notifications.xml
@@ -266,6 +266,10 @@ Seçili Sakinlere değişiklik yapma hakkı vermek istiyor musunuz?
Seçili Sakinlerin değişiklik yapma hakkını iptal etmek istiyor musunuz?
<usetemplate name="okcancelbuttons" notext="Hayır" yestext="Evet"/>
</notification>
+ <notification name="GroupNameLengthWarning">
+ Bir grup adı [MIN_LEN] ile [MAX_LEN] karakter olmalıdır.
+ <usetemplate name="okbutton" yestext="Tamam"/>
+ </notification>
<notification name="UnableToCreateGroup">
Grup oluşturulamıyor.
[MESSAGE]
@@ -360,7 +364,7 @@ Devam etmek istiyor musunuz?
Bu gruba katılmak için yeterli L$&apos;na sahip değilsiniz.
</notification>
<notification name="CreateGroupCost">
- Bu grubu oluşturmanın maliyeti: L$ 100.
+ Bu grubu oluşturmak L$[COST]'dır.
Grupların birden fazla üyeye sahip olması gereklidir, aksi takdirde grup kalıcı olarak silinir.
Lütfen 48 saat içinde diğer üyeleri davet edin.
<usetemplate canceltext="İptal" name="okcancelbuttons" notext="İptal" yestext="L$ 100 ödeyerek grubu oluştur"/>
@@ -501,6 +505,9 @@ Ortamı sadece bir yüze yerleştirmek için, Yüz Seç&apos;i seçin ve ardınd
<notification name="ErrorEncodingSnapshot">
Anlık görüntü kodlanırken hata oluştu.
</notification>
+ <notification name="ErrorCannotAffordUpload">
+ Bu nesneyi yüklemek için L$[COST] ' a ihtiyacınız var.
+ </notification>
<notification name="ErrorPhotoCannotAfford">
Envanterinize bir fotoğraf kaydedebilmek için [COST] L$ paraya ihtiyacınız var. L$ satın alabilir veya bunun yerine fotoğrafı bilgisayarınıza kaydedebilirsiniz.
</notification>
@@ -1739,11 +1746,14 @@ Gruptan ayrılmak istiyor musunuz?
<usetemplate name="okbutton" yestext="Tamam"/>
</notification>
<notification name="GroupLimitInfo">
- Temel hesaplar için grup limiti [MAX_BASIC], [https://secondlife.com/premium/ özel] hesaplar
-içinse [MAX_PREMIUM] olarak belirlenmiştir.
-Hesabınızı indirgediyseniz, daha fazla gruba katılmak için önce grup sayınızı [MAX_BASIC] grubun altına düşürmelisiniz.
-
-[https://secondlife.com/my/account/membership.php Şimdi yükselt!]
+ Temel üyelikler [MAX_BASIC]'a kadar katılım sağlayabilir.
+Premium üyelikler [MAX_PREMIUM] 'a kadar izinlidir. [https://secondlife.com/my/account/membership.php? Daha fazla bilgi alın ya da üyeiliğinizi yükseltin]
+ <usetemplate name="okbutton" yestext="Kapat"/>
+ </notification>
+ <notification name="GroupLimitInfoPlus">
+ Temel üyelik sahibi yerleşimciler [MAX_BASIC]'a kadar olan gruplara katılabilir.
+Premium üyeler [MAX_PREMIUM] 'a kadar izinlidir. Premium Plus üyeler [MAX_PREMIUM_PLUS] 'a kadar izinlidir.
+[https://secondlife.com/my/account/membership.php? Daha fazla bilgi alın ya da üyeiliğinizi yükseltin]
<usetemplate name="okbutton" yestext="Kapat"/>
</notification>
<notification name="KickUser">
@@ -3303,6 +3313,22 @@ Güvenliğiniz için birkaç saniye engellenecek.
Sesli sohbetiniz moderatör tarafından engellendi.
<usetemplate name="okbutton" yestext="Tamam"/>
</notification>
+ <notification name="FailedToGetBenefits">
+ Maalesef, bu oturumun avantajlarıyla ilgili bilgilere ulaşamıyoruz. Normal prodüksiyon ortamında yaşanmaması gereken bir durumdur. Lütfen destek ekibiyle iletişime geçin. Bu oturum normal bir şekilde çalışmayacaktır, yeniden başlatmanızı öneririz.
+ <usetemplate name="okbutton" yestext="Tamam"/>
+ </notification>
+ <notification name="BulkUploadCostConfirmation">
+ Bu, toplam tutarı L$[COST] olan [COUNT] nesne yükleyecektir. Bu yüklemeye devam etmek istiyor musunuz?
+ <usetemplate name="okcancelbuttons" notext="İptal" yestext="Karşıya Yükle"/>
+ </notification>
+ <notification name="BulkUploadNoCompatibleFiles">
+ Seçili dosyalar aynı anda yüklenemez.
+ <usetemplate name="okbutton" yestext="Tamam"/>
+ </notification>
+ <notification name="BulkUploadIncompatibleFiles">
+ Seçili bazı dosyalar aynı anda yüklenemez.
+ <usetemplate name="okbutton" yestext="Tamam"/>
+ </notification>
<notification name="UploadCostConfirmation">
Bu karşıya yükleme işleminin maliyeti L$[PRICE] olacak, karşıya yüklemeye devam etmek istiyor musunuz?
<usetemplate name="okcancelbuttons" notext="İptal" yestext="Karşıya Yükle"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_people.xml b/indra/newview/skins/default/xui/tr/panel_people.xml
index 29ca4772fd..25d29fcbb5 100644
--- a/indra/newview/skins/default/xui/tr/panel_people.xml
+++ b/indra/newview/skins/default/xui/tr/panel_people.xml
@@ -18,7 +18,7 @@ Birlikte takılacak kişiler mi arıyorsunuz? [secondlife:///app/worldmap Dünya
<string name="no_groups_msg" value="Katılacak Gruplar mı arıyorsunuz? [secondlife:///app/search/groups Ara] deneyin."/>
<string name="MiniMapToolTipMsg" value="[REGION](Haritayı açmak için çift tıkla, yatay hareket için shift çek)"/>
<string name="AltMiniMapToolTipMsg" value="[REGION](Işınlamak için çift tıkla, yatay hareket için shift çek)"/>
- <string name="GroupCountWithInfo" value="[COUNT] gruba üyesiniz, daha [REMAINING] gruba üye olabilirsiniz. [secondlife:/// Daha fazlasını mı istiyorsunuz?]"/>
+ <string name="GroupCountWithInfo" value="[COUNT] gruba üyesin ve [REMAINING] daha gruba üye olabilirsin. [secondlife:/// Limitini arttır]"/>
<tab_container name="tabs">
<panel label="YAKIN" name="nearby_panel">
<panel label="bottom_panel" name="nearby_buttons_panel">
@@ -51,7 +51,7 @@ Birlikte takılacak kişiler mi arıyorsunuz? [secondlife:///app/worldmap Dünya
<dnd_button name="minus_btn" tool_tip="Seçilen gruptan ayrıl"/>
</panel>
<text name="groupcount">
- [COUNT] gruba üyesiniz, daha [REMAINING] gruba üye olabilirsiniz.
+ [COUNT] gruba üyesin ve [REMAINING] daha gruba üye olabilirsin.
</text>
</panel>
<panel label="SON" name="recent_panel">
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index 3fd466d71c..56fad978f5 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -1643,11 +1643,14 @@ Bu mesaj size gelmeye devam ederse lütfen http://support.secondlife.com adresin
<string name="MarketplaceUpdating">
güncelleniyor...
</string>
+ <string name="UploadFeeInfo">
+ Ücret, üyelik seviyene göre belirlenir. Yüksek seviyelere daha düşük ücretler uygulanır. [https://secondlife.com/my/account/membership.php? Daha fazla bilgi al]
+ </string>
<string name="Open landmarks">
- Açık yer imleri
+ Açık alanlar
</string>
<string name="Unconstrained">
- Kısıtsız
+ Serbest
</string>
<string name="no_transfer" value="(aktarım yok)"/>
<string name="no_modify" value="(değiştirme yok)"/>
@@ -5092,6 +5095,9 @@ Hizmetle ilişkili bilinen bir sorun olup olmadığını görmek için lütfen h
<string name="Chat">
Sohbet
</string>
+ <string name="BaseMembership">
+ Temel
+ </string>
<string name="DeleteItems">
Seçili öğeler silinsin mi?
</string>
diff --git a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
index fcf2800728..41c8c26ccc 100644
--- a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
@@ -59,8 +59,7 @@
</text>
<button label="立即購買" name="buy_btn"/>
<button label="取消" name="cancel_btn"/>
- <text name="info_cannot_buy">
+ <floater.string name="info_cannot_buy">
無法購買
- </text>
- <button label="繼續到網頁" name="error_web"/>
+ </floater.string>
</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml
index 881ca40338..6fc3e1129b 100644
--- a/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml
@@ -9,14 +9,10 @@
<text name="Multiple">
多重材質
</text>
- <radio_group name="mode_selection">
- <radio_item label="收納區" name="inventory" value="0"/>
- <radio_item label="本地" name="local" value="1"/>
- <radio_item label="確定產出" name="bake" value="2"/>
- </radio_group>
- <text name="unknown">
- 尺寸:[DIMENSIONS]
- </text>
+ <combo_box name="mode_selection">
+ <combo_box.item label="收納區" name="inventory" value="0"/>
+ <combo_box.item label="本地" name="local" value="1"/>
+ </combo_box>
<button label="預設" label_selected="預設" name="Default"/>
<button label="空白" label_selected="空白" name="Blank"/>
<button label="無" label_selected="無" name="None"/>
diff --git a/indra/newview/skins/default/xui/zh/menu_cof_attachment.xml b/indra/newview/skins/default/xui/zh/menu_cof_attachment.xml
index 876fef16df..6ab2220ca7 100644
--- a/indra/newview/skins/default/xui/zh/menu_cof_attachment.xml
+++ b/indra/newview/skins/default/xui/zh/menu_cof_attachment.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="COF Attachment">
+ <menu_item_call label="觸碰" name="touch_attach" />
+ <menu_item_call label="編輯" name="edit_item" />
<menu_item_call label="卸下" name="detach"/>
</context_menu>
diff --git a/indra/newview/skins/default/xui/zh/menu_inventory.xml b/indra/newview/skins/default/xui/zh/menu_inventory.xml
index 8b65b5c8de..10b170d4a4 100644
--- a/indra/newview/skins/default/xui/zh/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inventory.xml
@@ -105,6 +105,7 @@
<menu_item_call label="穿上" name="Wearable And Object Wear"/>
<menu label="附著到..." name="Attach To"/>
<menu label="附著到擡頭顯示" name="Attach To HUD"/>
+ <menu_item_call label="觸碰" name="Attachment Touch" />
<menu_item_call label="編輯" name="Wearable Edit"/>
<menu_item_call label="添加" name="Wearable Add"/>
<menu_item_call label="脫下" name="Take Off"/>
diff --git a/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml
index 576f7f3b73..0093eb68f1 100644
--- a/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/zh/menu_wearable_list_item.xml
@@ -3,6 +3,7 @@
<menu_item_call label="取代" name="wear_replace"/>
<menu_item_call label="穿上" name="wear_wear"/>
<menu_item_call label="添加" name="wear_add"/>
+ <menu_item_call label="觸碰" name="touch" />
<menu_item_call label="脫下裝扮 / 卸除附件" name="take_off_or_detach"/>
<menu_item_call label="卸下" name="detach"/>
<context_menu label="附著到..." name="wearable_attach_to"/>
diff --git a/indra/newview/skins/default/xui/zh/menu_wearing_gear.xml b/indra/newview/skins/default/xui/zh/menu_wearing_gear.xml
index 6184f956d1..f09d4cfba9 100644
--- a/indra/newview/skins/default/xui/zh/menu_wearing_gear.xml
+++ b/indra/newview/skins/default/xui/zh/menu_wearing_gear.xml
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<toggleable_menu name="Gear Wearing">
- <menu_item_call label="編輯裝扮" name="edit"/>
+ <menu_item_call label="觸碰" name="touch"/>
+ <menu_item_call label="編輯" name="edit_item"/>
+ <menu_item_call label="編輯裝扮" name="edit_outfit"/>
<menu_item_call label="脫下" name="takeoff"/>
<menu_item_call label="複製裝扮清單到剪貼簿" name="copy"/>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/zh/menu_wearing_tab.xml b/indra/newview/skins/default/xui/zh/menu_wearing_tab.xml
index dc9adcbd25..945297885e 100644
--- a/indra/newview/skins/default/xui/zh/menu_wearing_tab.xml
+++ b/indra/newview/skins/default/xui/zh/menu_wearing_tab.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<context_menu name="Wearing">
+ <menu_item_call label="觸碰" name="touch_attach"/>
<menu_item_call label="脫下" name="take_off"/>
<menu_item_call label="卸下" name="detach"/>
- <menu_item_call label="編輯裝扮" name="edit"/>
+ <menu_item_call label="編輯裝扮" name="edit_outfit"/>
<menu_item_call label="編輯" name="edit_item"/>
<menu_item_call label="顯示原件" name="show_original"/>
</context_menu>
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
index 63967fae37..e5d226a2a4 100644
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ b/indra/newview/tests/llsechandler_basic_test.cpp
@@ -124,6 +124,14 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
S32 LLMachineID::init() { return 1; }
+LLCertException::LLCertException(const LLSD& cert_data, const std::string& msg)
+ : LLException(msg),
+ mCertData(cert_data)
+{
+ LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
+}
+
+
// -------------------------------------------------------------------------------------------
// TUT
// -------------------------------------------------------------------------------------------
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f5edde1923..90a2af98f7 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -523,6 +523,11 @@ class WindowsManifest(ViewerManifest):
else:
self.path("fmod.dll")
+ if self.args['openal'] == 'ON':
+ # Get openal dll
+ self.path("OpenAL32.dll")
+ self.path("alut.dll")
+
# For textures
self.path("openjpeg.dll")
@@ -1515,7 +1520,6 @@ class Linux_i686_Manifest(LinuxManifest):
print "Skipping libfmod.so - not found"
pass
-
# Vivox runtimes
with self.prefix(src=relpkgdir, dst="bin"):
self.path("SLVoice")
@@ -1545,10 +1549,12 @@ if __name__ == "__main__":
print('%s \\\n%s' %
(sys.executable,
' '.join((("'%s'" % arg) if ' ' in arg else arg) for arg in sys.argv)))
+ # fmodstudio and openal can be used simultaneously and controled by environment
extra_arguments = [
dict(name='bugsplat', description="""BugSplat database to which to post crashes,
if BugSplat crash reporting is desired""", default=''),
dict(name='fmodstudio', description="""Indication if fmod studio libraries are needed""", default='OFF'),
+ dict(name='openal', description="""Indication openal libraries are needed""", default='OFF'),
]
try:
main(extra=extra_arguments)
diff --git a/indra/test/llpermissions_tut.cpp b/indra/test/llpermissions_tut.cpp
index fa4b085fd3..e6ccd5ecb7 100644
--- a/indra/test/llpermissions_tut.cpp
+++ b/indra/test/llpermissions_tut.cpp
@@ -406,43 +406,6 @@ namespace tut
template<> template<>
void permission_object_t::test<20>()
{
- LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
- if(!fp)
- {
- LL_ERRS() << "file couldn't be opened\n" << LL_ENDL;
- return;
- }
- LLPermissions perm,perm1;
- LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
- LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
- LLUUID lastOwner("5e47a0dc-97bf-44e0-8b40-de06718cee9d");
- LLUUID group("9c8eca51-53d5-42a7-bb58-cef070395db8");
- perm.init(creator,owner,lastOwner,group);
-
- U32 base = PERM_TRANSFER | PERM_COPY;
- U32 ownerp = PERM_TRANSFER;
- U32 groupp = PERM_TRANSFER;
- U32 everyone = PERM_TRANSFER;
- U32 next = PERM_NONE;
-
- perm.initMasks(base, ownerp, everyone, groupp, next);
-
- ensure("Permissions export failed", perm.exportFile(fp));
- fclose(fp);
- fp = LLFile::fopen("linden_file.dat","r+");
- if(!fp)
- {
- LL_ERRS() << "file couldn't be opened\n" << LL_ENDL;
- return;
- }
- ensure("Permissions import failed", perm1.importFile(fp));
- fclose(fp);
- ensure_equals("exportFile()/importFile():failed to export and import the data ", perm1, perm);
-}
-
- template<> template<>
- void permission_object_t::test<21>()
- {
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
LLUUID owner("68edcf47-ccd7-45b8-9f90-1649d7f12806");
@@ -467,14 +430,7 @@ namespace tut
}
template<> template<>
- void permission_object_t::test<22>()
- {
- // Deleted LLPermissions::exportFileXML() and LLPermissions::importXML()
- // because I can't find any non-test code references to it. 2009-05-04 JC
- }
-
- template<> template<>
- void permission_object_t::test<23>()
+ void permission_object_t::test<21>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
@@ -490,7 +446,7 @@ namespace tut
}
template<> template<>
- void permission_object_t::test<24>()
+ void permission_object_t::test<22>()
{
LLPermissions perm,perm1;
LLUUID creator("abf0d56b-82e5-47a2-a8ad-74741bb2c29e");
@@ -513,7 +469,7 @@ namespace tut
}
template<> template<>
- void permission_object_t::test<25>()
+ void permission_object_t::test<23>()
{
LLAggregatePermissions AggrPermission;
LLAggregatePermissions AggrPermission1;
diff --git a/indra/test/llsaleinfo_tut.cpp b/indra/test/llsaleinfo_tut.cpp
index 5f4d9186a8..b7b207610f 100644
--- a/indra/test/llsaleinfo_tut.cpp
+++ b/indra/test/llsaleinfo_tut.cpp
@@ -107,41 +107,6 @@ namespace tut
template<> template<>
void llsaleinfo_test_t::test<2>()
{
-
- LLFILE* fp = LLFile::fopen("linden_file.dat","w+");
- if(!fp)
- {
- LL_ERRS() << "file could not be opened\n" << LL_ENDL;
- return;
- }
-
- S32 sale_price = 43500;
- LLSaleInfo llsaleinfo(LLSaleInfo::FS_COPY, sale_price);
-
- llsaleinfo.exportFile(fp);
- fclose(fp);
-
- LLSaleInfo llsaleinfo1;
- U32 perm_mask;
- BOOL has_perm_mask;
- fp = LLFile::fopen("linden_file.dat","r");
-
- if(!fp)
- {
- LL_ERRS() << "file coudnt be opened\n" << LL_ENDL;
- return;
- }
-
- llsaleinfo1.importFile(fp, has_perm_mask, perm_mask);
- fclose(fp);
-
- ensure("importFile() fn failed ", llsaleinfo.getSaleType() == llsaleinfo1.getSaleType() &&
- llsaleinfo.getSalePrice() == llsaleinfo1.getSalePrice());
- }
-
- template<> template<>
- void llsaleinfo_test_t::test<3>()
- {
S32 sale_price = 525452;
LLSaleInfo llsaleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
@@ -160,14 +125,7 @@ namespace tut
}
template<> template<>
- void llsaleinfo_test_t::test<4>()
- {
- // Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML()
- // because I can't find any non-test code references to it. 2009-05-04 JC
- }
-
- template<> template<>
- void llsaleinfo_test_t::test<5>()
+ void llsaleinfo_test_t::test<3>()
{
S32 sale_price = 99000;
LLSaleInfo saleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
@@ -186,7 +144,7 @@ namespace tut
//static EForSale lookup(const char* name) fn test
template<> template<>
- void llsaleinfo_test_t::test<6>()
+ void llsaleinfo_test_t::test<4>()
{
S32 sale_price = 233223;
LLSaleInfo::EForSale ret_type = LLSaleInfo::lookup("orig");
@@ -200,7 +158,7 @@ namespace tut
//void LLSaleInfo::accumulate(const LLSaleInfo& sale_info) fn test
template<> template<>
- void llsaleinfo_test_t::test<7>()
+ void llsaleinfo_test_t::test<5>()
{
S32 sale_price = 20;
LLSaleInfo saleinfo(LLSaleInfo::FS_COPY, sale_price);
@@ -213,7 +171,7 @@ namespace tut
// test cases of bool operator==(const LLSaleInfo &rhs) fn
// test case of bool operator!=(const LLSaleInfo &rhs) fn
template<> template<>
- void llsaleinfo_test_t::test<8>()
+ void llsaleinfo_test_t::test<6>()
{
S32 sale_price = 55000;
LLSaleInfo saleinfo(LLSaleInfo::FS_ORIGINAL, sale_price);
@@ -225,7 +183,7 @@ namespace tut
}
template<> template<>
- void llsaleinfo_test_t::test<9>()
+ void llsaleinfo_test_t::test<7>()
{
//TBD: void LLSaleInfo::packMessage(LLMessageSystem* msg) const