summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--[-rwxr-xr-x]indra/cmake/FMOD.cmake0
-rw-r--r--indra/cmake/Variables.cmake2
-rw-r--r--[-rwxr-xr-x]indra/cmake/run_build_test.py0
-rw-r--r--indra/integration_tests/llui_libtest/llwidgetreg.cpp2
-rw-r--r--indra/llcharacter/llcharacter.cpp25
-rw-r--r--indra/llcharacter/llcharacter.h1
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp73
-rw-r--r--indra/llcharacter/llkeyframemotion.h2
-rw-r--r--indra/llcommon/CMakeLists.txt1
-rw-r--r--indra/llcommon/llaccountingquota.h80
-rw-r--r--indra/llcommon/llchat.h3
-rw-r--r--indra/llcommon/llfoldertype.cpp2
-rw-r--r--indra/llcommon/llfoldertype.h5
-rw-r--r--indra/llcommon/llsdserialize.cpp4
-rw-r--r--indra/llcommon/llstat.cpp2
-rw-r--r--indra/llcommon/llsys.cpp25
-rw-r--r--indra/llcommon/llversionviewer.h4
-rw-r--r--indra/llinventory/llparcel.cpp36
-rw-r--r--indra/llinventory/llparcel.h34
-rw-r--r--indra/llinventory/llparcelflags.h2
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp2
-rw-r--r--indra/llmath/CMakeLists.txt4
-rw-r--r--indra/llmath/llcalc.cpp145
-rw-r--r--indra/llmath/llcalc.h83
-rw-r--r--indra/llmath/llcalcparser.cpp46
-rw-r--r--indra/llmath/llcalcparser.h174
-rw-r--r--indra/llmath/lloctree.h11
-rw-r--r--indra/llmath/llvolume.cpp373
-rw-r--r--indra/llmath/llvolume.h8
-rw-r--r--indra/llmessage/lldatapacker.h5
-rw-r--r--indra/llmessage/lliosocket.cpp26
-rw-r--r--indra/llmessage/lliosocket.h11
-rw-r--r--indra/llmessage/message_prehash.cpp4
-rw-r--r--indra/llmessage/message_prehash.h4
-rw-r--r--indra/llmessage/tests/commtest.h64
-rw-r--r--indra/llmessage/tests/test_llsdmessage_peer.py41
-rw-r--r--indra/llmessage/tests/testrunner.py201
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp2759
-rw-r--r--indra/llplugin/llpluginclassmedia.h841
-rw-r--r--indra/llprimitive/llmodel.cpp206
-rw-r--r--indra/llprimitive/llmodel.h2
-rw-r--r--indra/llrender/llfontgl.cpp2
-rw-r--r--indra/llrender/llgl.cpp180
-rw-r--r--indra/llrender/llgl.h11
-rw-r--r--indra/llrender/llglheaders.h66
-rw-r--r--indra/llrender/llglslshader.cpp55
-rw-r--r--indra/llrender/llglslshader.h4
-rw-r--r--indra/llrender/llimagegl.cpp15
-rw-r--r--indra/llrender/llimagegl.h2
-rw-r--r--indra/llrender/llrender.cpp41
-rw-r--r--indra/llrender/llrender.h1
-rw-r--r--indra/llrender/llrendertarget.cpp424
-rw-r--r--indra/llrender/llrendertarget.h26
-rw-r--r--indra/llrender/llshadermgr.cpp258
-rw-r--r--indra/llrender/llshadermgr.h5
-rw-r--r--indra/llrender/llvertexbuffer.cpp416
-rw-r--r--indra/llrender/llvertexbuffer.h58
-rw-r--r--indra/llui/CMakeLists.txt22
-rw-r--r--indra/llui/llaccordionctrltab.cpp2
-rw-r--r--indra/llui/llbadge.cpp274
-rw-r--r--indra/llui/llbadge.h159
-rw-r--r--indra/llui/llbadgeowner.cpp126
-rw-r--r--indra/llui/llbadgeowner.h (renamed from indra/newview/lldrawpoolclouds.h)57
-rw-r--r--indra/llui/llbutton.cpp71
-rw-r--r--indra/llui/llbutton.h16
-rw-r--r--indra/llui/llconsole.cpp13
-rw-r--r--indra/llui/lllayoutstack.cpp138
-rw-r--r--indra/llui/lllayoutstack.h36
-rw-r--r--indra/llui/lllineeditor.cpp156
-rw-r--r--indra/llui/lllineeditor.h13
-rw-r--r--indra/llui/llloadingindicator.h2
-rw-r--r--indra/llui/llmultislider.cpp2
-rw-r--r--indra/llui/llpanel.cpp8
-rw-r--r--indra/llui/llpanel.h5
-rw-r--r--indra/llui/llresmgr.cpp2
-rw-r--r--indra/llui/llspinctrl.cpp25
-rw-r--r--indra/llui/llspinctrl.h1
-rw-r--r--indra/llui/lltextbase.cpp119
-rw-r--r--indra/llui/lltextvalidate.cpp33
-rw-r--r--indra/llui/lltextvalidate.h1
-rw-r--r--indra/llui/lltimectrl.cpp432
-rw-r--r--indra/llui/lltimectrl.h131
-rw-r--r--indra/llui/lluictrl.cpp36
-rw-r--r--indra/llui/lluictrl.h8
-rw-r--r--indra/llui/llview.cpp15
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp2
-rw-r--r--indra/llvfs/CMakeLists.txt34
-rw-r--r--indra/llvfs/lldir_mac.cpp32
-rw-r--r--indra/llvfs/lldir_mac.h1
-rw-r--r--indra/llvfs/lldiriterator.cpp21
-rw-r--r--indra/llvfs/tests/lldiriterator_test.cpp65
-rw-r--r--indra/llwindow/llkeyboardheadless.cpp25
-rw-r--r--indra/llxuixml/llinitparam.cpp2
-rw-r--r--indra/llxuixml/llinitparam.h7
-rw-r--r--indra/lscript/lscript_compile/indra.l2
-rw-r--r--indra/lscript/lscript_library/lscript_library.cpp3
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp67
-rw-r--r--indra/newview/CMakeLists.txt145
-rw-r--r--indra/newview/app_settings/keys.xml2
-rw-r--r--indra/newview/app_settings/keywords.ini1
-rw-r--r--indra/newview/app_settings/logcontrol.xml2
-rw-r--r--indra/newview/app_settings/settings.xml390
-rw-r--r--indra/newview/app_settings/settings_minimal.xml13
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl7
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl67
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl36
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl21
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl9
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl113
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl79
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl165
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl40
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl23
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/giF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/giV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl65
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl137
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl232
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl108
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl9
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl133
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyF.glsl44
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyV.glsl140
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl318
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl234
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/starsF.glsl19
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/starsV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl123
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/effects/glowV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/terrainF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/terrainV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/environment/waterV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/highlightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/highlightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinyV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/transportF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl125
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl36
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl27
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl244
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl54
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl307
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl245
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl202
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl241
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/blurF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/blurV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/extractF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/effects/simpleF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/terrainF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/terrainV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/waterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl23
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl25
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl23
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl35
-rw-r--r--indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class2/objects/shinyV.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class2/objects/simpleV.glsl33
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/skyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/skyV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/transportF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/giV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/treeF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl2
-rw-r--r--indra/newview/app_settings/windlight/days/Colder%20Tones.xml28
-rw-r--r--indra/newview/app_settings/windlight/days/Dynamic%20Richness.xml32
-rw-r--r--indra/newview/app_settings/windlight/days/Pirate%27s%20Dream.xml44
-rw-r--r--indra/newview/app_settings/windlight/days/Psycho%20Strobe%21.xml72
-rw-r--r--indra/newview/app_settings/windlight/days/Tropicalia.xml32
-rw-r--r--indra/newview/app_settings/windlight/days/Weird-O.xml56
-rw-r--r--indra/newview/app_settings/windlight/skies/Midday.xml141
-rw-r--r--indra/newview/app_settings/windlight/skies/Midnight.xml141
-rw-r--r--indra/newview/app_settings/windlight/skies/Sunrise.xml141
-rw-r--r--indra/newview/app_settings/windlight/skies/Sunset.xml142
-rw-r--r--indra/newview/featuretable.txt19
-rw-r--r--indra/newview/featuretable_linux.txt17
-rw-r--r--indra/newview/featuretable_mac.txt45
-rw-r--r--indra/newview/featuretable_xp.txt19
-rw-r--r--indra/newview/groupchatlistener.cpp21
-rw-r--r--indra/newview/groupchatlistener.h21
-rw-r--r--indra/newview/llaccountingquotamanager.cpp278
-rw-r--r--indra/newview/llaccountingquotamanager.h55
-rw-r--r--indra/newview/llagent.cpp105
-rw-r--r--indra/newview/llagent.h16
-rw-r--r--indra/newview/llagentcamera.cpp2
-rw-r--r--indra/newview/llagentlistener.cpp439
-rw-r--r--indra/newview/llagentlistener.h27
-rw-r--r--indra/newview/llagentwearables.cpp2
-rw-r--r--indra/newview/llappviewer.cpp119
-rw-r--r--indra/newview/llappviewerwin32.cpp39
-rw-r--r--indra/newview/llassetuploadresponders.cpp14
-rw-r--r--indra/newview/llassetuploadresponders.h1
-rwxr-xr-x[-rw-r--r--]indra/newview/llavataractions.cpp73
-rw-r--r--indra/newview/llavataractions.h3
-rw-r--r--indra/newview/llbottomtray.cpp6
-rw-r--r--indra/newview/llbottomtray.h4
-rw-r--r--indra/newview/llchatbar.cpp6
-rw-r--r--indra/newview/llcloud.cpp538
-rw-r--r--indra/newview/llcloud.h199
-rw-r--r--indra/newview/llcofwearables.cpp5
-rwxr-xr-x[-rw-r--r--]indra/newview/llcommandhandler.cpp0
-rw-r--r--indra/newview/lldaycyclemanager.cpp230
-rw-r--r--indra/newview/lldaycyclemanager.h84
-rw-r--r--indra/newview/lldebugview.cpp3
-rw-r--r--indra/newview/lldrawable.cpp17
-rw-r--r--indra/newview/lldrawable.h1
-rw-r--r--indra/newview/lldrawpool.cpp54
-rw-r--r--indra/newview/lldrawpool.h4
-rw-r--r--indra/newview/lldrawpoolalpha.cpp173
-rw-r--r--indra/newview/lldrawpoolavatar.cpp38
-rw-r--r--indra/newview/lldrawpoolbump.cpp116
-rw-r--r--indra/newview/lldrawpoolbump.h2
-rw-r--r--indra/newview/lldrawpoolclouds.cpp97
-rw-r--r--indra/newview/lldrawpoolsimple.cpp114
-rw-r--r--indra/newview/lldrawpoolsimple.h14
-rw-r--r--indra/newview/lldrawpoolterrain.cpp6
-rw-r--r--indra/newview/lldrawpooltree.cpp4
-rw-r--r--indra/newview/lldrawpoolwater.cpp4
-rw-r--r--indra/newview/lldrawpoolwlsky.cpp99
-rw-r--r--indra/newview/lldrawpoolwlsky.h8
-rw-r--r--indra/newview/llenvmanager.cpp684
-rw-r--r--indra/newview/llenvmanager.h283
-rw-r--r--indra/newview/llface.cpp185
-rw-r--r--indra/newview/llface.h3
-rw-r--r--indra/newview/llfeaturemanager.cpp2
-rw-r--r--indra/newview/llfilteredwearablelist.cpp1
-rw-r--r--indra/newview/llfirstuse.cpp2
-rw-r--r--indra/newview/llflexibleobject.cpp8
-rw-r--r--indra/newview/llfloaterauction.cpp3
-rw-r--r--indra/newview/llfloaterbuyland.cpp18
-rw-r--r--indra/newview/llfloaterdaycycle.cpp531
-rw-r--r--indra/newview/llfloaterdaycycle.h120
-rw-r--r--indra/newview/llfloaterdeleteenvpreset.cpp285
-rw-r--r--indra/newview/llfloaterdeleteenvpreset.h62
-rw-r--r--indra/newview/llfloatereditdaycycle.cpp825
-rw-r--r--indra/newview/llfloatereditdaycycle.h137
-rw-r--r--indra/newview/llfloatereditsky.cpp923
-rw-r--r--indra/newview/llfloatereditsky.h113
-rw-r--r--indra/newview/llfloatereditwater.cpp772
-rw-r--r--indra/newview/llfloatereditwater.h (renamed from indra/newview/llfloaterwater.h)112
-rw-r--r--indra/newview/llfloaterenvironmentsettings.cpp282
-rw-r--r--indra/newview/llfloaterenvironmentsettings.h71
-rw-r--r--indra/newview/llfloaterenvsettings.cpp268
-rw-r--r--indra/newview/llfloaterenvsettings.h83
-rw-r--r--indra/newview/llfloaterhelpbrowser.cpp9
-rw-r--r--indra/newview/llfloaterhelpbrowser.h1
-rw-r--r--indra/newview/llfloaterland.cpp17
-rw-r--r--indra/newview/llfloaterland.h1
-rw-r--r--indra/newview/llfloatermodelpreview.cpp693
-rw-r--r--indra/newview/llfloatermodelpreview.h31
-rw-r--r--indra/newview/llfloatermodelwizard.cpp37
-rwxr-xr-x[-rw-r--r--]indra/newview/llfloaterpreference.cpp41
-rw-r--r--indra/newview/llfloaterpreference.h6
-rw-r--r--indra/newview/llfloaterregioninfo.cpp1027
-rw-r--r--indra/newview/llfloaterregioninfo.h120
-rw-r--r--indra/newview/llfloatersellland.cpp3
-rw-r--r--indra/newview/llfloatersounddevices.cpp3
-rw-r--r--indra/newview/llfloatertools.cpp8
-rw-r--r--indra/newview/llfloaterwater.cpp625
-rw-r--r--indra/newview/llfloaterwebcontent.cpp18
-rw-r--r--indra/newview/llfloaterwebcontent.h2
-rw-r--r--indra/newview/llfloaterwindlight.cpp875
-rw-r--r--indra/newview/llfloaterwindlight.h112
-rwxr-xr-x[-rw-r--r--]indra/newview/llfloaterworldmap.cpp21
-rw-r--r--indra/newview/llfolderview.cpp96
-rw-r--r--indra/newview/llfolderview.h26
-rw-r--r--indra/newview/llfolderviewitem.cpp202
-rw-r--r--indra/newview/llfolderviewitem.h36
-rw-r--r--indra/newview/llgesturelistener.cpp159
-rw-r--r--indra/newview/llgesturelistener.h52
-rw-r--r--indra/newview/llgesturemgr.cpp2
-rw-r--r--indra/newview/llgesturemgr.h10
-rw-r--r--indra/newview/llinventorybridge.cpp48
-rw-r--r--indra/newview/llinventorybridge.h4
-rw-r--r--indra/newview/llinventoryfilter.cpp123
-rw-r--r--indra/newview/llinventoryfilter.h6
-rw-r--r--indra/newview/llinventoryfunctions.h24
-rw-r--r--indra/newview/llinventorymodel.cpp4
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp2
-rw-r--r--indra/newview/llinventoryobserver.cpp28
-rw-r--r--indra/newview/llinventoryobserver.h22
-rw-r--r--indra/newview/llinventorypanel.cpp477
-rw-r--r--indra/newview/llinventorypanel.h50
-rw-r--r--indra/newview/lllocationinputctrl.cpp13
-rw-r--r--indra/newview/lllocationinputctrl.h16
-rw-r--r--indra/newview/lllogchat.cpp2
-rw-r--r--indra/newview/llmanipscale.cpp5
-rw-r--r--indra/newview/llmediactrl.cpp18
-rw-r--r--indra/newview/llmeshrepository.cpp881
-rw-r--r--indra/newview/llmeshrepository.h30
-rw-r--r--indra/newview/llnearbychatbar.cpp8
-rw-r--r--indra/newview/llnearbychatbarlistener.cpp100
-rw-r--r--indra/newview/llnearbychatbarlistener.h50
-rw-r--r--indra/newview/llnearbychathandler.cpp86
-rw-r--r--indra/newview/llnearbychathandler.h4
-rw-r--r--indra/newview/llnotificationmanager.h2
-rw-r--r--indra/newview/lloutfitslist.cpp2
-rw-r--r--indra/newview/llpanelappearancetab.cpp1
-rw-r--r--indra/newview/llpanelface.cpp21
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp95
-rw-r--r--indra/newview/llpanelimcontrolpanel.h8
-rw-r--r--indra/newview/llpanellandaudio.cpp22
-rw-r--r--indra/newview/llpanellandaudio.h2
-rw-r--r--indra/newview/llpanellandmarks.cpp9
-rw-r--r--indra/newview/llpanellogin.cpp13
-rw-r--r--indra/newview/llpanelmaininventory.cpp32
-rw-r--r--indra/newview/llpanelmaininventory.h4
-rw-r--r--indra/newview/llpanelmarketplaceinbox.cpp248
-rw-r--r--indra/newview/llpanelmarketplaceinbox.h78
-rw-r--r--indra/newview/llpanelmarketplaceinboxinventory.cpp167
-rw-r--r--indra/newview/llpanelmarketplaceinboxinventory.h77
-rw-r--r--indra/newview/llpanelmarketplaceoutbox.cpp209
-rw-r--r--indra/newview/llpanelmarketplaceoutbox.h82
-rw-r--r--indra/newview/llpanelobject.cpp161
-rw-r--r--indra/newview/llpanelobject.h5
-rw-r--r--indra/newview/llpanelobjectinventory.cpp62
-rw-r--r--indra/newview/llpaneloutfitedit.cpp2
-rwxr-xr-x[-rw-r--r--]indra/newview/llpanelpicks.cpp0
-rwxr-xr-x[-rw-r--r--]indra/newview/llpanelpicks.h0
-rw-r--r--indra/newview/llpanelplaceprofile.cpp19
-rw-r--r--indra/newview/llpanelplaceprofile.h2
-rw-r--r--indra/newview/llpanelplaces.cpp7
-rwxr-xr-x[-rw-r--r--]indra/newview/llpanelprofile.cpp0
-rwxr-xr-x[-rw-r--r--]indra/newview/llpanelprofile.h0
-rw-r--r--indra/newview/llpaneltopinfobar.cpp8
-rw-r--r--indra/newview/llpaneltopinfobar.h13
-rw-r--r--indra/newview/llpanelvoicedevicesettings.cpp17
-rw-r--r--indra/newview/llpanelvolume.cpp108
-rw-r--r--indra/newview/llpanelvolume.h6
-rw-r--r--indra/newview/llpanelwearing.cpp26
-rw-r--r--indra/newview/llpanelwearing.h2
-rw-r--r--indra/newview/llplacesinventorypanel.cpp85
-rw-r--r--indra/newview/llplacesinventorypanel.h2
-rw-r--r--indra/newview/llpreviewgesture.cpp1
-rw-r--r--indra/newview/llpreviewnotecard.cpp25
-rw-r--r--indra/newview/llprogressview.cpp88
-rw-r--r--indra/newview/llprogressview.h20
-rw-r--r--indra/newview/llregioninfomodel.cpp217
-rw-r--r--indra/newview/llregioninfomodel.h99
-rw-r--r--indra/newview/llselectmgr.cpp10
-rw-r--r--indra/newview/llsidepanelappearance.cpp1
-rw-r--r--indra/newview/llsidepanelinventory.cpp454
-rw-r--r--indra/newview/llsidepanelinventory.h31
-rw-r--r--indra/newview/llsidepanelinventorysubpanel.cpp4
-rw-r--r--indra/newview/llsidepanelinventorysubpanel.h2
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp7
-rw-r--r--indra/newview/llsidepaneliteminfo.h2
-rw-r--r--indra/newview/llsidetray.cpp177
-rw-r--r--indra/newview/llsidetray.h13
-rw-r--r--indra/newview/llspatialpartition.cpp146
-rw-r--r--indra/newview/llspatialpartition.h15
-rw-r--r--indra/newview/llstartup.cpp24
-rw-r--r--indra/newview/lltexlayer.cpp87
-rw-r--r--indra/newview/lltexlayer.h6
-rw-r--r--indra/newview/lltexturecache.cpp8
-rw-r--r--indra/newview/lltexturectrl.cpp5
-rw-r--r--indra/newview/lltoolgrab.cpp99
-rw-r--r--indra/newview/lltoolgrab.h7
-rw-r--r--indra/newview/lltoolpie.cpp1
-rw-r--r--indra/newview/lltranslate.cpp6
-rw-r--r--indra/newview/llviewerchat.cpp8
-rw-r--r--indra/newview/llviewercontrol.cpp34
-rw-r--r--indra/newview/llviewerdisplay.cpp11
-rw-r--r--indra/newview/llviewerfloaterreg.cpp18
-rw-r--r--indra/newview/llviewerfoldertype.cpp4
-rw-r--r--indra/newview/llviewerhelp.cpp16
-rw-r--r--indra/newview/llviewerinventory.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp111
-rw-r--r--indra/newview/llviewermedia.h5
-rw-r--r--indra/newview/llviewermenu.cpp158
-rw-r--r--indra/newview/llviewermenufile.cpp76
-rw-r--r--indra/newview/llviewermenufile.h17
-rw-r--r--indra/newview/llviewermessage.cpp180
-rw-r--r--indra/newview/llviewermessage.h2
-rw-r--r--indra/newview/llviewerobject.cpp56
-rw-r--r--indra/newview/llviewerobject.h13
-rw-r--r--indra/newview/llviewerobjectlist.cpp30
-rw-r--r--indra/newview/llviewerobjectlist.h4
-rw-r--r--indra/newview/llviewerparcelmgr.cpp6
-rw-r--r--indra/newview/llviewerprecompiledheaders.h2
-rw-r--r--indra/newview/llviewerregion.cpp106
-rw-r--r--indra/newview/llviewerregion.h16
-rw-r--r--indra/newview/llviewershadermgr.cpp496
-rw-r--r--indra/newview/llviewershadermgr.h31
-rw-r--r--indra/newview/llviewertexture.cpp19
-rw-r--r--indra/newview/llviewertexture.h3
-rw-r--r--indra/newview/llviewertexturelist.cpp46
-rw-r--r--indra/newview/llviewertexturelist.h7
-rw-r--r--indra/newview/llviewerwindow.cpp14
-rw-r--r--indra/newview/llviewerwindow.h1
-rw-r--r--indra/newview/llvlmanager.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp114
-rw-r--r--indra/newview/llvoavatar.h8
-rw-r--r--indra/newview/llvocache.cpp14
-rw-r--r--indra/newview/llvoclouds.cpp293
-rw-r--r--indra/newview/llvoclouds.h79
-rw-r--r--indra/newview/llvoicevivox.cpp303
-rw-r--r--indra/newview/llvoicevivox.h15
-rw-r--r--indra/newview/llvopartgroup.cpp13
-rw-r--r--indra/newview/llvosky.cpp44
-rw-r--r--indra/newview/llvosurfacepatch.cpp2
-rw-r--r--indra/newview/llvotree.cpp5
-rw-r--r--indra/newview/llvovolume.cpp315
-rw-r--r--indra/newview/llvowlsky.cpp4
-rw-r--r--indra/newview/llwaterparammanager.cpp332
-rw-r--r--indra/newview/llwaterparammanager.h76
-rw-r--r--indra/newview/llwaterparamset.cpp44
-rw-r--r--indra/newview/llwaterparamset.h1
-rw-r--r--indra/newview/llwlanimator.cpp202
-rw-r--r--indra/newview/llwlanimator.h86
-rw-r--r--indra/newview/llwldaycycle.cpp240
-rw-r--r--indra/newview/llwldaycycle.h54
-rw-r--r--indra/newview/llwlhandlers.cpp203
-rw-r--r--indra/newview/llwlhandlers.h106
-rw-r--r--indra/newview/llwlparammanager.cpp574
-rw-r--r--indra/newview/llwlparammanager.h210
-rw-r--r--indra/newview/llwlparamset.cpp60
-rw-r--r--indra/newview/llwlparamset.h3
-rw-r--r--indra/newview/llworld.cpp94
-rw-r--r--indra/newview/pipeline.cpp302
-rw-r--r--indra/newview/pipeline.h24
-rw-r--r--indra/newview/skins/default/colors.xml24
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gift.pngbin0 -> 1335 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Disabled.pngbin0 -> 1848 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Off.pngbin0 -> 1835 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_On.pngbin0 -> 1851 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_On_Over.pngbin0 -> 1863 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.pngbin0 -> 1912 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Over.pngbin0 -> 1826 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Press.pngbin0 -> 1891 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.pngbin0 -> 1848 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.pngbin0 -> 1807 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.pngbin0 -> 1819 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.pngbin0 -> 1894 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.pngbin0 -> 1921 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.pngbin0 -> 1853 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected.pngbin0 -> 1894 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.pngbin0 -> 1840 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.pngbin0 -> 1870 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.pngbin0 -> 1912 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Dark.pngbin0 -> 3194 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Light.pngbin0 -> 3189 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Dark.pngbin0 -> 3011 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Light.pngbin0 -> 3011 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Disabled.pngbin0 -> 1187 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Enabled.pngbin0 -> 1168 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_1.pngbin0 -> 1149 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_2.pngbin0 -> 1147 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_3.pngbin0 -> 1211 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_4.pngbin0 -> 1205 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_5.pngbin0 -> 1137 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_6.pngbin0 -> 1164 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml41
-rw-r--r--indra/newview/skins/default/textures/widgets/Badge_Background.pngbin0 -> 1352 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Badge_Border.pngbin0 -> 1565 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.pngbin0 -> 1067 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.pngbin0 -> 1086 bytes
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml12
-rw-r--r--indra/newview/tests/lldir_stub.cpp45
-rw-r--r--indra/newview/tests/llglslshader_stub.cpp22
-rw-r--r--indra/newview/tests/llpipeline_stub.cpp15
-rw-r--r--indra/newview/tests/llsky_stub.cpp20
-rw-r--r--indra/newview/tests/llviewershadermgr_stub.cpp33
-rw-r--r--indra/newview/tests/llwlanimator_stub.cpp12
-rw-r--r--indra/newview/tests/llwldaycycle_stub.cpp35
-rw-r--r--indra/newview/tests/llwlparammanager_test.cpp254
-rw-r--r--indra/newview/tests/llwlparamset_stub.cpp24
-rw-r--r--indra/viewer_components/login/lllogin.cpp2
622 files changed, 27899 insertions, 11274 deletions
diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake
index cb5124812d..cb5124812d 100755..100644
--- a/indra/cmake/FMOD.cmake
+++ b/indra/cmake/FMOD.cmake
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index cfccd29def..4cbf7aa043 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -102,7 +102,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# To support a different SDK update these Xcode settings:
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
- set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "4.2")
+ set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "4.0")
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
# NOTE: To attempt an i386/PPC Universal build, add this on the configure line:
diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py
index ce2d1e0386..ce2d1e0386 100755..100644
--- a/indra/cmake/run_build_test.py
+++ b/indra/cmake/run_build_test.py
diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp
index 0d0d9fbff6..cbf6021119 100644
--- a/indra/integration_tests/llui_libtest/llwidgetreg.cpp
+++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp
@@ -49,6 +49,7 @@
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltexteditor.h"
+#include "lltimectrl.h"
#include "llflyoutbutton.h"
#include "llfiltereditor.h"
#include "lllayoutstack.h"
@@ -92,6 +93,7 @@ void LLWidgetReg::initClass(bool register_widgets)
//LLDefaultChildRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder");
LLDefaultChildRegistry::Register<LLTabContainer> tab_container("tab_container");
LLDefaultChildRegistry::Register<LLTextBox> text("text");
+ LLDefaultChildRegistry::Register<LLTimeCtrl> time("time");
LLDefaultChildRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor");
LLDefaultChildRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl");
LLDefaultChildRegistry::Register<LLStatView> stat_view("stat_view");
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 5f84be2c5d..c9fb8534f1 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -38,7 +38,7 @@
LLStringTable LLCharacter::sVisualParamNames(1024);
std::vector< LLCharacter* > LLCharacter::sInstances;
-
+BOOL LLCharacter::sAllowInstancesChange = TRUE ;
//-----------------------------------------------------------------------------
// LLCharacter()
@@ -51,8 +51,10 @@ LLCharacter::LLCharacter()
mAppearanceSerialNum( 0 ),
mSkeletonSerialNum( 0 )
{
- mMotionController.setCharacter( this );
+ llassert_always(sAllowInstancesChange) ;
sInstances.push_back(this);
+
+ mMotionController.setCharacter( this );
mPauseRequest = new LLPauseRequestHandle();
}
@@ -62,18 +64,29 @@ LLCharacter::LLCharacter()
// Class Destructor
//-----------------------------------------------------------------------------
LLCharacter::~LLCharacter()
-{
+{
for (LLVisualParam *param = getFirstVisualParam();
param;
param = getNextVisualParam())
{
delete param;
}
- std::vector<LLCharacter*>::iterator iter = std::find(sInstances.begin(), sInstances.end(), this);
- if (iter != sInstances.end())
+
+ U32 i ;
+ U32 size = sInstances.size() ;
+ for(i = 0 ; i < size ; i++)
{
- sInstances.erase(iter);
+ if(sInstances[i] == this)
+ {
+ break ;
+ }
}
+
+ llassert_always(i < size) ;
+
+ llassert_always(sAllowInstancesChange) ;
+ sInstances[i] = sInstances[size - 1] ;
+ sInstances.pop_back() ;
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index a6347fcc3c..e81a27c2bc 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -266,6 +266,7 @@ public:
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
static std::vector< LLCharacter* > sInstances;
+ static BOOL sAllowInstancesChange ; //debug use
protected:
LLMotionController mMotionController;
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 9df033a4ca..c6f45bffa2 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -467,13 +467,15 @@ LLPointer<LLJointState>& LLKeyframeMotion::getJointState(U32 index)
}
//-----------------------------------------------------------------------------
-// getJoin()
+// getJoint()
//-----------------------------------------------------------------------------
LLJoint* LLKeyframeMotion::getJoint(U32 index)
{
llassert_always (index < mJointStates.size());
LLJoint* joint = mJointStates[index]->getJoint();
- llassert_always (joint);
+
+ //Commented out 06-28-11 by Aura.
+ //llassert_always (joint);
return joint;
}
@@ -821,7 +823,11 @@ void LLKeyframeMotion::initializeConstraint(JointConstraint* constraint)
S32 joint_num;
LLVector3 source_pos = mCharacter->getVolumePos(shared_data->mSourceConstraintVolume, shared_data->mSourceConstraintOffset);
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[0]);
-
+ if ( !cur_joint )
+ {
+ return;
+ }
+
F32 source_pos_offset = dist_vec(source_pos, cur_joint->getWorldPosition());
constraint->mTotalLength = constraint->mJointLengths[0] = dist_vec(cur_joint->getParent()->getWorldPosition(), source_pos);
@@ -872,6 +878,10 @@ void LLKeyframeMotion::activateConstraint(JointConstraint* constraint)
for (joint_num = 1; joint_num < shared_data->mChainLength; joint_num++)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+ if ( !cur_joint )
+ {
+ return;
+ }
constraint->mPositions[joint_num] = (cur_joint->getWorldPosition() - mPelvisp->getWorldPosition()) * ~mPelvisp->getWorldRotation();
}
@@ -932,6 +942,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
}
LLJoint* root_joint = getJoint(shared_data->mJointStateIndices[shared_data->mChainLength]);
+ if (! root_joint)
+ {
+ return;
+ }
+
LLVector3 root_pos = root_joint->getWorldPosition();
// LLQuaternion root_rot =
root_joint->getParent()->getWorldRotation();
@@ -943,6 +958,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+ if (!cur_joint)
+ {
+ return;
+ }
+
if (joint_mask[cur_joint->getJointNum()] >= (0xff >> (7 - getPriority())))
{
// skip constraint
@@ -1033,7 +1053,14 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
if (shared_data->mChainLength)
{
- LLQuaternion end_rot = getJoint(shared_data->mJointStateIndices[0])->getWorldRotation();
+ LLJoint* end_joint = getJoint(shared_data->mJointStateIndices[0]);
+
+ if (!end_joint)
+ {
+ return;
+ }
+
+ LLQuaternion end_rot = end_joint->getWorldRotation();
// slam start and end of chain to the proper positions (rest of chain stays put)
positions[0] = lerp(keyframe_source_pos, target_pos, weight);
@@ -1042,7 +1069,14 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
// grab keyframe-specified positions of joints
for (joint_num = 1; joint_num < shared_data->mChainLength; joint_num++)
{
- LLVector3 kinematic_position = getJoint(shared_data->mJointStateIndices[joint_num])->getWorldPosition() +
+ LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+
+ if (!cur_joint)
+ {
+ return;
+ }
+
+ LLVector3 kinematic_position = cur_joint->getWorldPosition() +
(source_to_target * constraint->mJointLengthFractions[joint_num]);
// convert intermediate joint positions to world coordinates
@@ -1088,7 +1122,17 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
for (joint_num = shared_data->mChainLength; joint_num > 0; joint_num--)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+
+ if (!cur_joint)
+ {
+ return;
+ }
LLJoint* child_joint = getJoint(shared_data->mJointStateIndices[joint_num - 1]);
+ if (!child_joint)
+ {
+ return;
+ }
+
LLQuaternion parent_rot = cur_joint->getParent()->getWorldRotation();
LLQuaternion cur_rot = cur_joint->getWorldRotation();
@@ -1122,7 +1166,6 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
cur_joint->setRotation(target_rot);
}
- LLJoint* end_joint = getJoint(shared_data->mJointStateIndices[0]);
LLQuaternion end_local_rot = end_rot * ~end_joint->getParent()->getWorldRotation();
if (weight == 1.f)
@@ -1150,7 +1193,13 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
//reset old joint rots
for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++)
{
- getJoint(shared_data->mJointStateIndices[joint_num])->setRotation(old_rots[joint_num]);
+ LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+ if (!cur_joint)
+ {
+ return;
+ }
+
+ cur_joint->setRotation(old_rots[joint_num]);
}
}
// simple positional constraint (pelvis only)
@@ -1775,7 +1824,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
constraintp->mJointStateIndices[i] = -1;
for (U32 j = 0; j < mJointMotionList->getNumJointMotions(); j++)
{
- if(getJoint(j) == joint)
+ LLJoint* constraint_joint = getJoint(j);
+
+ if ( !constraint_joint )
+ {
+ llwarns << "Invalid joint " << j << llendl;
+ return FALSE;
+ }
+
+ if(constraint_joint == joint)
{
constraintp->mJointStateIndices[i] = (S32)j;
break;
diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h
index 1fe9af40b3..b1422b2b90 100644
--- a/indra/llcharacter/llkeyframemotion.h
+++ b/indra/llcharacter/llkeyframemotion.h
@@ -70,7 +70,7 @@ public:
private:
// private helper functions to wrap some asserts
LLPointer<LLJointState>& getJointState(U32 index);
- LLJoint* getJoint(U32 index);
+ LLJoint* getJoint(U32 index );
public:
//-------------------------------------------------------------------------
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 80df91a5c1..9910281b64 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -115,6 +115,7 @@ set(llcommon_HEADER_FILES
indra_constants.h
linden_common.h
linked_lists.h
+ llaccountingquota.h
llallocator.h
llallocator_heap_profile.h
llagentconstants.h
diff --git a/indra/llcommon/llaccountingquota.h b/indra/llcommon/llaccountingquota.h
new file mode 100644
index 0000000000..140333de07
--- /dev/null
+++ b/indra/llcommon/llaccountingquota.h
@@ -0,0 +1,80 @@
+/**
+ * @file llaccountingquota.h
+ * @
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCOUNTINGQUOTA_H
+#define LL_ACCOUNTINGQUOTA_H
+
+struct ParcelQuota
+{
+ ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
+ F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
+ F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
+ F32 tempRenderCost, F32 tempPhysicsCost, F32 tempNetworkCost, F32 tempSimulationCost,
+ F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
+ F32 parcelCapacity )
+ : mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost )
+ , mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
+ , mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
+ , mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
+ , mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
+ , mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
+ , mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost )
+ , mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
+ , mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost )
+ , mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
+ , mParcelCapacity( parcelCapacity )
+ {
+ }
+
+ ParcelQuota(){}
+ F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
+ F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
+ F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
+ F32 mTempRenderCost, mTempPhysicsCost, mTempNetworkCost, mTempSimulationCost;
+ F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
+ F32 mParcelCapacity;
+};
+
+struct SelectionQuota
+{
+ SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
+ : mLocalId( localId)
+ , mRenderCost( renderCost )
+ , mPhysicsCost( physicsCost )
+ , mNetworkCost( networkCost )
+ , mSimulationCost( simulationCost )
+ {
+ }
+ SelectionQuota() {}
+
+ F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;
+ LLUUID mLocalId;
+};
+
+#endif
+
+
+
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
index 87c2d6775b..f5b242fdfc 100644
--- a/indra/llcommon/llchat.h
+++ b/indra/llcommon/llchat.h
@@ -49,7 +49,8 @@ typedef enum e_chat_type
CHAT_TYPE_STOP = 5,
CHAT_TYPE_DEBUG_MSG = 6,
CHAT_TYPE_REGION = 7,
- CHAT_TYPE_OWNER = 8
+ CHAT_TYPE_OWNER = 8,
+ CHAT_TYPE_DIRECT = 9 // From llRegionSayTo()
} EChatType;
typedef enum e_chat_audible_level
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
index c2cfb7286e..f6d0f5bce8 100644
--- a/indra/llcommon/llfoldertype.cpp
+++ b/indra/llcommon/llfoldertype.cpp
@@ -93,6 +93,8 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
+ addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE));
+ addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
};
diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h
index cb32cb075b..a0c847914f 100644
--- a/indra/llcommon/llfoldertype.h
+++ b/indra/llcommon/llfoldertype.h
@@ -83,8 +83,11 @@ public:
FT_MESH = 49,
FT_INBOX = 50,
+ FT_OUTBOX = 51,
- FT_COUNT = 51,
+ FT_BASIC_ROOT = 52,
+
+ FT_COUNT,
FT_NONE = -1
};
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 5be5ecc492..bf62600514 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -2036,7 +2036,9 @@ std::string zip_llsd(LLSD& data)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
- llerrs << "WTF?" << llendl;
+ free(output);
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
}
have = CHUNK-strm.avail_out;
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 8ba97d7730..b2c495d093 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -737,7 +737,7 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
}
}
else
- { // WTF? Shouldn't have a NULL pointer in the map.
+ { // Shouldn't have a NULL pointer in the map.
llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
}
}
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index ca2d3f9181..e8616a9be6 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -188,22 +188,30 @@ LLOSInfo::LLOSInfo() :
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows XP x64 Edition ";
else
- mOSStringSimple = "Microsoft Windows Server 2003 ";
+ mOSStringSimple = "Microsoft Windows Server 2003 ";
}
- else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 1)
+ else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 2)
{
if(osvi.dwMinorVersion == 0)
{
- mOSStringSimple = "Microsoft Windows Vista ";
+ if(osvi.wProductType == VER_NT_WORKSTATION)
+ mOSStringSimple = "Microsoft Windows Vista ";
+ else
+ mOSStringSimple = "Windows Server 2008 ";
}
else if(osvi.dwMinorVersion == 1)
{
- mOSStringSimple = "Microsoft Windows 7 ";
+ if(osvi.wProductType == VER_NT_WORKSTATION)
+ mOSStringSimple = "Microsoft Windows 7 ";
+ else
+ mOSStringSimple = "Windows Server 2008 R2 ";
}
-
- if(osvi.wProductType != VER_NT_WORKSTATION)
+ else if(osvi.dwMinorVersion == 2)
{
- mOSStringSimple += "Server ";
+ if(osvi.wProductType == VER_NT_WORKSTATION)
+ mOSStringSimple = "Microsoft Windows 8 ";
+ else
+ mOSStringSimple = "Windows Server 2012 ";
}
///get native system info if available..
@@ -308,8 +316,7 @@ LLOSInfo::LLOSInfo() :
std::string compatibility_mode;
if(got_shell32_version)
{
- if(osvi.dwMajorVersion != shell32_major
- || osvi.dwMinorVersion != shell32_minor)
+ if(osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor)
{
compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",
shell32_major,
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 7703132d90..0018b8e844 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -28,8 +28,8 @@
#define LL_LLVERSIONVIEWER_H
const S32 LL_VERSION_MAJOR = 2;
-const S32 LL_VERSION_MINOR = 7;
-const S32 LL_VERSION_PATCH = 0;
+const S32 LL_VERSION_MINOR = 8;
+const S32 LL_VERSION_PATCH = 1;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index 0a4cd51ea0..c95f922301 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -226,6 +226,11 @@ void LLParcel::init(const LLUUID &owner_id,
setPreviousOwnerID(LLUUID::null);
setPreviouslyGroupOwned(FALSE);
+
+ setSeeAVs(TRUE);
+ setAllowGroupAVSounds(TRUE);
+ setAllowAnyAVSounds(TRUE);
+ setHaveNewParcelLimitData(FALSE);
}
void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
@@ -702,7 +707,9 @@ void LLParcel::packMessage(LLSD& msg)
msg["user_location"] = ll_sd_from_vector3(mUserLocation);
msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt);
msg["landing_type"] = (U8)mLandingType;
-
+ msg["see_avs"] = (LLSD::Boolean) getSeeAVs();
+ msg["group_av_sounds"] = (LLSD::Boolean) getAllowGroupAVSounds();
+ msg["any_av_sounds"] = (LLSD::Boolean) getAllowAnyAVSounds();
}
@@ -721,6 +728,24 @@ void LLParcel::unpackMessage(LLMessageSystem* msg)
msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, buffer );
setMediaURL(buffer);
+ BOOL see_avs = TRUE; // All default to true for legacy server behavior
+ BOOL any_av_sounds = TRUE;
+ BOOL group_av_sounds = TRUE;
+ bool have_new_parcel_limit_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_SeeAVs) > 0); // New version of server should send all 3 of these values
+ have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds) > 0);
+ have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds) > 0);
+ if (have_new_parcel_limit_data)
+ {
+ msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_SeeAVs, see_avs);
+ msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds, any_av_sounds);
+ msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds, group_av_sounds);
+ }
+ setSeeAVs((bool) see_avs);
+ setAllowAnyAVSounds((bool) any_av_sounds);
+ setAllowGroupAVSounds((bool) group_av_sounds);
+
+ setHaveNewParcelLimitData(have_new_parcel_limit_data);
+
// non-optimized version
msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale );
@@ -1348,3 +1373,12 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s)
// is a distinct option from "None" and "Other"
return LLParcel::C_ANY;
}
+
+void LLParcel::updateQuota( const LLUUID& objectId, const ParcelQuota& quota )
+{
+ if ( mID == objectId )
+ {
+ mQuota = quota;
+ }
+}
+
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 71b65d99ce..ff35caab4c 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -34,7 +34,7 @@
#include "llpermissions.h"
#include "lltimer.h"
#include "v3math.h"
-
+#include "llaccountingquota.h"
// Grid out of which parcels taken is stepped every 4 meters.
const F32 PARCEL_GRID_STEP_METERS = 4.f;
@@ -75,7 +75,7 @@ const U8 PARCEL_AUCTION = 0x05;
// unused 0x06
// unused 0x07
// flag, unused 0x08
-// flag, unused 0x10
+const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
const U8 PARCEL_SOUND_LOCAL = 0x20;
const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
@@ -130,6 +130,12 @@ class LLSD;
class LLAccessEntry
{
public:
+ LLAccessEntry()
+ : mID(),
+ mTime(0),
+ mFlags(0)
+ {}
+
LLUUID mID; // Agent ID
S32 mTime; // Time (unix seconds) when entry expires
U32 mFlags; // Not used - currently should always be zero
@@ -265,6 +271,8 @@ public:
void setUserLocation(const LLVector3& pos) { mUserLocation = pos; }
void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; }
void setLandingType(const ELandingType type) { mLandingType = type; }
+ void setSeeAVs(BOOL see_avs) { mSeeAVs = see_avs; }
+ void setHaveNewParcelLimitData(bool have_new_parcel_data) { mHaveNewParcelLimitData = have_new_parcel_data; } // Remove this once hidden AV feature is fully available grid-wide
void setAuctionID(U32 auction_id) { mAuctionID = auction_id;}
@@ -291,6 +299,8 @@ public:
void setDenyAnonymous(BOOL b) { setParcelFlag(PF_DENY_ANONYMOUS, b); }
void setDenyAgeUnverified(BOOL b) { setParcelFlag(PF_DENY_AGEUNVERIFIED, b); }
void setRestrictPushObject(BOOL b) { setParcelFlag(PF_RESTRICT_PUSHOBJECT, b); }
+ void setAllowGroupAVSounds(BOOL b) { mAllowGroupAVSounds = b; }
+ void setAllowAnyAVSounds(BOOL b) { mAllowAnyAVSounds = b; }
void setDrawDistance(F32 dist) { mDrawDistance = dist; }
void setSalePrice(S32 price) { mSalePrice = price; }
@@ -367,6 +377,8 @@ public:
const LLVector3& getUserLocation() const { return mUserLocation; }
const LLVector3& getUserLookAt() const { return mUserLookAt; }
ELandingType getLandingType() const { return mLandingType; }
+ BOOL getSeeAVs() const { return mSeeAVs; }
+ BOOL getHaveNewParcelLimitData() const { return mHaveNewParcelLimitData; }
// User-specified snapshot
const LLUUID& getSnapshotID() const { return mSnapshotID; }
@@ -496,6 +508,9 @@ public:
BOOL getRegionDenyAgeUnverifiedOverride() const
{ return mRegionDenyAgeUnverifiedOverride; }
+ BOOL getAllowGroupAVSounds() const { return mAllowGroupAVSounds; }
+ BOOL getAllowAnyAVSounds() const { return mAllowAnyAVSounds; }
+
F32 getDrawDistance() const { return mDrawDistance; }
S32 getSalePrice() const { return mSalePrice; }
time_t getClaimDate() const { return mClaimDate; }
@@ -586,7 +601,11 @@ public:
LLUUID getPreviousOwnerID() const { return mPreviousOwnerID; }
BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
-
+
+
+ void updateQuota( const LLUUID& objectId, const ParcelQuota& quota );
+ const ParcelQuota& getQuota( void ) { return mQuota; }
+
protected:
LLUUID mID;
LLUUID mOwnerID;
@@ -602,6 +621,8 @@ protected:
LLVector3 mUserLocation;
LLVector3 mUserLookAt;
ELandingType mLandingType;
+ BOOL mSeeAVs; // Avatars on this parcel are visible from outside it
+ BOOL mHaveNewParcelLimitData; // Remove once hidden AV feature is grid-wide
LLTimer mSaleTimerExpires;
LLTimer mMediaResetTimer;
@@ -657,8 +678,11 @@ protected:
BOOL mRegionPushOverride;
BOOL mRegionDenyAnonymousOverride;
BOOL mRegionDenyAgeUnverifiedOverride;
-
-
+ BOOL mAllowGroupAVSounds;
+ BOOL mAllowAnyAVSounds;
+
+ ParcelQuota mQuota;
+
public:
// HACK, make private
S32 mLocalID;
diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h
index a61130132a..b1a917df73 100644
--- a/indra/llinventory/llparcelflags.h
+++ b/indra/llinventory/llparcelflags.h
@@ -126,5 +126,7 @@ const S32 PARCEL_DETAILS_DESC = 1;
const S32 PARCEL_DETAILS_OWNER = 2;
const S32 PARCEL_DETAILS_GROUP = 3;
const S32 PARCEL_DETAILS_AREA = 4;
+const S32 PARCEL_DETAILS_ID = 5;
+const S32 PARCEL_DETAILS_SEE_AVATARS = 6;
#endif
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index 39ae09650e..c156ed0cef 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -73,7 +73,7 @@ void set_default_colour_weights(kdu_params *siz);
const char* engineInfoLLImageJ2CKDU()
{
- std::string version = llformat("KDU %s", KDU_CORE_VERSION);
+ static std::string version = llformat("KDU %s", KDU_CORE_VERSION);
return version.c_str();
}
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 9dadad7dd3..cd100cdf9f 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -12,6 +12,8 @@ include_directories(
set(llmath_SOURCE_FILES
llbbox.cpp
llbboxlocal.cpp
+ llcalc.cpp
+ llcalcparser.cpp
llcamera.cpp
llcoordframe.cpp
llline.cpp
@@ -46,6 +48,8 @@ set(llmath_HEADER_FILES
coordframe.h
llbbox.h
llbboxlocal.h
+ llcalc.h
+ llcalcparser.h
llcamera.h
llcoord.h
llcoordframe.h
diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp
new file mode 100644
index 0000000000..597d0815fb
--- /dev/null
+++ b/indra/llmath/llcalc.cpp
@@ -0,0 +1,145 @@
+/*
+ * LLCalc.cpp
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#include "linden_common.h"
+
+#include "llcalc.h"
+
+#include "llcalcparser.h"
+#include "llmath.h"
+
+
+// Variable names for use in the build floater
+const char* LLCalc::X_POS = "PX";
+const char* LLCalc::Y_POS = "PY";
+const char* LLCalc::Z_POS = "PZ";
+const char* LLCalc::X_SCALE = "SX";
+const char* LLCalc::Y_SCALE = "SY";
+const char* LLCalc::Z_SCALE = "SZ";
+const char* LLCalc::X_ROT = "RX";
+const char* LLCalc::Y_ROT = "RY";
+const char* LLCalc::Z_ROT = "RZ";
+const char* LLCalc::HOLLOW = "HLW";
+const char* LLCalc::CUT_BEGIN = "CB";
+const char* LLCalc::CUT_END = "CE";
+const char* LLCalc::PATH_BEGIN = "PB";
+const char* LLCalc::PATH_END = "PE";
+const char* LLCalc::TWIST_BEGIN = "TB";
+const char* LLCalc::TWIST_END = "TE";
+const char* LLCalc::X_SHEAR = "SHX";
+const char* LLCalc::Y_SHEAR = "SHY";
+const char* LLCalc::X_TAPER = "TPX";
+const char* LLCalc::Y_TAPER = "TPY";
+const char* LLCalc::RADIUS_OFFSET = "ROF";
+const char* LLCalc::REVOLUTIONS = "REV";
+const char* LLCalc::SKEW = "SKW";
+const char* LLCalc::X_HOLE = "HLX";
+const char* LLCalc::Y_HOLE = "HLY";
+const char* LLCalc::TEX_U_SCALE = "TSU";
+const char* LLCalc::TEX_V_SCALE = "TSV";
+const char* LLCalc::TEX_U_OFFSET = "TOU";
+const char* LLCalc::TEX_V_OFFSET = "TOV";
+const char* LLCalc::TEX_ROTATION = "TROT";
+const char* LLCalc::TEX_TRANSPARENCY = "TRNS";
+const char* LLCalc::TEX_GLOW = "GLOW";
+
+
+LLCalc* LLCalc::sInstance = NULL;
+
+LLCalc::LLCalc() : mLastErrorPos(0)
+{
+ // Init table of constants
+ mConstants["PI"] = F_PI;
+ mConstants["TWO_PI"] = F_TWO_PI;
+ mConstants["PI_BY_TWO"] = F_PI_BY_TWO;
+ mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI;
+ mConstants["SQRT2"] = F_SQRT2;
+ mConstants["SQRT3"] = F_SQRT3;
+ mConstants["DEG_TO_RAD"] = DEG_TO_RAD;
+ mConstants["RAD_TO_DEG"] = RAD_TO_DEG;
+ mConstants["GRAVITY"] = GRAVITY;
+}
+
+LLCalc::~LLCalc()
+{
+}
+
+//static
+void LLCalc::cleanUp()
+{
+ delete sInstance;
+ sInstance = NULL;
+}
+
+//static
+LLCalc* LLCalc::getInstance()
+{
+ if (!sInstance) sInstance = new LLCalc();
+ return sInstance;
+}
+
+void LLCalc::setVar(const std::string& name, const F32& value)
+{
+ mVariables[name] = value;
+}
+
+void LLCalc::clearVar(const std::string& name)
+{
+ mVariables.erase(name);
+}
+
+void LLCalc::clearAllVariables()
+{
+ mVariables.clear();
+}
+
+/*
+void LLCalc::updateVariables(LLSD& vars)
+{
+ LLSD::map_iterator cIt = vars.beginMap();
+ for(; cIt != vars.endMap(); cIt++)
+ {
+ setVar(cIt->first, (F32)(LLSD::Real)cIt->second);
+ }
+}
+*/
+
+bool LLCalc::evalString(const std::string& expression, F32& result)
+{
+ std::string expr_upper = expression;
+ LLStringUtil::toUpper(expr_upper);
+
+ LLCalcParser calc(result, &mConstants, &mVariables);
+
+ mLastErrorPos = 0;
+ std::string::iterator start = expr_upper.begin();
+ parse_info<std::string::iterator> info;
+
+ try
+ {
+ info = parse(start, expr_upper.end(), calc, space_p);
+ lldebugs << "Math expression: " << expression << " = " << result << llendl;
+ }
+ catch(parser_error<std::string, std::string::iterator> &e)
+ {
+ mLastErrorPos = e.where - expr_upper.begin();
+
+ llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl;
+ return false;
+ }
+
+ if (!info.full)
+ {
+ mLastErrorPos = info.stop - expr_upper.begin();
+ llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl;
+ return false;
+ }
+
+ return true;
+}
diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h
new file mode 100644
index 0000000000..cc31950cb6
--- /dev/null
+++ b/indra/llmath/llcalc.h
@@ -0,0 +1,83 @@
+/*
+ * LLCalc.h
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#ifndef LL_CALC_H
+#define LL_CALC_H
+
+#include <map>
+#include <string>
+
+class LLCalc
+{
+public:
+ LLCalc();
+ ~LLCalc();
+
+ // Variable name constants
+ static const char* X_POS;
+ static const char* Y_POS;
+ static const char* Z_POS;
+ static const char* X_SCALE;
+ static const char* Y_SCALE;
+ static const char* Z_SCALE;
+ static const char* X_ROT;
+ static const char* Y_ROT;
+ static const char* Z_ROT;
+ static const char* HOLLOW;
+ static const char* CUT_BEGIN;
+ static const char* CUT_END;
+ static const char* PATH_BEGIN;
+ static const char* PATH_END;
+ static const char* TWIST_BEGIN;
+ static const char* TWIST_END;
+ static const char* X_SHEAR;
+ static const char* Y_SHEAR;
+ static const char* X_TAPER;
+ static const char* Y_TAPER;
+ static const char* RADIUS_OFFSET;
+ static const char* REVOLUTIONS;
+ static const char* SKEW;
+ static const char* X_HOLE;
+ static const char* Y_HOLE;
+ static const char* TEX_U_SCALE;
+ static const char* TEX_V_SCALE;
+ static const char* TEX_U_OFFSET;
+ static const char* TEX_V_OFFSET;
+ static const char* TEX_ROTATION;
+ static const char* TEX_TRANSPARENCY;
+ static const char* TEX_GLOW;
+
+ void setVar(const std::string& name, const F32& value);
+ void clearVar(const std::string& name);
+ void clearAllVariables();
+// void updateVariables(LLSD& vars);
+
+ bool evalString(const std::string& expression, F32& result);
+ std::string::size_type getLastErrorPos() { return mLastErrorPos; }
+
+ static LLCalc* getInstance();
+ static void cleanUp();
+
+ typedef std::map<std::string, F32> calc_map_t;
+
+private:
+ std::string::size_type mLastErrorPos;
+
+ calc_map_t mConstants;
+ calc_map_t mVariables;
+
+ // *TODO: Add support for storing user defined variables, and stored functions.
+ // Will need UI work, and a means to save them between sessions.
+// calc_map_t mUserVariables;
+
+ // "There shall be only one"
+ static LLCalc* sInstance;
+};
+
+#endif // LL_CALC_H
diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp
new file mode 100644
index 0000000000..fd55376fa9
--- /dev/null
+++ b/indra/llmath/llcalcparser.cpp
@@ -0,0 +1,46 @@
+/*
+ * LLCalcParser.cpp
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#include "linden_common.h"
+
+#include "llcalcparser.h"
+using namespace boost::spirit::classic;
+
+F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const
+{
+ LLCalc::calc_map_t::iterator iter;
+
+ std::string name(start, end);
+
+ if (mConstants)
+ {
+ iter = mConstants->find(name);
+ if (iter != mConstants->end())
+ {
+ return (*iter).second;
+ }
+ }
+ else
+ {
+ // This should never happen!
+ throw_(end, std::string("Missing constants table"));
+ }
+
+ if (mVariables)
+ {
+ iter = mVariables->find(name);
+ if (iter != mVariables->end())
+ {
+ return (*iter).second;
+ }
+ }
+
+ throw_(end, std::string("Unknown symbol " + name));
+ return 0.f;
+}
diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h
new file mode 100644
index 0000000000..600e173661
--- /dev/null
+++ b/indra/llmath/llcalcparser.h
@@ -0,0 +1,174 @@
+/*
+ * LLCalcParser.h
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#ifndef LL_CALCPARSER_H
+#define LL_CALCPARSER_H
+
+#include <boost/spirit/include/classic_attribute.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_error_handling.hpp>
+#include <boost/spirit/include/classic_position_iterator.hpp>
+#include <boost/spirit/include/phoenix1_binders.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+using namespace boost::spirit::classic;
+
+#include "llcalc.h"
+#include "llmath.h"
+
+struct LLCalcParser : grammar<LLCalcParser>
+{
+ LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) :
+ mResult(result), mConstants(constants), mVariables(vars) {};
+
+ struct value_closure : closure<value_closure, F32>
+ {
+ member1 value;
+ };
+
+ template <typename ScannerT>
+ struct definition
+ {
+ // Rule declarations
+ rule<ScannerT> statement, identifier;
+ rule<ScannerT, value_closure::context_t> expression, term,
+ power,
+ unary_expr,
+ factor,
+ unary_func,
+ binary_func,
+ group;
+
+ // start() should return the starting symbol
+ rule<ScannerT> const& start() const { return statement; }
+
+ definition(LLCalcParser const& self)
+ {
+ using namespace phoenix;
+
+ assertion<std::string> assert_domain("Domain error");
+// assertion<std::string> assert_symbol("Unknown symbol");
+ assertion<std::string> assert_syntax("Syntax error");
+
+ identifier =
+ lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')]
+ ;
+
+ group =
+ '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')'))
+ ;
+
+ unary_func =
+ ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) |
+ (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) |
+ (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) |
+ (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) |
+ (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) |
+ (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) |
+ (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) |
+ (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) |
+ (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) |
+ (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) |
+ (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) |
+ (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)])
+ ) >> assert_syntax(ch_p(')'))
+ ;
+
+ binary_func =
+ ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
+ expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) |
+ (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
+ expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) |
+ (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
+ expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)])
+ ) >> assert_syntax(ch_p(')'))
+ ;
+
+ // *TODO: Localisation of the decimal point?
+ // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate
+ // for the current locale. However to do that here could clash with using
+ // the comma as a separator when passing arguments to functions.
+ factor =
+ (ureal_p[factor.value = arg1] |
+ group[factor.value = arg1] |
+ unary_func[factor.value = arg1] |
+ binary_func[factor.value = arg1] |
+ // Lookup throws an Unknown Symbol error if it is unknown, while this works fine,
+ // would be "neater" to handle symbol lookup from here with an assertive parser.
+// constants_p[factor.value = arg1]|
+ identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)]
+ ) >>
+ // Detect and throw math errors.
+ assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value)))
+ ;
+
+ unary_expr =
+ !ch_p('+') >> factor[unary_expr.value = arg1] |
+ '-' >> factor[unary_expr.value = -arg1]
+ ;
+
+ power =
+ unary_expr[power.value = arg1] >>
+ *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)]))
+ ;
+
+ term =
+ power[term.value = arg1] >>
+ *(('*' >> assert_syntax(power[term.value *= arg1])) |
+ ('/' >> assert_syntax(power[term.value /= arg1])) |
+ ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)]))
+ )
+ ;
+
+ expression =
+ assert_syntax(term[expression.value = arg1]) >>
+ *(('+' >> assert_syntax(term[expression.value += arg1])) |
+ ('-' >> assert_syntax(term[expression.value -= arg1]))
+ )
+ ;
+
+ statement =
+ !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p)
+ ;
+ }
+ };
+
+private:
+ // Member functions for semantic actions
+ F32 lookup(const std::string::iterator&, const std::string::iterator&) const;
+ F32 _min(const F32& a, const F32& b) const { return llmin(a, b); }
+ F32 _max(const F32& a, const F32& b) const { return llmax(a, b); }
+
+ bool checkNaN(const F32& a) const { return !llisnan(a); }
+
+ //FIX* non ambigious function fix making SIN() work for calc -Cryogenic Blitz
+ F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); }
+ F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); }
+ F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); }
+ F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); }
+ F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); }
+ F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); }
+ F32 _sqrt(const F32& a) const { return sqrt(a); }
+ F32 _log(const F32& a) const { return log(a); }
+ F32 _exp(const F32& a) const { return exp(a); }
+ F32 _fabs(const F32& a) const { return fabs(a); }
+ F32 _floor(const F32& a) const { return llfloor(a); }
+ F32 _ceil(const F32& a) const { return llceil(a); }
+
+ F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); }
+
+
+
+ LLCalc::calc_map_t* mConstants;
+ LLCalc::calc_map_t* mVariables;
+// LLCalc::calc_map_t* mUserVariables;
+
+ F32& mResult;
+};
+
+#endif // LL_CALCPARSER_H
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index fdfc24f8b7..e5ca47da69 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -35,12 +35,14 @@
#define OCT_ERRS LL_WARNS("OctreeErrors")
-#define LL_OCTREE_PARANOIA_CHECK 0
+
+extern U32 gOctreeMaxCapacity;
+/*#define LL_OCTREE_PARANOIA_CHECK 0
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
#else
#define LL_OCTREE_MAX_CAPACITY 128
-#endif
+#endif*/
template <class T> class LLOctreeNode;
@@ -74,6 +76,7 @@ template <class T>
class LLOctreeNode : public LLTreeNode<T>
{
public:
+
typedef LLOctreeTraveler<T> oct_traveler;
typedef LLTreeTraveler<T> tree_traveler;
typedef typename std::set<LLPointer<T> > element_list;
@@ -294,8 +297,8 @@ public:
//is it here?
if (isInside(data->getPositionGroup()))
{
- if ((getElementCount() < LL_OCTREE_MAX_CAPACITY && contains(data->getBinRadius()) ||
- (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
+ if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
+ (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
#if LL_OCTREE_PARANOIA_CHECK
//if this is a redundant insertion, error out (should never happen)
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index c504215ee5..21cc9b22f2 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -100,7 +100,7 @@ void assert_aligned(void* ptr, uintptr_t alignment)
uintptr_t t = (uintptr_t) ptr;
if (t%alignment != 0)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Alignment check failed." << llendl;
}
#endif
}
@@ -361,7 +361,7 @@ public:
}
else
{
- llerrs << "WTF? Empty leaf" << llendl;
+ llerrs << "Empty leaf" << llendl;
}
for (S32 i = 0; i < branch->getChildCount(); ++i)
@@ -416,6 +416,70 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO
return face;
}
+//static
+S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
+{ // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points
+ LLMemType m1(LLMemType::MTYPE_VOLUME);
+ S32 np = 0;
+
+ // Generate an n-sided "circular" path.
+ // 0 is (1,0), and we go counter-clockwise along a circular path from there.
+ F32 t, t_step, t_first, t_fraction;
+
+ F32 begin = params.getBegin();
+ F32 end = params.getEnd();
+
+ t_step = 1.0f / sides;
+
+ t_first = floor(begin * sides) / (F32)sides;
+
+ // pt1 is the first point on the fractional face.
+ // Starting t and ang values for the first face
+ t = t_first;
+
+ // Increment to the next point.
+ // pt2 is the end point on the fractional face
+ t += t_step;
+
+ t_fraction = (begin - t_first)*sides;
+
+ // Only use if it's not almost exactly on an edge.
+ if (t_fraction < 0.9999f)
+ {
+ np++;
+ }
+
+ // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02
+ while (t < end)
+ {
+ // Iterate through all the integer steps of t.
+ np++;
+
+ t += t_step;
+ }
+
+ t_fraction = (end - (t - t_step))*sides;
+
+ // Find the fraction that we need to add to the end point.
+ t_fraction = (end - (t - t_step))*sides;
+ if (t_fraction > 0.0001f)
+ {
+ np++;
+ }
+
+ // If we're sliced, the profile is open.
+ if ((end - begin)*ang_scale < 0.99f)
+ {
+ if (params.getHollow() <= 0)
+ {
+ // put center point if not hollow.
+ np++;
+ }
+ }
+
+ return np;
+}
+
// What is the bevel parameter used for? - DJS 04/05/02
// Bevel parameter is currently unused but presumedly would support
// filleted and chamfered corners
@@ -672,6 +736,117 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3
return face;
}
+//static
+S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
+ BOOL is_sculpted, S32 sculpt_size)
+{ // this is basically LLProfile::generate stripped down to only operations that influence the number of points
+ LLMemType m1(LLMemType::MTYPE_VOLUME);
+
+ if (detail < MIN_LOD)
+ {
+ detail = MIN_LOD;
+ }
+
+ // Generate the face data
+ F32 hollow = params.getHollow();
+
+ S32 np = 0;
+
+ switch (params.getCurveType() & LL_PCODE_PROFILE_MASK)
+ {
+ case LL_PCODE_PROFILE_SQUARE:
+ {
+ np = getNumNGonPoints(params, 4,-0.375, 0, 1, split);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+ }
+ break;
+ case LL_PCODE_PROFILE_ISOTRI:
+ case LL_PCODE_PROFILE_RIGHTTRI:
+ case LL_PCODE_PROFILE_EQUALTRI:
+ {
+ np = getNumNGonPoints(params, 3,0, 0, 1, split);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+ }
+ break;
+ case LL_PCODE_PROFILE_CIRCLE:
+ {
+ // If this has a square hollow, we should adjust the
+ // number of faces a bit so that the geometry lines up.
+ U8 hole_type=0;
+ F32 circle_detail = MIN_DETAIL_FACES * detail;
+ if (hollow)
+ {
+ hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
+ if (hole_type == LL_PCODE_HOLE_SQUARE)
+ {
+ // Snap to the next multiple of four sides,
+ // so that corners line up.
+ circle_detail = llceil(circle_detail / 4.0f) * 4.0f;
+ }
+ }
+
+ S32 sides = (S32)circle_detail;
+
+ if (is_sculpted)
+ sides = sculpt_size;
+
+ np = getNumNGonPoints(params, sides);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+ }
+ break;
+ case LL_PCODE_PROFILE_CIRCLE_HALF:
+ {
+ // If this has a square hollow, we should adjust the
+ // number of faces a bit so that the geometry lines up.
+ U8 hole_type=0;
+ // Number of faces is cut in half because it's only a half-circle.
+ F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f;
+ if (hollow)
+ {
+ hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
+ if (hole_type == LL_PCODE_HOLE_SQUARE)
+ {
+ // Snap to the next multiple of four sides (div 2),
+ // so that corners line up.
+ circle_detail = llceil(circle_detail / 2.0f) * 2.0f;
+ }
+ }
+ np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f);
+
+ if (hollow)
+ {
+ np *= 2;
+ }
+
+ // Special case for openness of sphere
+ if ((params.getEnd() - params.getBegin()) < 1.f)
+ {
+ }
+ else if (!hollow)
+ {
+ np++;
+ }
+ }
+ break;
+ default:
+ break;
+ };
+
+
+ return np;
+}
BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
@@ -1133,6 +1308,32 @@ LLPath::~LLPath()
{
}
+S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
+{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added
+ S32 ret = 0;
+
+ F32 step= 1.0f / sides;
+ F32 t = params.getBegin();
+ ret = 1;
+
+ t+=step;
+
+ // Snap to a quantized parameter, so that cut does not
+ // affect most sample points.
+ t = ((S32)(t * sides)) / (F32)sides;
+
+ // Run through the non-cut dependent points.
+ while (t < params.getEnd())
+ {
+ ret++;
+ t+=step;
+ }
+
+ ret++;
+
+ return ret;
+}
+
void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{
// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
@@ -1310,6 +1511,56 @@ const LLVector2 LLPathParams::getEndScale() const
return end_scale;
}
+S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail)
+{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points
+ LLMemType m1(LLMemType::MTYPE_VOLUME);
+
+ if (detail < MIN_LOD)
+ {
+ detail = MIN_LOD;
+ }
+
+ S32 np = 2; // hardcode for line
+
+ // Is this 0xf0 mask really necessary? DK 03/02/05
+
+ switch (params.getCurveType() & 0xf0)
+ {
+ default:
+ case LL_PCODE_PATH_LINE:
+ {
+ // Take the begin/end twist into account for detail.
+ np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2;
+ }
+ break;
+
+ case LL_PCODE_PATH_CIRCLE:
+ {
+ // Increase the detail as the revolutions and twist increase.
+ F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist());
+
+ S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
+
+ np = sides;
+ }
+ break;
+
+ case LL_PCODE_PATH_CIRCLE2:
+ {
+ //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
+ np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail));
+ }
+ break;
+
+ case LL_PCODE_PATH_TEST:
+
+ np = 5;
+ break;
+ };
+
+ return np;
+}
+
BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
BOOL is_sculpted, S32 sculpt_size)
{
@@ -2159,27 +2410,41 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
U32 face_count = mdl.size();
if (face_count == 0)
- {
- llerrs << "WTF?" << llendl;
+ { //no faces unpacked, treat as failed decode
+ llwarns << "found no faces!" << llendl;
+ return false;
}
mVolumeFaces.resize(face_count);
for (U32 i = 0; i < face_count; ++i)
{
+ LLVolumeFace& face = mVolumeFaces[i];
+
+ if (mdl[i].has("NoGeometry"))
+ { //face has no geometry, continue
+ face.resizeIndices(3);
+ face.resizeVertices(1);
+ memset(face.mPositions, 0, sizeof(LLVector4a));
+ memset(face.mNormals, 0, sizeof(LLVector4a));
+ memset(face.mTexCoords, 0, sizeof(LLVector2));
+ memset(face.mIndices, 0, sizeof(U16)*3);
+ continue;
+ }
+
LLSD::Binary pos = mdl[i]["Position"];
LLSD::Binary norm = mdl[i]["Normal"];
LLSD::Binary tc = mdl[i]["TexCoord0"];
LLSD::Binary idx = mdl[i]["TriangleList"];
- LLVolumeFace& face = mVolumeFaces[i];
+
//copy out indices
face.resizeIndices(idx.size()/2);
if (idx.empty() || face.mNumIndices < 3)
{ //why is there an empty index list?
- llerrs <<"WTF?" << llendl;
+ llwarns <<"Empty face present!" << llendl;
continue;
}
@@ -2235,37 +2500,43 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
{
U16* n = (U16*) &(norm[0]);
- for (U32 j = 0; j < num_verts; ++j)
+ if(n)
{
- norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]);
- norm_out->div(65535.f);
- norm_out->mul(2.f);
- norm_out->sub(1.f);
- norm_out++;
- n += 3;
+ for (U32 j = 0; j < num_verts; ++j)
+ {
+ norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]);
+ norm_out->div(65535.f);
+ norm_out->mul(2.f);
+ norm_out->sub(1.f);
+ norm_out++;
+ n += 3;
+ }
}
}
{
U16* t = (U16*) &(tc[0]);
- for (U32 j = 0; j < num_verts; j+=2)
+ if(t)
{
- if (j < num_verts-1)
+ for (U32 j = 0; j < num_verts; j+=2)
{
- tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]);
- }
- else
- {
- tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f);
- }
+ if (j < num_verts-1)
+ {
+ tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]);
+ }
+ else
+ {
+ tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f);
+ }
- t += 4;
+ t += 4;
- tc_out->div(65535.f);
- tc_out->mul(tc_range);
- tc_out->add(min_tc4);
+ tc_out->div(65535.f);
+ tc_out->mul(tc_range);
+ tc_out->add(min_tc4);
- tc_out++;
+ tc_out++;
+ }
}
}
@@ -2377,14 +2648,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LLVector4a& min = face.mExtents[0];
LLVector4a& max = face.mExtents[1];
- min.clear();
- max.clear();
- min = max = face.mPositions[0];
-
- for (S32 i = 1; i < face.mNumVertices; ++i)
+ if (face.mNumVertices < 3)
+ { //empty face, use a dummy 1cm (at 1m scale) bounding box
+ min.splat(-0.005f);
+ max.splat(0.005f);
+ }
+ else
{
- min.setMin(min, face.mPositions[i]);
- max.setMax(max, face.mPositions[i]);
+ min = max = face.mPositions[0];
+
+ for (S32 i = 1; i < face.mNumVertices; ++i)
+ {
+ min.setMin(min, face.mPositions[i]);
+ max.setMax(max, face.mPositions[i]);
+ }
}
}
}
@@ -2980,7 +3257,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
// don't test lowest LOD to support legacy content DEV-33670
if (mDetail > SCULPT_MIN_AREA_DETAIL)
{
- if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+ F32 area = sculptGetSurfaceArea();
+
+ const F32 SCULPT_MAX_AREA = 384.f;
+
+ if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
{
data_is_empty = TRUE;
}
@@ -4064,6 +4345,23 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
return index;
}
+void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)
+{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the
+ //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost
+ F32 detail[] = {1.f, 1.5f, 2.5f, 4.f};
+ for (S32 i = 0; i < 4; i++)
+ {
+ S32 count = 0;
+ S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]);
+ S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]);
+
+ count = (profile_points-1)*2*(path_points-1);
+ count += profile_points*2;
+
+ counts[i] = count;
+ }
+}
+
S32 LLVolume::getNumTriangleIndices() const
{
BOOL profile_open = getProfile().isOpen();
@@ -5220,6 +5518,8 @@ LLVolumeFace::LLVolumeFace() :
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
+ mExtents[0].splat(-0.5f);
+ mExtents[1].splat(0.5f);
mCenter = mExtents+2;
}
@@ -5741,6 +6041,11 @@ void LLVolumeFace::cacheOptimize()
LLVCacheLRU cache;
+ if (mNumVertices < 3)
+ { //nothing to do
+ return;
+ }
+
//mapping of vertices to triangles and indices
std::vector<LLVCacheVertexData> vertex_data;
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 01bfbd858b..f67f8f644d 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -690,6 +690,9 @@ public:
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
BOOL isOpen() const { return mOpen; }
void setDirty() { mDirty = TRUE; }
+
+ static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
+ BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL isConcave() const { return mConcave; }
@@ -714,6 +717,7 @@ public:
protected:
void genNormals(const LLProfileParams& params);
+ static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
@@ -756,6 +760,9 @@ public:
virtual ~LLPath();
+ static S32 getNumPoints(const LLPathParams& params, F32 detail);
+ static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
+
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
@@ -981,6 +988,7 @@ public:
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
+ static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
S32 getNumTriangles() const;
diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h
index dd9c4eaa38..b0a638c16e 100644
--- a/indra/llmessage/lldatapacker.h
+++ b/indra/llmessage/lldatapacker.h
@@ -168,10 +168,15 @@ public:
S32 getCurrentSize() const { return (S32)(mCurBufferp - mBufferp); }
S32 getBufferSize() const { return mBufferSize; }
+ const U8* getBuffer() const { return mBufferp; }
void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); }
void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = FALSE; }
void assignBuffer(U8 *bufferp, S32 size)
{
+ if(mBufferp && mBufferp != bufferp)
+ {
+ freeBuffer() ;
+ }
mBufferp = bufferp;
mCurBufferp = bufferp;
mBufferSize = size;
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index ca84fa8bb8..8c752fbe30 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -191,7 +191,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
port = PORT_EPHEMERAL;
}
rv->mPort = port;
- rv->setOptions();
+ rv->setNonBlocking();
return rv;
}
@@ -206,7 +206,7 @@ LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
}
rv = ptr_t(new LLSocket(socket, pool));
rv->mPort = PORT_EPHEMERAL;
- rv->setOptions();
+ rv->setNonBlocking();
return rv;
}
@@ -227,10 +227,10 @@ bool LLSocket::blockingConnect(const LLHost& host)
{
return false;
}
- apr_socket_timeout_set(mSocket, 1000);
+ setBlocking(1000);
ll_debug_socket("Blocking connect", mSocket);
if(ll_apr_warn_status(apr_socket_connect(mSocket, sa))) return false;
- setOptions();
+ setNonBlocking();
return true;
}
@@ -258,11 +258,27 @@ LLSocket::~LLSocket()
}
}
-void LLSocket::setOptions()
+// See http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4
+// for an explanation of how to get non-blocking sockets and timeouts with
+// consistent behavior across platforms.
+
+void LLSocket::setBlocking(S32 timeout)
+{
+ LLMemType m1(LLMemType::MTYPE_IO_TCP);
+ // set up the socket options
+ ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
+
+}
+
+void LLSocket::setNonBlocking()
{
LLMemType m1(LLMemType::MTYPE_IO_TCP);
// set up the socket options
ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 1));
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index 6806e5084a..e0f6c1e34d 100644
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -153,9 +153,16 @@ protected:
LLSocket(apr_socket_t* socket, apr_pool_t* pool);
/**
- * @brief Set default socket options.
+ * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.
+ * @param timeout Number of microseconds to wait on this socket. Any
+ * negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE.
*/
- void setOptions();
+ void setBlocking(S32 timeout);
+
+ /**
+ * @brief Set default socket options, with SO_NONBLOCK = 1 and timeout = 0.
+ */
+ void setNonBlocking();
public:
/**
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 5d03615e53..e71fb96540 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS
char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect");
char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID");
char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd");
+char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures");
char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection");
char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction");
char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode");
@@ -1375,3 +1376,6 @@ char const* const _PREHASH_VCoord = LLMessageStringTable::getInstance()->getStri
char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex");
char const* const _PREHASH_StatusData = LLMessageStringTable::getInstance()->getString("StatusData");
char const* const _PREHASH_ProductSKU = LLMessageStringTable::getInstance()->getString("ProductSKU");
+char const* const _PREHASH_SeeAVs = LLMessageStringTable::getInstance()->getString("SeeAVs");
+char const* const _PREHASH_AnyAVSounds = LLMessageStringTable::getInstance()->getString("AnyAVSounds");
+char const* const _PREHASH_GroupAVSounds = LLMessageStringTable::getInstance()->getString("GroupAVSounds");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 8dc86601e6..dd2c2dbd64 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData;
extern char const* const _PREHASH_ObjectDeselect;
extern char const* const _PREHASH_NewAssetID;
extern char const* const _PREHASH_ObjectAdd;
+extern char const* const _PREHASH_SimulatorFeatures;
extern char const* const _PREHASH_RayEndIsIntersection;
extern char const* const _PREHASH_CompleteAuction;
extern char const* const _PREHASH_CircuitCode;
@@ -1375,4 +1376,7 @@ extern char const* const _PREHASH_VCoord;
extern char const* const _PREHASH_FaceIndex;
extern char const* const _PREHASH_StatusData;
extern char const* const _PREHASH_ProductSKU;
+extern char const* const _PREHASH_SeeAVs;
+extern char const* const _PREHASH_AnyAVSounds;
+extern char const* const _PREHASH_GroupAVSounds;
#endif
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h
index 0fef596df2..0d149b5258 100644
--- a/indra/llmessage/tests/commtest.h
+++ b/indra/llmessage/tests/commtest.h
@@ -34,6 +34,7 @@
#include "llsd.h"
#include "llhost.h"
#include "stringize.h"
+#include <map>
#include <string>
#include <stdexcept>
#include <boost/lexical_cast.hpp>
@@ -43,6 +44,58 @@ struct CommtestError: public std::runtime_error
CommtestError(const std::string& what): std::runtime_error(what) {}
};
+static bool query_verbose()
+{
+ const char* cbose = getenv("INTEGRATION_TEST_VERBOSE");
+ if (! cbose)
+ {
+ cbose = "1";
+ }
+ std::string strbose(cbose);
+ return (! (strbose == "0" || strbose == "off" ||
+ strbose == "false" || strbose == "quiet"));
+}
+
+bool verbose()
+{
+ // This should only be initialized once.
+ static bool vflag = query_verbose();
+ return vflag;
+}
+
+static int query_port(const std::string& var)
+{
+ const char* cport = getenv(var.c_str());
+ if (! cport)
+ {
+ throw CommtestError(STRINGIZE("missing environment variable" << var));
+ }
+ // This will throw, too, if the value of PORT isn't numeric.
+ int port(boost::lexical_cast<int>(cport));
+ if (verbose())
+ {
+ std::cout << "getport('" << var << "') = " << port << std::endl;
+ }
+ return port;
+}
+
+static int getport(const std::string& var)
+{
+ typedef std::map<std::string, int> portsmap;
+ static portsmap ports;
+ // We can do this with a single map lookup with map::insert(). Either it
+ // returns an existing entry and 'false' (not newly inserted), or it
+ // inserts the specified value and 'true'.
+ std::pair<portsmap::iterator, bool> inserted(ports.insert(portsmap::value_type(var, 0)));
+ if (inserted.second)
+ {
+ // We haven't yet seen this var. Remember its value.
+ inserted.first->second = query_port(var);
+ }
+ // Return the (existing or new) iterator's value.
+ return inserted.first->second;
+}
+
/**
* This struct is shared by a couple of standalone comm tests (ADD_COMM_BUILD_TEST).
*/
@@ -71,13 +124,10 @@ struct commtest_data
static int getport(const std::string& var)
{
- const char* port = getenv(var.c_str());
- if (! port)
- {
- throw CommtestError("missing $PORT environment variable");
- }
- // This will throw, too, if the value of PORT isn't numeric.
- return boost::lexical_cast<int>(port);
+ // We have a couple consumers of commtest_data::getport(). But we've
+ // since moved it out to the global namespace. So this is just a
+ // facade.
+ return ::getport(var);
}
bool outcome(const LLSD& _result, bool _success)
diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py
index cea5032111..22edd9dad8 100644
--- a/indra/llmessage/tests/test_llsdmessage_peer.py
+++ b/indra/llmessage/tests/test_llsdmessage_peer.py
@@ -38,7 +38,7 @@ mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tes
sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python"))
from indra.util.fastest_elementtree import parse as xml_parse
from indra.base import llsd
-from testrunner import freeport, run, debug
+from testrunner import freeport, run, debug, VERBOSE
class TestHTTPRequestHandler(BaseHTTPRequestHandler):
"""This subclass of BaseHTTPRequestHandler is to receive and echo
@@ -72,10 +72,10 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
## # assuming that the underlying XML parser reads its input file
## # incrementally. Unfortunately I haven't been able to make it work.
## tree = xml_parse(self.rfile)
-## debug("Finished raw parse\n")
-## debug("parsed XML tree %s\n" % tree)
-## debug("parsed root node %s\n" % tree.getroot())
-## debug("root node tag %s\n" % tree.getroot().tag)
+## debug("Finished raw parse")
+## debug("parsed XML tree %s", tree)
+## debug("parsed root node %s", tree.getroot())
+## debug("root node tag %s", tree.getroot().tag)
## return llsd.to_python(tree.getroot())
def do_GET(self):
@@ -88,8 +88,10 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
self.answer(self.read_xml())
def answer(self, data):
+ debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
if "fail" not in self.path:
response = llsd.format_xml(data.get("reply", llsd.LLSD("success")))
+ debug("success: %s", response)
self.send_response(200)
self.send_header("Content-type", "application/llsd+xml")
self.send_header("Content-Length", str(len(response)))
@@ -106,28 +108,39 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
("fail requested",
"Your request specified failure status %s "
"without providing a reason" % status))[1])
+ debug("fail requested: %s: %r", status, reason)
self.send_error(status, reason)
- def log_request(self, code, size=None):
- # For present purposes, we don't want the request splattered onto
- # stderr, as it would upset devs watching the test run
- pass
+ if not VERBOSE:
+ # When VERBOSE is set, skip both these overrides because they exist to
+ # suppress output.
- def log_error(self, format, *args):
- # Suppress error output as well
- pass
+ def log_request(self, code, size=None):
+ # For present purposes, we don't want the request splattered onto
+ # stderr, as it would upset devs watching the test run
+ pass
+
+ def log_error(self, format, *args):
+ # Suppress error output as well
+ pass
+
+class Server(HTTPServer):
+ # This pernicious flag is on by default in HTTPServer. But proper
+ # operation of freeport() absolutely depends on it being off.
+ allow_reuse_address = False
if __name__ == "__main__":
- # Instantiate an HTTPServer(TestHTTPRequestHandler) on the first free port
+ # Instantiate a Server(TestHTTPRequestHandler) on the first free port
# in the specified port range. Doing this inline is better than in a
# daemon thread: if it blows up here, we'll get a traceback. If it blew up
# in some other thread, the traceback would get eaten and we'd run the
# subject test program anyway.
httpd, port = freeport(xrange(8000, 8020),
- lambda port: HTTPServer(('127.0.0.1', port), TestHTTPRequestHandler))
+ lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler))
# Pass the selected port number to the subject test program via the
# environment. We don't want to impose requirements on the test program's
# command-line parsing -- and anyway, for C++ integration tests, that's
# performed in TUT code rather than our own.
os.environ["PORT"] = str(port)
+ debug("$PORT = %s", port)
sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), *sys.argv[1:]))
diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py
index 8ff13e0426..f2c841532a 100644
--- a/indra/llmessage/tests/testrunner.py
+++ b/indra/llmessage/tests/testrunner.py
@@ -27,16 +27,25 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
+from __future__ import with_statement
+
import os
import sys
+import re
import errno
import socket
-def debug(*args):
- sys.stdout.writelines(args)
- sys.stdout.flush()
-# comment out the line below to enable debug output
-debug = lambda *args: None
+VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "1") # default to verbose
+# Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if
+# that construct actually turns on verbosity...
+VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE)
+
+if VERBOSE:
+ def debug(fmt, *args):
+ print fmt % args
+ sys.stdout.flush()
+else:
+ debug = lambda *args: None
def freeport(portlist, expr):
"""
@@ -72,50 +81,64 @@ def freeport(portlist, expr):
Example:
+ class Server(HTTPServer):
+ # If you use BaseHTTPServer.HTTPServer, turning off this flag is
+ # essential for proper operation of freeport()!
+ allow_reuse_address = False
+ # ...
server, port = freeport(xrange(8000, 8010),
- lambda port: HTTPServer(("localhost", port),
- MyRequestHandler))
+ lambda port: Server(("localhost", port),
+ MyRequestHandler))
# pass 'port' to client code
# call server.serve_forever()
"""
- # If portlist is completely empty, let StopIteration propagate: that's an
- # error because we can't return meaningful values. We have no 'port',
- # therefore no 'expr(port)'.
- portiter = iter(portlist)
- port = portiter.next()
+ try:
+ # If portlist is completely empty, let StopIteration propagate: that's an
+ # error because we can't return meaningful values. We have no 'port',
+ # therefore no 'expr(port)'.
+ portiter = iter(portlist)
+ port = portiter.next()
- while True:
- try:
- # If this value of port works, return as promised.
- return expr(port), port
-
- except socket.error, err:
- # Anything other than 'Address already in use', propagate
- if err.args[0] != errno.EADDRINUSE:
- raise
-
- # Here we want the next port from portiter. But on StopIteration,
- # we want to raise the original exception rather than
- # StopIteration. So save the original exc_info().
- type, value, tb = sys.exc_info()
+ while True:
try:
+ # If this value of port works, return as promised.
+ value = expr(port)
+
+ except socket.error, err:
+ # Anything other than 'Address already in use', propagate
+ if err.args[0] != errno.EADDRINUSE:
+ raise
+
+ # Here we want the next port from portiter. But on StopIteration,
+ # we want to raise the original exception rather than
+ # StopIteration. So save the original exc_info().
+ type, value, tb = sys.exc_info()
try:
- port = portiter.next()
- except StopIteration:
- raise type, value, tb
- finally:
- # Clean up local traceback, see docs for sys.exc_info()
- del tb
-
- # Recap of the control flow above:
- # If expr(port) doesn't raise, return as promised.
- # If expr(port) raises anything but EADDRINUSE, propagate that
- # exception.
- # If portiter.next() raises StopIteration -- that is, if the port
- # value we just passed to expr(port) was the last available -- reraise
- # the EADDRINUSE exception.
- # If we've actually arrived at this point, portiter.next() delivered a
- # new port value. Loop back to pass that to expr(port).
+ try:
+ port = portiter.next()
+ except StopIteration:
+ raise type, value, tb
+ finally:
+ # Clean up local traceback, see docs for sys.exc_info()
+ del tb
+
+ else:
+ debug("freeport() returning %s on port %s", value, port)
+ return value, port
+
+ # Recap of the control flow above:
+ # If expr(port) doesn't raise, return as promised.
+ # If expr(port) raises anything but EADDRINUSE, propagate that
+ # exception.
+ # If portiter.next() raises StopIteration -- that is, if the port
+ # value we just passed to expr(port) was the last available -- reraise
+ # the EADDRINUSE exception.
+ # If we've actually arrived at this point, portiter.next() delivered a
+ # new port value. Loop back to pass that to expr(port).
+
+ except Exception, err:
+ debug("*** freeport() raising %s: %s", err.__class__.__name__, err)
+ raise
def run(*args, **kwds):
"""All positional arguments collectively form a command line, executed as
@@ -144,8 +167,96 @@ def run(*args, **kwds):
# - [no p] don't use the PATH because we specifically want to invoke the
# executable passed as our first arg,
# - [no e] child should inherit this process's environment.
- debug("Running %s...\n" % (" ".join(args)))
- sys.stdout.flush()
+ debug("Running %s...", " ".join(args))
rc = os.spawnv(os.P_WAIT, args[0], args)
- debug("%s returned %s\n" % (args[0], rc))
+ debug("%s returned %s", args[0], rc)
return rc
+
+# ****************************************************************************
+# test code -- manual at this point, see SWAT-564
+# ****************************************************************************
+def test_freeport():
+ # ------------------------------- Helpers --------------------------------
+ from contextlib import contextmanager
+ # helper Context Manager for expecting an exception
+ # with exc(SomeError):
+ # raise SomeError()
+ # raises AssertionError otherwise.
+ @contextmanager
+ def exc(exception_class, *args):
+ try:
+ yield
+ except exception_class, err:
+ for i, expected_arg in enumerate(args):
+ assert expected_arg == err.args[i], \
+ "Raised %s, but args[%s] is %r instead of %r" % \
+ (err.__class__.__name__, i, err.args[i], expected_arg)
+ print "Caught expected exception %s(%s)" % \
+ (err.__class__.__name__, ', '.join(repr(arg) for arg in err.args))
+ else:
+ assert False, "Failed to raise " + exception_class.__class__.__name__
+
+ # helper to raise specified exception
+ def raiser(exception):
+ raise exception
+
+ # the usual
+ def assert_equals(a, b):
+ assert a == b, "%r != %r" % (a, b)
+
+ # ------------------------ Sanity check the above ------------------------
+ class SomeError(Exception): pass
+ # Without extra args, accept any err.args value
+ with exc(SomeError):
+ raiser(SomeError("abc"))
+ # With extra args, accept only the specified value
+ with exc(SomeError, "abc"):
+ raiser(SomeError("abc"))
+ with exc(AssertionError):
+ with exc(SomeError, "abc"):
+ raiser(SomeError("def"))
+ with exc(AssertionError):
+ with exc(socket.error, errno.EADDRINUSE):
+ raiser(socket.error(errno.ECONNREFUSED, 'Connection refused'))
+
+ # ----------- freeport() without engaging socket functionality -----------
+ # If portlist is empty, freeport() raises StopIteration.
+ with exc(StopIteration):
+ freeport([], None)
+
+ assert_equals(freeport([17], str), ("17", 17))
+
+ # This is the magic exception that should prompt us to retry
+ inuse = socket.error(errno.EADDRINUSE, 'Address already in use')
+ # Get the iterator to our ports list so we can check later if we've used all
+ ports = iter(xrange(5))
+ with exc(socket.error, errno.EADDRINUSE):
+ freeport(ports, lambda port: raiser(inuse))
+ # did we entirely exhaust 'ports'?
+ with exc(StopIteration):
+ ports.next()
+
+ ports = iter(xrange(2))
+ # Any exception but EADDRINUSE should quit immediately
+ with exc(SomeError):
+ freeport(ports, lambda port: raiser(SomeError()))
+ assert_equals(ports.next(), 1)
+
+ # ----------- freeport() with platform-dependent socket stuff ------------
+ # This is what we should've had unit tests to begin with (see CHOP-661).
+ def newbind(port):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.bind(('127.0.0.1', port))
+ return sock
+
+ bound0, port0 = freeport(xrange(7777, 7780), newbind)
+ assert_equals(port0, 7777)
+ bound1, port1 = freeport(xrange(7777, 7780), newbind)
+ assert_equals(port1, 7778)
+ bound2, port2 = freeport(xrange(7777, 7780), newbind)
+ assert_equals(port2, 7779)
+ with exc(socket.error, errno.EADDRINUSE):
+ bound3, port3 = freeport(xrange(7777, 7780), newbind)
+
+if __name__ == "__main__":
+ test_freeport()
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 2103216536..d3d0403bbb 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1,1335 +1,1424 @@
-/**
- * @file llpluginclassmedia.cpp
- * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llpluginclassmedia.h"
-#include "llpluginmessageclasses.h"
-
-#include "llqtwebkit.h"
-
-static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
-
-static int nextPowerOf2( int value )
-{
- int next_power_of_2 = 1;
- while ( next_power_of_2 < value )
- {
- next_power_of_2 <<= 1;
- }
-
- return next_power_of_2;
-}
-
-LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
-{
- mOwner = owner;
- mPlugin = NULL;
- reset();
-
- //debug use
- mDeleteOK = true ;
-}
-
-
-LLPluginClassMedia::~LLPluginClassMedia()
-{
- llassert_always(mDeleteOK) ;
- reset();
-}
-
-bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{
- LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
- LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
- LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
-
- mPlugin = new LLPluginProcessParent(this);
- mPlugin->setSleepTime(mSleepTime);
-
- // Queue up the media init message -- it will be sent after all the currently queued messages.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
- message.setValue("target", mTarget);
- sendMessage(message);
-
- mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
-
- return true;
-}
-
-
-void LLPluginClassMedia::reset()
-{
- if(mPlugin != NULL)
- {
- delete mPlugin;
- mPlugin = NULL;
- }
-
- mTextureParamsReceived = false;
- mRequestedTextureDepth = 0;
- mRequestedTextureInternalFormat = 0;
- mRequestedTextureFormat = 0;
- mRequestedTextureType = 0;
- mRequestedTextureSwapBytes = false;
- mRequestedTextureCoordsOpenGL = false;
- mTextureSharedMemorySize = 0;
- mTextureSharedMemoryName.clear();
- mDefaultMediaWidth = 0;
- mDefaultMediaHeight = 0;
- mNaturalMediaWidth = 0;
- mNaturalMediaHeight = 0;
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- mRequestedMediaWidth = 0;
- mRequestedMediaHeight = 0;
- mRequestedTextureWidth = 0;
- mRequestedTextureHeight = 0;
- mFullMediaWidth = 0;
- mFullMediaHeight = 0;
- mTextureWidth = 0;
- mTextureHeight = 0;
- mMediaWidth = 0;
- mMediaHeight = 0;
- mDirtyRect = LLRect::null;
- mAutoScaleMedia = false;
- mRequestedVolume = 1.0f;
- mPriority = PRIORITY_NORMAL;
- mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
- mAllowDownsample = false;
- mPadding = 0;
- mLastMouseX = 0;
- mLastMouseY = 0;
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- mSleepTime = 1.0f / 100.0f;
- mCanCut = false;
- mCanCopy = false;
- mCanPaste = false;
- mMediaName.clear();
- mMediaDescription.clear();
- mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-
- // media_browser class
- mNavigateURI.clear();
- mNavigateResultCode = -1;
- mNavigateResultString.clear();
- mHistoryBackAvailable = false;
- mHistoryForwardAvailable = false;
- mStatusText.clear();
- mProgressPercent = 0;
- mClickURL.clear();
- mClickNavType.clear();
- mClickTarget.clear();
- mClickUUID.clear();
- mStatusCode = 0;
-
- // media_time class
- mCurrentTime = 0.0f;
- mDuration = 0.0f;
- mCurrentRate = 0.0f;
- mLoadedDuration = 0.0f;
-}
-
-void LLPluginClassMedia::idle(void)
-{
- if(mPlugin)
- {
- mPlugin->idle();
- }
-
- if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
- {
- // Can't process a size change at this time
- }
- else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
- {
- // Calculate the correct size for the media texture
- mRequestedTextureHeight = mRequestedMediaHeight;
- if(mPadding < 0)
- {
- // negative values indicate the plugin wants a power of 2
- mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
- }
- else
- {
- mRequestedTextureWidth = mRequestedMediaWidth;
-
- if(mPadding > 1)
- {
- // Pad up to a multiple of the specified number of bytes per row
- int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
- int pad = rowbytes % mPadding;
- if(pad != 0)
- {
- rowbytes += mPadding - pad;
- }
-
- if(rowbytes % mRequestedTextureDepth == 0)
- {
- mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
- }
- else
- {
- LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
- }
- }
- }
-
-
- // Size change has been requested but not initiated yet.
- size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
-
- // Add an extra line for padding, just in case.
- newsize += mRequestedTextureWidth * mRequestedTextureDepth;
-
- if(newsize != mTextureSharedMemorySize)
- {
- if(!mTextureSharedMemoryName.empty())
- {
- // Tell the plugin to remove the old memory segment
- mPlugin->removeSharedMemory(mTextureSharedMemoryName);
- mTextureSharedMemoryName.clear();
- }
-
- mTextureSharedMemorySize = newsize;
- mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
- if(!mTextureSharedMemoryName.empty())
- {
- void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-
- // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
- memset( addr, 0x00, newsize );
-
- // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
- // so it may not be worthwhile.
- // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
- }
- }
-
- // This is our local indicator that a change is in progress.
- mTextureWidth = -1;
- mTextureHeight = -1;
- mMediaWidth = -1;
- mMediaHeight = -1;
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // Send a size change message to the plugin
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
- message.setValue("name", mTextureSharedMemoryName);
- message.setValueS32("width", mRequestedMediaWidth);
- message.setValueS32("height", mRequestedMediaHeight);
- message.setValueS32("texture_width", mRequestedTextureWidth);
- message.setValueS32("texture_height", mRequestedTextureHeight);
- message.setValueReal("background_r", mBackgroundColor.mV[VX]);
- message.setValueReal("background_g", mBackgroundColor.mV[VY]);
- message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
- message.setValueReal("background_a", mBackgroundColor.mV[VW]);
- mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-
- LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
- }
- }
-
- if(mPlugin && mPlugin->isRunning())
- {
- // Send queued messages
- while(!mSendQueue.empty())
- {
- LLPluginMessage message = mSendQueue.front();
- mSendQueue.pop();
- mPlugin->sendMessage(message);
- }
- }
-}
-
-int LLPluginClassMedia::getTextureWidth() const
-{
- return nextPowerOf2(mTextureWidth);
-}
-
-int LLPluginClassMedia::getTextureHeight() const
-{
- return nextPowerOf2(mTextureHeight);
-}
-
-unsigned char* LLPluginClassMedia::getBitsData()
-{
- unsigned char *result = NULL;
- if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
- {
- result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
- }
- return result;
-}
-
-void LLPluginClassMedia::setSize(int width, int height)
-{
- if((width > 0) && (height > 0))
- {
- mSetMediaWidth = width;
- mSetMediaHeight = height;
- }
- else
- {
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- }
-
- setSizeInternal();
-}
-
-void LLPluginClassMedia::setSizeInternal(void)
-{
- if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
- {
- mRequestedMediaWidth = mSetMediaWidth;
- mRequestedMediaHeight = mSetMediaHeight;
- }
- else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
- {
- mRequestedMediaWidth = mNaturalMediaWidth;
- mRequestedMediaHeight = mNaturalMediaHeight;
- }
- else
- {
- mRequestedMediaWidth = mDefaultMediaWidth;
- mRequestedMediaHeight = mDefaultMediaHeight;
- }
-
- // Save these for size/interest calculations
- mFullMediaWidth = mRequestedMediaWidth;
- mFullMediaHeight = mRequestedMediaHeight;
-
- if(mAllowDownsample)
- {
- switch(mPriority)
- {
- case PRIORITY_SLIDESHOW:
- case PRIORITY_LOW:
- // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
- while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
- {
- mRequestedMediaWidth /= 2;
- mRequestedMediaHeight /= 2;
- }
- break;
-
- default:
- // Don't adjust texture size
- break;
- }
- }
-
- if(mAutoScaleMedia)
- {
- mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
- mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
- }
-
- if(mRequestedMediaWidth > 2048)
- mRequestedMediaWidth = 2048;
-
- if(mRequestedMediaHeight > 2048)
- mRequestedMediaHeight = 2048;
-}
-
-void LLPluginClassMedia::setAutoScale(bool auto_scale)
-{
- if(auto_scale != mAutoScaleMedia)
- {
- mAutoScaleMedia = auto_scale;
- setSizeInternal();
- }
-}
-
-bool LLPluginClassMedia::textureValid(void)
-{
- if(
- !mTextureParamsReceived ||
- mTextureWidth <= 0 ||
- mTextureHeight <= 0 ||
- mMediaWidth <= 0 ||
- mMediaHeight <= 0 ||
- mRequestedMediaWidth != mMediaWidth ||
- mRequestedMediaHeight != mMediaHeight ||
- getBitsData() == NULL
- )
- return false;
-
- return true;
-}
-
-bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
-{
- bool result = !mDirtyRect.isEmpty();
-
- if(dirty_rect != NULL)
- {
- *dirty_rect = mDirtyRect;
- }
-
- return result;
-}
-
-void LLPluginClassMedia::resetDirty(void)
-{
- mDirtyRect = LLRect::null;
-}
-
-std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
-{
- std::string result;
-
-
- if(modifiers & MASK_CONTROL)
- {
- result += "control|";
- }
-
- if(modifiers & MASK_ALT)
- {
- result += "alt|";
- }
-
- if(modifiers & MASK_SHIFT)
- {
- result += "shift|";
- }
-
- // TODO: should I deal with platform differences here or in callers?
- // TODO: how do we deal with the Mac "command" key?
-/*
- if(modifiers & MASK_SOMETHING)
- {
- result += "meta|";
- }
-*/
- return result;
-}
-
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
-{
- if(type == MOUSE_EVENT_MOVE)
- {
- if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
- {
- // Don't queue up mouse move events that can't be delivered.
- return;
- }
-
- if((x == mLastMouseX) && (y == mLastMouseY))
- {
- // Don't spam unnecessary mouse move events.
- return;
- }
-
- mLastMouseX = x;
- mLastMouseY = y;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
- std::string temp;
- switch(type)
- {
- case MOUSE_EVENT_DOWN: temp = "down"; break;
- case MOUSE_EVENT_UP: temp = "up"; break;
- case MOUSE_EVENT_MOVE: temp = "move"; break;
- case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("button", button);
-
- message.setValueS32("x", x);
-
- // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
- if(!mRequestedTextureCoordsOpenGL)
- {
- // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
- y = mMediaHeight - y;
- }
- message.setValueS32("y", y);
-
- message.setValue("modifiers", translateModifiers(modifiers));
-
- sendMessage(message);
-}
-
-bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
-{
- bool result = true;
-
- // FIXME:
- // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
- // For now, return false for the ones the webkit plugin won't handle properly.
-
- switch(key_code)
- {
- case KEY_BACKSPACE:
- case KEY_TAB:
- case KEY_RETURN:
- case KEY_PAD_RETURN:
- case KEY_SHIFT:
- case KEY_CONTROL:
- case KEY_ALT:
- case KEY_CAPSLOCK:
- case KEY_ESCAPE:
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_END:
- case KEY_HOME:
- case KEY_LEFT:
- case KEY_UP:
- case KEY_RIGHT:
- case KEY_DOWN:
- case KEY_INSERT:
- case KEY_DELETE:
- // These will be handled
- break;
-
- default:
- // regular ASCII characters will also be handled
- if(key_code >= KEY_SPECIAL)
- {
- // Other "special" codes will not work properly.
- result = false;
- }
- break;
- }
-
-#if LL_DARWIN
- if(modifiers & MASK_ALT)
- {
- // Option-key modified characters should be handled by the unicode input path instead of this one.
- result = false;
- }
-#endif
-
- if(result)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
- std::string temp;
- switch(type)
- {
- case KEY_EVENT_DOWN: temp = "down"; break;
- case KEY_EVENT_UP: temp = "up"; break;
- case KEY_EVENT_REPEAT: temp = "repeat"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("key", key_code);
-
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
-
- sendMessage(message);
- }
-
- return result;
-}
-
-void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
-
- message.setValueS32("x", x);
- message.setValueS32("y", y);
- message.setValue("modifiers", translateModifiers(modifiers));
-
- sendMessage(message);
-}
-
-bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
-
- message.setValue("text", text);
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
-
- sendMessage(message);
-
- return true;
-}
-
-void LLPluginClassMedia::loadURI(const std::string &uri)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
-
- message.setValue("uri", uri);
-
- sendMessage(message);
-}
-
-const char* LLPluginClassMedia::priorityToString(EPriority priority)
-{
- const char* result = "UNKNOWN";
- switch(priority)
- {
- case PRIORITY_UNLOADED: result = "unloaded"; break;
- case PRIORITY_STOPPED: result = "stopped"; break;
- case PRIORITY_HIDDEN: result = "hidden"; break;
- case PRIORITY_SLIDESHOW: result = "slideshow"; break;
- case PRIORITY_LOW: result = "low"; break;
- case PRIORITY_NORMAL: result = "normal"; break;
- case PRIORITY_HIGH: result = "high"; break;
- }
-
- return result;
-}
-
-void LLPluginClassMedia::setPriority(EPriority priority)
-{
- if(mPriority != priority)
- {
- mPriority = priority;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
-
- std::string priority_string = priorityToString(priority);
- switch(priority)
- {
- case PRIORITY_UNLOADED:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_STOPPED:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_HIDDEN:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_SLIDESHOW:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_LOW:
- mSleepTime = 1.0f / 25.0f;
- break;
- case PRIORITY_NORMAL:
- mSleepTime = 1.0f / 50.0f;
- break;
- case PRIORITY_HIGH:
- mSleepTime = 1.0f / 100.0f;
- break;
- }
-
- message.setValue("priority", priority_string);
-
- sendMessage(message);
-
- if(mPlugin)
- {
- mPlugin->setSleepTime(mSleepTime);
- }
-
- LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
-
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
-}
-
-void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
-{
- int power = nextPowerOf2(size);
- if(mLowPrioritySizeLimit != power)
- {
- mLowPrioritySizeLimit = power;
-
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
-}
-
-F64 LLPluginClassMedia::getCPUUsage()
-{
- F64 result = 0.0f;
-
- if(mPlugin)
- {
- result = mPlugin->getCPUUsage();
- }
-
- return result;
-}
-
-void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
- message.setValue("file", file);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
-}
-
-void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
- message.setValueBoolean("ok", ok);
- message.setValue("username", username);
- message.setValue("password", password);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
-}
-
-void LLPluginClassMedia::cut()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::copy()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::paste()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
- message.setValue("path", user_data_path);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
- message.setValue("language", language_code);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setTarget(const std::string &target)
-{
- mTarget = target;
-}
-
-/* virtual */
-void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
-{
- std::string message_class = message.getClass();
-
- if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- std::string message_name = message.getName();
- if(message_name == "texture_params")
- {
- mRequestedTextureDepth = message.getValueS32("depth");
- mRequestedTextureInternalFormat = message.getValueU32("internalformat");
- mRequestedTextureFormat = message.getValueU32("format");
- mRequestedTextureType = message.getValueU32("type");
- mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
- mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
-
- // These two are optional, and will default to 0 if they're not specified.
- mDefaultMediaWidth = message.getValueS32("default_width");
- mDefaultMediaHeight = message.getValueS32("default_height");
-
- mAllowDownsample = message.getValueBoolean("allow_downsample");
- mPadding = message.getValueS32("padding");
-
- setSizeInternal();
-
- mTextureParamsReceived = true;
- }
- else if(message_name == "updated")
- {
- if(message.hasValue("left"))
- {
- LLRect newDirtyRect;
- newDirtyRect.mLeft = message.getValueS32("left");
- newDirtyRect.mTop = message.getValueS32("top");
- newDirtyRect.mRight = message.getValueS32("right");
- newDirtyRect.mBottom = message.getValueS32("bottom");
-
- // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
- // If they're backwards, swap them.
- if(newDirtyRect.mTop < newDirtyRect.mBottom)
- {
- S32 temp = newDirtyRect.mTop;
- newDirtyRect.mTop = newDirtyRect.mBottom;
- newDirtyRect.mBottom = temp;
- }
-
- if(mDirtyRect.isEmpty())
- {
- mDirtyRect = newDirtyRect;
- }
- else
- {
- mDirtyRect.unionWith(newDirtyRect);
- }
-
- LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
- << newDirtyRect.mLeft << ", "
- << newDirtyRect.mTop << ", "
- << newDirtyRect.mRight << ", "
- << newDirtyRect.mBottom << "), new dirty rect is: ("
- << mDirtyRect.mLeft << ", "
- << mDirtyRect.mTop << ", "
- << mDirtyRect.mRight << ", "
- << mDirtyRect.mBottom << ")"
- << LL_ENDL;
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
- }
-
-
- bool time_duration_updated = false;
- int previous_percent = mProgressPercent;
-
- if(message.hasValue("current_time"))
- {
- mCurrentTime = message.getValueReal("current_time");
- time_duration_updated = true;
- }
- if(message.hasValue("duration"))
- {
- mDuration = message.getValueReal("duration");
- time_duration_updated = true;
- }
-
- if(message.hasValue("current_rate"))
- {
- mCurrentRate = message.getValueReal("current_rate");
- }
-
- if(message.hasValue("loaded_duration"))
- {
- mLoadedDuration = message.getValueReal("loaded_duration");
- time_duration_updated = true;
- }
- else
- {
- // If the message doesn't contain a loaded_duration param, assume it's equal to duration
- mLoadedDuration = mDuration;
- }
-
- // Calculate a percentage based on the loaded duration and total duration.
- if(mDuration != 0.0f) // Don't divide by zero.
- {
- mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
- }
-
- if(time_duration_updated)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
- }
-
- if(previous_percent != mProgressPercent)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- }
- else if(message_name == "media_status")
- {
- std::string status = message.getValue("status");
-
- LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-
- if(status == "loading")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
- }
- else if(status == "loaded")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
- }
- else if(status == "error")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
- }
- else if(status == "playing")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
- }
- else if(status == "paused")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
- }
- else if(status == "done")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
- }
- else
- {
- // empty string or any unknown string
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- }
- }
- else if(message_name == "size_change_request")
- {
- S32 width = message.getValueS32("width");
- S32 height = message.getValueS32("height");
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
- mNaturalMediaWidth = width;
- mNaturalMediaHeight = height;
-
- setSizeInternal();
- }
- else if(message_name == "size_change_response")
- {
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
-
- mTextureWidth = message.getValueS32("texture_width");
- mTextureHeight = message.getValueS32("texture_height");
- mMediaWidth = message.getValueS32("width");
- mMediaHeight = message.getValueS32("height");
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // TODO: should we verify that the plugin sent back the right values?
- // Two size changes in a row may cause them to not match, due to queueing, etc.
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
- }
- else if(message_name == "cursor_changed")
- {
- mCursorName = message.getValue("name");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
- }
- else if(message_name == "edit_state")
- {
- if(message.hasValue("cut"))
- {
- mCanCut = message.getValueBoolean("cut");
- }
- if(message.hasValue("copy"))
- {
- mCanCopy = message.getValueBoolean("copy");
- }
- if(message.hasValue("paste"))
- {
- mCanPaste = message.getValueBoolean("paste");
- }
- }
- else if(message_name == "name_text")
- {
- mMediaName = message.getValue("name");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
- }
- else if(message_name == "pick_file")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
- }
- else if(message_name == "auth_request")
- {
- mAuthURL = message.getValue("url");
- mAuthRealm = message.getValue("realm");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
- {
- std::string message_name = message.getName();
- if(message_name == "navigate_begin")
- {
- mNavigateURI = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
- }
- else if(message_name == "navigate_complete")
- {
- mNavigateURI = message.getValue("uri");
- mNavigateResultCode = message.getValueS32("result_code");
- mNavigateResultString = message.getValue("result_string");
- mHistoryBackAvailable = message.getValueBoolean("history_back_available");
- mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
- }
- else if(message_name == "progress")
- {
- mProgressPercent = message.getValueS32("percent");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- else if(message_name == "status_text")
- {
- mStatusText = message.getValue("status");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
- }
- else if(message_name == "location_changed")
- {
- mLocation = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
- }
- else if(message_name == "click_href")
- {
- mClickURL = message.getValue("uri");
- mClickTarget = message.getValue("target");
- mClickUUID = message.getValue("uuid");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
- }
- else if(message_name == "click_nofollow")
- {
- mClickURL = message.getValue("uri");
- mClickNavType = message.getValue("nav_type");
- mClickTarget.clear();
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
- }
- else if(message_name == "navigate_error_page")
- {
- mStatusCode = message.getValueS32("status_code");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
- }
- else if(message_name == "cookie_set")
- {
- if(mOwner)
- {
- mOwner->handleCookieSet(this, message.getValue("cookie"));
- }
- }
- else if(message_name == "close_request")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
- }
- else if(message_name == "geometry_change")
- {
- mClickUUID = message.getValue("uuid");
- mGeometryX = message.getValueS32("x");
- mGeometryY = message.getValueS32("y");
- mGeometryWidth = message.getValueS32("width");
- mGeometryHeight = message.getValueS32("height");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
- }
- else if(message_name == "link_hovered")
- {
- // text is not currently used -- the tooltip hover text is taken from the "title".
- mHoverLink = message.getValue("link");
- mHoverText = message.getValue("title");
- // message.getValue("text");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- std::string message_name = message.getName();
-
- // This class hasn't defined any incoming messages yet.
-// if(message_name == "message_name")
-// {
-// }
-// else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
-
-}
-
-/* virtual */
-void LLPluginClassMedia::pluginLaunchFailed()
-{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
-}
-
-/* virtual */
-void LLPluginClassMedia::pluginDied()
-{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
-}
-
-void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
-{
- if(mOwner)
- {
- mOwner->handleMediaEvent(this, event);
- }
-}
-
-void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
-{
- if(mPlugin && mPlugin->isRunning())
- {
- mPlugin->sendMessage(message);
- }
- else
- {
- // The plugin isn't set up yet -- queue this message to be sent after initialization.
- mSendQueue.push(message);
- }
-}
-
-////////////////////////////////////////////////////////////
-// MARK: media_browser class functions
-bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
-{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
- return !version.empty();
-}
-
-void LLPluginClassMedia::focus(bool focused)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
-
- message.setValueBoolean("focused", focused);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cache()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cookies()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::set_cookies(const std::string &cookies)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
- message.setValue("cookies", cookies);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::enable_cookies(bool enable)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
- message.setValueBoolean("enable", enable);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
-
- message.setValueBoolean("enable", enable);
- message.setValue("host", host);
- message.setValueS32("port", port);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_stop()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_reload(bool ignore_cache)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
-
- message.setValueBoolean("ignore_cache", ignore_cache);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_forward()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_back()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
-
- message.setValue("user_agent", user_agent);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
-
- message.setValue("target", target);
- message.setValue("uuid", uuid);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
-
- message.setValue("uuid", uuid);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
- message.setValueBoolean("ignore", ignore);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
- message.setValue("path", path);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::crashPlugin()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::hangPlugin()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
-
- sendMessage(message);
-}
-
-
-////////////////////////////////////////////////////////////
-// MARK: media_time class functions
-bool LLPluginClassMedia::pluginSupportsMediaTime(void)
-{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
- return !version.empty();
-}
-
-void LLPluginClassMedia::stop()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::start(float rate)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
-
- message.setValueReal("rate", rate);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::pause()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::seek(float time)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
-
- message.setValueReal("time", time);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setLoop(bool loop)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
-
- message.setValueBoolean("loop", loop);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setVolume(float volume)
-{
- if(volume != mRequestedVolume)
- {
- mRequestedVolume = volume;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
-
- message.setValueReal("volume", volume);
-
- sendMessage(message);
- }
-}
-
-float LLPluginClassMedia::getVolume()
-{
- return mRequestedVolume;
-}
-
-void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
-{
- // Send URL history to plugin
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
- message.setValueLLSD("history", url_history);
- sendMessage(message);
-
- LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
-}
-
+/**
+ * @file llpluginclassmedia.cpp
+ * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llpluginclassmedia.h"
+#include "llpluginmessageclasses.h"
+
+#include "llqtwebkit.h"
+
+static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
+
+static int nextPowerOf2( int value )
+{
+ int next_power_of_2 = 1;
+ while ( next_power_of_2 < value )
+ {
+ next_power_of_2 <<= 1;
+ }
+
+ return next_power_of_2;
+}
+
+LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
+{
+ mOwner = owner;
+ mPlugin = NULL;
+ reset();
+
+ //debug use
+ mDeleteOK = true ;
+}
+
+
+LLPluginClassMedia::~LLPluginClassMedia()
+{
+ llassert_always(mDeleteOK) ;
+ reset();
+}
+
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
+{
+ LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
+ LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+
+ mPlugin = new LLPluginProcessParent(this);
+ mPlugin->setSleepTime(mSleepTime);
+
+ // Queue up the media init message -- it will be sent after all the currently queued messages.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
+ message.setValue("target", mTarget);
+ sendMessage(message);
+
+ mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
+
+ return true;
+}
+
+
+void LLPluginClassMedia::reset()
+{
+ if(mPlugin != NULL)
+ {
+ delete mPlugin;
+ mPlugin = NULL;
+ }
+
+ mTextureParamsReceived = false;
+ mRequestedTextureDepth = 0;
+ mRequestedTextureInternalFormat = 0;
+ mRequestedTextureFormat = 0;
+ mRequestedTextureType = 0;
+ mRequestedTextureSwapBytes = false;
+ mRequestedTextureCoordsOpenGL = false;
+ mTextureSharedMemorySize = 0;
+ mTextureSharedMemoryName.clear();
+ mDefaultMediaWidth = 0;
+ mDefaultMediaHeight = 0;
+ mNaturalMediaWidth = 0;
+ mNaturalMediaHeight = 0;
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ mRequestedMediaWidth = 0;
+ mRequestedMediaHeight = 0;
+ mRequestedTextureWidth = 0;
+ mRequestedTextureHeight = 0;
+ mFullMediaWidth = 0;
+ mFullMediaHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mMediaWidth = 0;
+ mMediaHeight = 0;
+ mDirtyRect = LLRect::null;
+ mAutoScaleMedia = false;
+ mRequestedVolume = 1.0f;
+ mPriority = PRIORITY_NORMAL;
+ mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+ mAllowDownsample = false;
+ mPadding = 0;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ mSleepTime = 1.0f / 100.0f;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mMediaName.clear();
+ mMediaDescription.clear();
+ mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // media_browser class
+ mNavigateURI.clear();
+ mNavigateResultCode = -1;
+ mNavigateResultString.clear();
+ mHistoryBackAvailable = false;
+ mHistoryForwardAvailable = false;
+ mStatusText.clear();
+ mProgressPercent = 0;
+ mClickURL.clear();
+ mClickNavType.clear();
+ mClickTarget.clear();
+ mClickUUID.clear();
+ mStatusCode = 0;
+
+ // media_time class
+ mCurrentTime = 0.0f;
+ mDuration = 0.0f;
+ mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
+}
+
+void LLPluginClassMedia::idle(void)
+{
+ if(mPlugin)
+ {
+ mPlugin->idle();
+ }
+
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
+ {
+ // Can't process a size change at this time
+ }
+ else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+ {
+ // Calculate the correct size for the media texture
+ mRequestedTextureHeight = mRequestedMediaHeight;
+ if(mPadding < 0)
+ {
+ // negative values indicate the plugin wants a power of 2
+ mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+ }
+ else
+ {
+ mRequestedTextureWidth = mRequestedMediaWidth;
+
+ if(mPadding > 1)
+ {
+ // Pad up to a multiple of the specified number of bytes per row
+ int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+ int pad = rowbytes % mPadding;
+ if(pad != 0)
+ {
+ rowbytes += mPadding - pad;
+ }
+
+ if(rowbytes % mRequestedTextureDepth == 0)
+ {
+ mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+ }
+ }
+ }
+
+
+ // Size change has been requested but not initiated yet.
+ size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+ // Add an extra line for padding, just in case.
+ newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+ if(newsize != mTextureSharedMemorySize)
+ {
+ if(!mTextureSharedMemoryName.empty())
+ {
+ // Tell the plugin to remove the old memory segment
+ mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+ mTextureSharedMemoryName.clear();
+ }
+
+ mTextureSharedMemorySize = newsize;
+ mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+ if(!mTextureSharedMemoryName.empty())
+ {
+ void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+
+ // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+ memset( addr, 0x00, newsize );
+
+ // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+ // so it may not be worthwhile.
+ // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+ }
+ }
+
+ // This is our local indicator that a change is in progress.
+ mTextureWidth = -1;
+ mTextureHeight = -1;
+ mMediaWidth = -1;
+ mMediaHeight = -1;
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // Send a size change message to the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+ message.setValue("name", mTextureSharedMemoryName);
+ message.setValueS32("width", mRequestedMediaWidth);
+ message.setValueS32("height", mRequestedMediaHeight);
+ message.setValueS32("texture_width", mRequestedTextureWidth);
+ message.setValueS32("texture_height", mRequestedTextureHeight);
+ message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+ message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+ message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+ message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+ mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+
+ LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+ }
+ }
+
+ if(mPlugin && mPlugin->isRunning())
+ {
+ // Send queued messages
+ while(!mSendQueue.empty())
+ {
+ LLPluginMessage message = mSendQueue.front();
+ mSendQueue.pop();
+ mPlugin->sendMessage(message);
+ }
+ }
+}
+
+int LLPluginClassMedia::getTextureWidth() const
+{
+ return nextPowerOf2(mTextureWidth);
+}
+
+int LLPluginClassMedia::getTextureHeight() const
+{
+ return nextPowerOf2(mTextureHeight);
+}
+
+unsigned char* LLPluginClassMedia::getBitsData()
+{
+ unsigned char *result = NULL;
+ if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+ {
+ result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+ }
+ return result;
+}
+
+void LLPluginClassMedia::setSize(int width, int height)
+{
+ if((width > 0) && (height > 0))
+ {
+ mSetMediaWidth = width;
+ mSetMediaHeight = height;
+ }
+ else
+ {
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ }
+
+ setSizeInternal();
+}
+
+void LLPluginClassMedia::setSizeInternal(void)
+{
+ if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mSetMediaWidth;
+ mRequestedMediaHeight = mSetMediaHeight;
+ }
+ else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mNaturalMediaWidth;
+ mRequestedMediaHeight = mNaturalMediaHeight;
+ }
+ else
+ {
+ mRequestedMediaWidth = mDefaultMediaWidth;
+ mRequestedMediaHeight = mDefaultMediaHeight;
+ }
+
+ // Save these for size/interest calculations
+ mFullMediaWidth = mRequestedMediaWidth;
+ mFullMediaHeight = mRequestedMediaHeight;
+
+ if(mAllowDownsample)
+ {
+ switch(mPriority)
+ {
+ case PRIORITY_SLIDESHOW:
+ case PRIORITY_LOW:
+ // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+ while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+ {
+ mRequestedMediaWidth /= 2;
+ mRequestedMediaHeight /= 2;
+ }
+ break;
+
+ default:
+ // Don't adjust texture size
+ break;
+ }
+ }
+
+ if(mAutoScaleMedia)
+ {
+ mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+ mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+ }
+
+ if(mRequestedMediaWidth > 2048)
+ mRequestedMediaWidth = 2048;
+
+ if(mRequestedMediaHeight > 2048)
+ mRequestedMediaHeight = 2048;
+}
+
+void LLPluginClassMedia::setAutoScale(bool auto_scale)
+{
+ if(auto_scale != mAutoScaleMedia)
+ {
+ mAutoScaleMedia = auto_scale;
+ setSizeInternal();
+ }
+}
+
+bool LLPluginClassMedia::textureValid(void)
+{
+ if(
+ !mTextureParamsReceived ||
+ mTextureWidth <= 0 ||
+ mTextureHeight <= 0 ||
+ mMediaWidth <= 0 ||
+ mMediaHeight <= 0 ||
+ mRequestedMediaWidth != mMediaWidth ||
+ mRequestedMediaHeight != mMediaHeight ||
+ getBitsData() == NULL
+ )
+ return false;
+
+ return true;
+}
+
+bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
+{
+ bool result = !mDirtyRect.isEmpty();
+
+ if(dirty_rect != NULL)
+ {
+ *dirty_rect = mDirtyRect;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::resetDirty(void)
+{
+ mDirtyRect = LLRect::null;
+}
+
+std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
+{
+ std::string result;
+
+
+ if(modifiers & MASK_CONTROL)
+ {
+ result += "control|";
+ }
+
+ if(modifiers & MASK_ALT)
+ {
+ result += "alt|";
+ }
+
+ if(modifiers & MASK_SHIFT)
+ {
+ result += "shift|";
+ }
+
+ // TODO: should I deal with platform differences here or in callers?
+ // TODO: how do we deal with the Mac "command" key?
+/*
+ if(modifiers & MASK_SOMETHING)
+ {
+ result += "meta|";
+ }
+*/
+ return result;
+}
+
+void LLPluginClassMedia::jsEnableObject( bool enable )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
+ message.setValueReal( "angle", angle );
+
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
+ message.setValue( "language", language );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
+ message.setValue( "region", region );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
+ message.setValue( "maturity", maturity );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
+{
+ if(type == MOUSE_EVENT_MOVE)
+ {
+ if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+ {
+ // Don't queue up mouse move events that can't be delivered.
+ return;
+ }
+
+ if((x == mLastMouseX) && (y == mLastMouseY))
+ {
+ // Don't spam unnecessary mouse move events.
+ return;
+ }
+
+ mLastMouseX = x;
+ mLastMouseY = y;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+ std::string temp;
+ switch(type)
+ {
+ case MOUSE_EVENT_DOWN: temp = "down"; break;
+ case MOUSE_EVENT_UP: temp = "up"; break;
+ case MOUSE_EVENT_MOVE: temp = "move"; break;
+ case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("button", button);
+
+ message.setValueS32("x", x);
+
+ // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+ if(!mRequestedTextureCoordsOpenGL)
+ {
+ // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+ y = mMediaHeight - y;
+ }
+ message.setValueS32("y", y);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
+{
+ bool result = true;
+
+ // FIXME:
+ // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+ // For now, return false for the ones the webkit plugin won't handle properly.
+
+ switch(key_code)
+ {
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
+ case KEY_DELETE:
+ // These will be handled
+ break;
+
+ default:
+ // regular ASCII characters will also be handled
+ if(key_code >= KEY_SPECIAL)
+ {
+ // Other "special" codes will not work properly.
+ result = false;
+ }
+ break;
+ }
+
+#if LL_DARWIN
+ if(modifiers & MASK_ALT)
+ {
+ // Option-key modified characters should be handled by the unicode input path instead of this one.
+ result = false;
+ }
+#endif
+
+ if(result)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+ std::string temp;
+ switch(type)
+ {
+ case KEY_EVENT_DOWN: temp = "down"; break;
+ case KEY_EVENT_UP: temp = "up"; break;
+ case KEY_EVENT_REPEAT: temp = "repeat"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("key", key_code);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+
+ message.setValue("text", text);
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+
+ return true;
+}
+
+void LLPluginClassMedia::loadURI(const std::string &uri)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+
+ message.setValue("uri", uri);
+
+ sendMessage(message);
+}
+
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+ const char* result = "UNKNOWN";
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED: result = "unloaded"; break;
+ case PRIORITY_STOPPED: result = "stopped"; break;
+ case PRIORITY_HIDDEN: result = "hidden"; break;
+ case PRIORITY_SLIDESHOW: result = "slideshow"; break;
+ case PRIORITY_LOW: result = "low"; break;
+ case PRIORITY_NORMAL: result = "normal"; break;
+ case PRIORITY_HIGH: result = "high"; break;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::setPriority(EPriority priority)
+{
+ if(mPriority != priority)
+ {
+ mPriority = priority;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+
+ std::string priority_string = priorityToString(priority);
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_STOPPED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_HIDDEN:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_SLIDESHOW:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_LOW:
+ mSleepTime = 1.0f / 25.0f;
+ break;
+ case PRIORITY_NORMAL:
+ mSleepTime = 1.0f / 50.0f;
+ break;
+ case PRIORITY_HIGH:
+ mSleepTime = 1.0f / 100.0f;
+ break;
+ }
+
+ message.setValue("priority", priority_string);
+
+ sendMessage(message);
+
+ if(mPlugin)
+ {
+ mPlugin->setSleepTime(mSleepTime);
+ }
+
+ LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
+{
+ int power = nextPowerOf2(size);
+ if(mLowPrioritySizeLimit != power)
+ {
+ mLowPrioritySizeLimit = power;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+F64 LLPluginClassMedia::getCPUUsage()
+{
+ F64 result = 0.0f;
+
+ if(mPlugin)
+ {
+ result = mPlugin->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
+ message.setValue("file", file);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+ message.setValueBoolean("ok", ok);
+ message.setValue("username", username);
+ message.setValue("password", password);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::cut()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::copy()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::paste()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
+ message.setValue("path", user_data_path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
+ message.setValue("language", language_code);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setTarget(const std::string &target)
+{
+ mTarget = target;
+}
+
+/* virtual */
+void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
+{
+ std::string message_class = message.getClass();
+
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "texture_params")
+ {
+ mRequestedTextureDepth = message.getValueS32("depth");
+ mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+ mRequestedTextureFormat = message.getValueU32("format");
+ mRequestedTextureType = message.getValueU32("type");
+ mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
+ // These two are optional, and will default to 0 if they're not specified.
+ mDefaultMediaWidth = message.getValueS32("default_width");
+ mDefaultMediaHeight = message.getValueS32("default_height");
+
+ mAllowDownsample = message.getValueBoolean("allow_downsample");
+ mPadding = message.getValueS32("padding");
+
+ setSizeInternal();
+
+ mTextureParamsReceived = true;
+ }
+ else if(message_name == "updated")
+ {
+ if(message.hasValue("left"))
+ {
+ LLRect newDirtyRect;
+ newDirtyRect.mLeft = message.getValueS32("left");
+ newDirtyRect.mTop = message.getValueS32("top");
+ newDirtyRect.mRight = message.getValueS32("right");
+ newDirtyRect.mBottom = message.getValueS32("bottom");
+
+ // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+ // If they're backwards, swap them.
+ if(newDirtyRect.mTop < newDirtyRect.mBottom)
+ {
+ S32 temp = newDirtyRect.mTop;
+ newDirtyRect.mTop = newDirtyRect.mBottom;
+ newDirtyRect.mBottom = temp;
+ }
+
+ if(mDirtyRect.isEmpty())
+ {
+ mDirtyRect = newDirtyRect;
+ }
+ else
+ {
+ mDirtyRect.unionWith(newDirtyRect);
+ }
+
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ << newDirtyRect.mLeft << ", "
+ << newDirtyRect.mTop << ", "
+ << newDirtyRect.mRight << ", "
+ << newDirtyRect.mBottom << "), new dirty rect is: ("
+ << mDirtyRect.mLeft << ", "
+ << mDirtyRect.mTop << ", "
+ << mDirtyRect.mRight << ", "
+ << mDirtyRect.mBottom << ")"
+ << LL_ENDL;
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+ }
+
+
+ bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
+
+ if(message.hasValue("current_time"))
+ {
+ mCurrentTime = message.getValueReal("current_time");
+ time_duration_updated = true;
+ }
+ if(message.hasValue("duration"))
+ {
+ mDuration = message.getValueReal("duration");
+ time_duration_updated = true;
+ }
+
+ if(message.hasValue("current_rate"))
+ {
+ mCurrentRate = message.getValueReal("current_rate");
+ }
+
+ if(message.hasValue("loaded_duration"))
+ {
+ mLoadedDuration = message.getValueReal("loaded_duration");
+ time_duration_updated = true;
+ }
+ else
+ {
+ // If the message doesn't contain a loaded_duration param, assume it's equal to duration
+ mLoadedDuration = mDuration;
+ }
+
+ // Calculate a percentage based on the loaded duration and total duration.
+ if(mDuration != 0.0f) // Don't divide by zero.
+ {
+ mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+ }
+
+ if(time_duration_updated)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+ }
+
+ if(previous_percent != mProgressPercent)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ }
+ else if(message_name == "media_status")
+ {
+ std::string status = message.getValue("status");
+
+ LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+
+ if(status == "loading")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+ }
+ else if(status == "loaded")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+ }
+ else if(status == "error")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+ }
+ else if(status == "playing")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ else if(status == "paused")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+ }
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
+ else
+ {
+ // empty string or any unknown string
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ }
+ }
+ else if(message_name == "size_change_request")
+ {
+ S32 width = message.getValueS32("width");
+ S32 height = message.getValueS32("height");
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+ mNaturalMediaWidth = width;
+ mNaturalMediaHeight = height;
+
+ setSizeInternal();
+ }
+ else if(message_name == "size_change_response")
+ {
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+
+ mTextureWidth = message.getValueS32("texture_width");
+ mTextureHeight = message.getValueS32("texture_height");
+ mMediaWidth = message.getValueS32("width");
+ mMediaHeight = message.getValueS32("height");
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // TODO: should we verify that the plugin sent back the right values?
+ // Two size changes in a row may cause them to not match, due to queueing, etc.
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+ }
+ else if(message_name == "cursor_changed")
+ {
+ mCursorName = message.getValue("name");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+ }
+ else if(message_name == "edit_state")
+ {
+ if(message.hasValue("cut"))
+ {
+ mCanCut = message.getValueBoolean("cut");
+ }
+ if(message.hasValue("copy"))
+ {
+ mCanCopy = message.getValueBoolean("copy");
+ }
+ if(message.hasValue("paste"))
+ {
+ mCanPaste = message.getValueBoolean("paste");
+ }
+ }
+ else if(message_name == "name_text")
+ {
+ mMediaName = message.getValue("name");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+ }
+ else if(message_name == "pick_file")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
+ }
+ else if(message_name == "auth_request")
+ {
+ mAuthURL = message.getValue("url");
+ mAuthRealm = message.getValue("realm");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "navigate_begin")
+ {
+ mNavigateURI = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+ }
+ else if(message_name == "navigate_complete")
+ {
+ mNavigateURI = message.getValue("uri");
+ mNavigateResultCode = message.getValueS32("result_code");
+ mNavigateResultString = message.getValue("result_string");
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+ }
+ else if(message_name == "progress")
+ {
+ mProgressPercent = message.getValueS32("percent");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ else if(message_name == "status_text")
+ {
+ mStatusText = message.getValue("status");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+ }
+ else if(message_name == "location_changed")
+ {
+ mLocation = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+ }
+ else if(message_name == "click_href")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget = message.getValue("target");
+ mClickUUID = message.getValue("uuid");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+ }
+ else if(message_name == "click_nofollow")
+ {
+ mClickURL = message.getValue("uri");
+ mClickNavType = message.getValue("nav_type");
+ mClickTarget.clear();
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+ }
+ else if(message_name == "navigate_error_page")
+ {
+ mStatusCode = message.getValueS32("status_code");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
+ }
+ else if(message_name == "cookie_set")
+ {
+ if(mOwner)
+ {
+ mOwner->handleCookieSet(this, message.getValue("cookie"));
+ }
+ }
+ else if(message_name == "close_request")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
+ }
+ else if(message_name == "geometry_change")
+ {
+ mClickUUID = message.getValue("uuid");
+ mGeometryX = message.getValueS32("x");
+ mGeometryY = message.getValueS32("y");
+ mGeometryWidth = message.getValueS32("width");
+ mGeometryHeight = message.getValueS32("height");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
+ }
+ else if(message_name == "link_hovered")
+ {
+ // text is not currently used -- the tooltip hover text is taken from the "title".
+ mHoverLink = message.getValue("link");
+ mHoverText = message.getValue("title");
+ // message.getValue("text");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ std::string message_name = message.getName();
+
+ // This class hasn't defined any incoming messages yet.
+// if(message_name == "message_name")
+// {
+// }
+// else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginDied()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+}
+
+void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
+{
+ if(mOwner)
+ {
+ mOwner->handleMediaEvent(this, event);
+ }
+}
+
+void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
+{
+ if(mPlugin && mPlugin->isRunning())
+ {
+ mPlugin->sendMessage(message);
+ }
+ else
+ {
+ // The plugin isn't set up yet -- queue this message to be sent after initialization.
+ mSendQueue.push(message);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// MARK: media_browser class functions
+bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::focus(bool focused)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+
+ message.setValueBoolean("focused", focused);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cache()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cookies()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::set_cookies(const std::string &cookies)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
+ message.setValue("cookies", cookies);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::enable_cookies(bool enable)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
+ message.setValueBoolean("enable", enable);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+
+ message.setValueBoolean("enable", enable);
+ message.setValue("host", host);
+ message.setValueS32("port", port);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_reload(bool ignore_cache)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+
+ message.setValueBoolean("ignore_cache", ignore_cache);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_forward()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_back()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+
+ message.setValue("user_agent", user_agent);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
+
+ message.setValue("target", target);
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
+
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+ message.setValueBoolean("ignore", ignore);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+ message.setValue("path", path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::crashPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::hangPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+
+ sendMessage(message);
+}
+
+
+////////////////////////////////////////////////////////////
+// MARK: media_time class functions
+bool LLPluginClassMedia::pluginSupportsMediaTime(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::start(float rate)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+
+ message.setValueReal("rate", rate);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::pause()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::seek(float time)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+
+ message.setValueReal("time", time);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLoop(bool loop)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+
+ message.setValueBoolean("loop", loop);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setVolume(float volume)
+{
+ if(volume != mRequestedVolume)
+ {
+ mRequestedVolume = volume;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+
+ message.setValueReal("volume", volume);
+
+ sendMessage(message);
+ }
+}
+
+float LLPluginClassMedia::getVolume()
+{
+ return mRequestedVolume;
+}
+
+void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
+{
+ // Send URL history to plugin
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+ message.setValueLLSD("history", url_history);
+ sendMessage(message);
+
+ LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index cf8d8b26b9..f8ed89f644 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -1,416 +1,425 @@
-/**
- * @file llpluginclassmedia.h
- * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#ifndef LL_LLPLUGINCLASSMEDIA_H
-#define LL_LLPLUGINCLASSMEDIA_H
-
-#include "llgltypes.h"
-#include "llpluginprocessparent.h"
-#include "llrect.h"
-#include "llpluginclassmediaowner.h"
-#include <queue>
-#include "v4color.h"
-
-class LLPluginClassMedia : public LLPluginProcessParentOwner
-{
- LOG_CLASS(LLPluginClassMedia);
-public:
- LLPluginClassMedia(LLPluginClassMediaOwner *owner);
- virtual ~LLPluginClassMedia();
-
- // local initialization, called by the media manager when creating a source
- virtual bool init(const std::string &launcher_filename,
- const std::string &plugin_dir,
- const std::string &plugin_filename,
- bool debug);
-
- // undoes everything init() didm called by the media manager when destroying a source
- virtual void reset();
-
- void idle(void);
-
- // All of these may return 0 or an actual valid value.
- // Callers need to check the return for 0, and not use the values in that case.
- int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
- int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
- int getNaturalWidth() const { return mNaturalMediaWidth; };
- int getNaturalHeight() const { return mNaturalMediaHeight; };
- int getSetWidth() const { return mSetMediaWidth; };
- int getSetHeight() const { return mSetMediaHeight; };
- int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
- int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
- int getTextureWidth() const;
- int getTextureHeight() const;
- int getFullWidth() const { return mFullMediaWidth; };
- int getFullHeight() const { return mFullMediaHeight; };
-
- // This may return NULL. Callers need to check for and handle this case.
- unsigned char* getBitsData();
-
- // gets the format details of the texture data
- // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
- int getTextureDepth() const { return mRequestedTextureDepth; };
- int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
- int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
- int getTextureFormatType() const { return mRequestedTextureType; };
- bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
- bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
-
- void setSize(int width, int height);
- void setAutoScale(bool auto_scale);
-
- void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
-
- void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
-
- // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
- // This will initially be false, and will also be false for some time after setSize while the resize is processed.
- // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
- // until you call idle() again.
- bool textureValid(void);
-
- bool getDirty(LLRect *dirty_rect = NULL);
- void resetDirty(void);
-
- typedef enum
- {
- MOUSE_EVENT_DOWN,
- MOUSE_EVENT_UP,
- MOUSE_EVENT_MOVE,
- MOUSE_EVENT_DOUBLE_CLICK
- }EMouseEventType;
-
- void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
-
- typedef enum
- {
- KEY_EVENT_DOWN,
- KEY_EVENT_UP,
- KEY_EVENT_REPEAT
- }EKeyEventType;
-
- bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
-
- void scrollEvent(int x, int y, MASK modifiers);
-
- // Text may be unicode (utf8 encoded)
- bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
-
- void loadURI(const std::string &uri);
-
- // "Loading" means uninitialized or any state prior to fully running (processing commands)
- bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
-
- // "Running" means the steady state -- i.e. processing messages
- bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
-
- // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
- bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
-
- std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
-
- bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
- void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
-
- // Inherited from LLPluginProcessParentOwner
- /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
- /* virtual */ void pluginLaunchFailed();
- /* virtual */ void pluginDied();
-
-
- typedef enum
- {
- PRIORITY_UNLOADED, // media plugin isn't even loaded.
- PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
- PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
- PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
- PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
- PRIORITY_NORMAL, // normal (default) priority
- PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
- }EPriority;
-
- static const char* priorityToString(EPriority priority);
- void setPriority(EPriority priority);
- void setLowPrioritySizeLimit(int size);
-
- F64 getCPUUsage();
-
- void sendPickFileResponse(const std::string &file);
-
- void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
-
- // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
- std::string getCursorName() const { return mCursorName; };
-
- LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
-
- void cut();
- bool canCut() const { return mCanCut; };
-
- void copy();
- bool canCopy() const { return mCanCopy; };
-
- void paste();
- 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);
- void setLanguageCode(const std::string &language_code);
- void setPluginsEnabled(const bool enabled);
- void setJavascriptEnabled(const bool enabled);
- void setTarget(const std::string &target);
-
- ///////////////////////////////////
- // media browser class functions
- bool pluginSupportsMediaBrowser(void);
-
- void focus(bool focused);
- void clear_cache();
- void clear_cookies();
- void set_cookies(const std::string &cookies);
- void enable_cookies(bool enable);
- void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
- void browse_stop();
- void browse_reload(bool ignore_cache = false);
- void browse_forward();
- void browse_back();
- void setBrowserUserAgent(const std::string& user_agent);
- void proxyWindowOpened(const std::string &target, const std::string &uuid);
- void proxyWindowClosed(const std::string &uuid);
- void ignore_ssl_cert_errors(bool ignore);
- void addCertificateFilePath(const std::string& path);
-
- // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
- std::string getNavigateURI() const { return mNavigateURI; };
-
- // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
- S32 getNavigateResultCode() const { return mNavigateResultCode; };
- std::string getNavigateResultString() const { return mNavigateResultString; };
- bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
- bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
-
- // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
- int getProgressPercent() const { return mProgressPercent; };
-
- // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
- std::string getStatusText() const { return mStatusText; };
-
- // This is valid after MEDIA_EVENT_LOCATION_CHANGED
- std::string getLocation() const { return mLocation; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickURL() const { return mClickURL; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickNavType() const { return mClickNavType; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
- std::string getClickTarget() const { return mClickTarget; };
-
- // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
- std::string getClickUUID() const { return mClickUUID; };
-
- // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
- S32 getStatusCode() const { return mStatusCode; };
-
- // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
- S32 getGeometryX() const { return mGeometryX; };
- S32 getGeometryY() const { return mGeometryY; };
- S32 getGeometryWidth() const { return mGeometryWidth; };
- S32 getGeometryHeight() const { return mGeometryHeight; };
-
- // These are valid during MEDIA_EVENT_AUTH_REQUEST
- std::string getAuthURL() const { return mAuthURL; };
- std::string getAuthRealm() const { return mAuthRealm; };
-
- // These are valid during MEDIA_EVENT_LINK_HOVERED
- std::string getHoverText() const { return mHoverText; };
- std::string getHoverLink() const { return mHoverLink; };
-
- std::string getMediaName() const { return mMediaName; };
- std::string getMediaDescription() const { return mMediaDescription; };
-
- // Crash the plugin. If you use this outside of a testbed, you will be punished.
- void crashPlugin();
-
- // Hang the plugin. If you use this outside of a testbed, you will be punished.
- void hangPlugin();
-
- ///////////////////////////////////
- // media time class functions
- bool pluginSupportsMediaTime(void);
- void stop();
- void start(float rate = 0.0f);
- void pause();
- void seek(float time);
- void setLoop(bool loop);
- void setVolume(float volume);
- float getVolume();
-
- F64 getCurrentTime(void) const { return mCurrentTime; };
- F64 getDuration(void) const { return mDuration; };
- F64 getCurrentPlayRate(void) { return mCurrentRate; };
- F64 getLoadedDuration(void) const { return mLoadedDuration; };
-
- // Initialize the URL history of the plugin by sending
- // "init_history" message
- void initializeUrlHistory(const LLSD& url_history);
-
-protected:
-
- LLPluginClassMediaOwner *mOwner;
-
- // Notify this object's owner that an event has occurred.
- void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
-
- void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
- std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
-
- void setSizeInternal(void);
-
- bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
- S32 mRequestedTextureDepth;
- LLGLenum mRequestedTextureInternalFormat;
- LLGLenum mRequestedTextureFormat;
- LLGLenum mRequestedTextureType;
- bool mRequestedTextureSwapBytes;
- bool mRequestedTextureCoordsOpenGL;
-
- std::string mTextureSharedMemoryName;
- size_t mTextureSharedMemorySize;
-
- // True to scale requested media up to the full size of the texture (i.e. next power of two)
- bool mAutoScaleMedia;
-
- // default media size for the plugin, from the texture_params message.
- int mDefaultMediaWidth;
- int mDefaultMediaHeight;
-
- // Size that has been requested by the plugin itself
- int mNaturalMediaWidth;
- int mNaturalMediaHeight;
-
- // Size that has been requested with setSize()
- int mSetMediaWidth;
- int mSetMediaHeight;
-
- // Full calculated media size (before auto-scale and downsample calculations)
- int mFullMediaWidth;
- int mFullMediaHeight;
-
- // Actual media size being set (after auto-scale)
- int mRequestedMediaWidth;
- int mRequestedMediaHeight;
-
- // Texture size calculated from actual media size
- int mRequestedTextureWidth;
- int mRequestedTextureHeight;
-
- // Size that the plugin has acknowledged
- int mTextureWidth;
- int mTextureHeight;
- int mMediaWidth;
- int mMediaHeight;
-
- float mRequestedVolume;
-
- // Priority of this media stream
- EPriority mPriority;
- int mLowPrioritySizeLimit;
-
- bool mAllowDownsample;
- int mPadding;
-
-
- LLPluginProcessParent *mPlugin;
-
- LLRect mDirtyRect;
-
- std::string translateModifiers(MASK modifiers);
-
- std::string mCursorName;
- int mLastMouseX;
- int mLastMouseY;
-
- LLPluginClassMediaOwner::EMediaStatus mStatus;
-
- F64 mSleepTime;
-
- bool mCanCut;
- bool mCanCopy;
- bool mCanPaste;
-
- std::string mMediaName;
- std::string mMediaDescription;
-
- LLColor4 mBackgroundColor;
-
- std::string mTarget;
-
- /////////////////////////////////////////
- // media_browser class
- std::string mNavigateURI;
- S32 mNavigateResultCode;
- std::string mNavigateResultString;
- bool mHistoryBackAvailable;
- bool mHistoryForwardAvailable;
- std::string mStatusText;
- int mProgressPercent;
- std::string mLocation;
- std::string mClickURL;
- std::string mClickNavType;
- std::string mClickTarget;
- std::string mClickUUID;
- S32 mGeometryX;
- S32 mGeometryY;
- S32 mGeometryWidth;
- S32 mGeometryHeight;
- S32 mStatusCode;
- std::string mAuthURL;
- std::string mAuthRealm;
- std::string mHoverText;
- std::string mHoverLink;
-
- /////////////////////////////////////////
- // media_time class
- F64 mCurrentTime;
- F64 mDuration;
- F64 mCurrentRate;
- F64 mLoadedDuration;
-
-//--------------------------------------
- //debug use only
- //
-private:
- bool mDeleteOK ;
-public:
- void setDeleteOK(bool flag) { mDeleteOK = flag ;}
-//--------------------------------------
-};
-
-#endif // LL_LLPLUGINCLASSMEDIA_H
+/**
+ * @file llpluginclassmedia.h
+ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINCLASSMEDIA_H
+#define LL_LLPLUGINCLASSMEDIA_H
+
+#include "llgltypes.h"
+#include "llpluginprocessparent.h"
+#include "llrect.h"
+#include "llpluginclassmediaowner.h"
+#include <queue>
+#include "v4color.h"
+
+class LLPluginClassMedia : public LLPluginProcessParentOwner
+{
+ LOG_CLASS(LLPluginClassMedia);
+public:
+ LLPluginClassMedia(LLPluginClassMediaOwner *owner);
+ virtual ~LLPluginClassMedia();
+
+ // local initialization, called by the media manager when creating a source
+ virtual bool init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
+ const std::string &plugin_filename,
+ bool debug);
+
+ // undoes everything init() didm called by the media manager when destroying a source
+ virtual void reset();
+
+ void idle(void);
+
+ // All of these may return 0 or an actual valid value.
+ // Callers need to check the return for 0, and not use the values in that case.
+ int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
+ int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
+ int getNaturalWidth() const { return mNaturalMediaWidth; };
+ int getNaturalHeight() const { return mNaturalMediaHeight; };
+ int getSetWidth() const { return mSetMediaWidth; };
+ int getSetHeight() const { return mSetMediaHeight; };
+ int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
+ int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
+ int getTextureWidth() const;
+ int getTextureHeight() const;
+ int getFullWidth() const { return mFullMediaWidth; };
+ int getFullHeight() const { return mFullMediaHeight; };
+
+ // This may return NULL. Callers need to check for and handle this case.
+ unsigned char* getBitsData();
+
+ // gets the format details of the texture data
+ // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
+ int getTextureDepth() const { return mRequestedTextureDepth; };
+ int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
+ int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
+ int getTextureFormatType() const { return mRequestedTextureType; };
+ bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
+ bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
+
+ void setSize(int width, int height);
+ void setAutoScale(bool auto_scale);
+
+ void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+
+ void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
+
+ // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
+ // This will initially be false, and will also be false for some time after setSize while the resize is processed.
+ // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
+ // until you call idle() again.
+ bool textureValid(void);
+
+ bool getDirty(LLRect *dirty_rect = NULL);
+ void resetDirty(void);
+
+ typedef enum
+ {
+ MOUSE_EVENT_DOWN,
+ MOUSE_EVENT_UP,
+ MOUSE_EVENT_MOVE,
+ MOUSE_EVENT_DOUBLE_CLICK
+ }EMouseEventType;
+
+ void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
+
+ typedef enum
+ {
+ KEY_EVENT_DOWN,
+ KEY_EVENT_UP,
+ KEY_EVENT_REPEAT
+ }EKeyEventType;
+
+ bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
+
+ void scrollEvent(int x, int y, MASK modifiers);
+
+ // Javascript <-> viewer events
+ void jsEnableObject( bool enable );
+ void jsAgentLocationEvent( double x, double y, double z );
+ void jsAgentGlobalLocationEvent( double x, double y, double z );
+ void jsAgentOrientationEvent( double angle );
+ void jsAgentLanguageEvent( const std::string& language );
+ void jsAgentRegionEvent( const std::string& region_name );
+ void jsAgentMaturityEvent( const std::string& maturity );
+
+ // Text may be unicode (utf8 encoded)
+ bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+
+ void loadURI(const std::string &uri);
+
+ // "Loading" means uninitialized or any state prior to fully running (processing commands)
+ bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
+
+ // "Running" means the steady state -- i.e. processing messages
+ bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
+
+ // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
+ bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
+
+ std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
+
+ bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
+ void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
+
+ // Inherited from LLPluginProcessParentOwner
+ /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+ /* virtual */ void pluginLaunchFailed();
+ /* virtual */ void pluginDied();
+
+
+ typedef enum
+ {
+ PRIORITY_UNLOADED, // media plugin isn't even loaded.
+ PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
+ PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
+ PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
+ PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
+ PRIORITY_NORMAL, // normal (default) priority
+ PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
+ }EPriority;
+
+ static const char* priorityToString(EPriority priority);
+ void setPriority(EPriority priority);
+ void setLowPrioritySizeLimit(int size);
+
+ F64 getCPUUsage();
+
+ void sendPickFileResponse(const std::string &file);
+
+ void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
+
+ // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
+ std::string getCursorName() const { return mCursorName; };
+
+ LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
+
+ void cut();
+ bool canCut() const { return mCanCut; };
+
+ void copy();
+ bool canCopy() const { return mCanCopy; };
+
+ void paste();
+ 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);
+ void setLanguageCode(const std::string &language_code);
+ void setPluginsEnabled(const bool enabled);
+ void setJavascriptEnabled(const bool enabled);
+ void setTarget(const std::string &target);
+
+ ///////////////////////////////////
+ // media browser class functions
+ bool pluginSupportsMediaBrowser(void);
+
+ void focus(bool focused);
+ void clear_cache();
+ void clear_cookies();
+ void set_cookies(const std::string &cookies);
+ void enable_cookies(bool enable);
+ void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
+ void browse_stop();
+ void browse_reload(bool ignore_cache = false);
+ void browse_forward();
+ void browse_back();
+ void setBrowserUserAgent(const std::string& user_agent);
+ void proxyWindowOpened(const std::string &target, const std::string &uuid);
+ void proxyWindowClosed(const std::string &uuid);
+ void ignore_ssl_cert_errors(bool ignore);
+ void addCertificateFilePath(const std::string& path);
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
+ std::string getNavigateURI() const { return mNavigateURI; };
+
+ // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
+ S32 getNavigateResultCode() const { return mNavigateResultCode; };
+ std::string getNavigateResultString() const { return mNavigateResultString; };
+ bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
+ bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
+
+ // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
+ int getProgressPercent() const { return mProgressPercent; };
+
+ // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
+ std::string getStatusText() const { return mStatusText; };
+
+ // This is valid after MEDIA_EVENT_LOCATION_CHANGED
+ std::string getLocation() const { return mLocation; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickURL() const { return mClickURL; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickNavType() const { return mClickNavType; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+ std::string getClickTarget() const { return mClickTarget; };
+
+ // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
+ std::string getClickUUID() const { return mClickUUID; };
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
+ S32 getStatusCode() const { return mStatusCode; };
+
+ // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
+ S32 getGeometryX() const { return mGeometryX; };
+ S32 getGeometryY() const { return mGeometryY; };
+ S32 getGeometryWidth() const { return mGeometryWidth; };
+ S32 getGeometryHeight() const { return mGeometryHeight; };
+
+ // These are valid during MEDIA_EVENT_AUTH_REQUEST
+ std::string getAuthURL() const { return mAuthURL; };
+ std::string getAuthRealm() const { return mAuthRealm; };
+
+ // These are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getHoverText() const { return mHoverText; };
+ std::string getHoverLink() const { return mHoverLink; };
+
+ std::string getMediaName() const { return mMediaName; };
+ std::string getMediaDescription() const { return mMediaDescription; };
+
+ // Crash the plugin. If you use this outside of a testbed, you will be punished.
+ void crashPlugin();
+
+ // Hang the plugin. If you use this outside of a testbed, you will be punished.
+ void hangPlugin();
+
+ ///////////////////////////////////
+ // media time class functions
+ bool pluginSupportsMediaTime(void);
+ void stop();
+ void start(float rate = 0.0f);
+ void pause();
+ void seek(float time);
+ void setLoop(bool loop);
+ void setVolume(float volume);
+ float getVolume();
+
+ F64 getCurrentTime(void) const { return mCurrentTime; };
+ F64 getDuration(void) const { return mDuration; };
+ F64 getCurrentPlayRate(void) { return mCurrentRate; };
+ F64 getLoadedDuration(void) const { return mLoadedDuration; };
+
+ // Initialize the URL history of the plugin by sending
+ // "init_history" message
+ void initializeUrlHistory(const LLSD& url_history);
+
+protected:
+
+ LLPluginClassMediaOwner *mOwner;
+
+ // Notify this object's owner that an event has occurred.
+ void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
+
+ void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
+ std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
+
+ void setSizeInternal(void);
+
+ bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
+ S32 mRequestedTextureDepth;
+ LLGLenum mRequestedTextureInternalFormat;
+ LLGLenum mRequestedTextureFormat;
+ LLGLenum mRequestedTextureType;
+ bool mRequestedTextureSwapBytes;
+ bool mRequestedTextureCoordsOpenGL;
+
+ std::string mTextureSharedMemoryName;
+ size_t mTextureSharedMemorySize;
+
+ // True to scale requested media up to the full size of the texture (i.e. next power of two)
+ bool mAutoScaleMedia;
+
+ // default media size for the plugin, from the texture_params message.
+ int mDefaultMediaWidth;
+ int mDefaultMediaHeight;
+
+ // Size that has been requested by the plugin itself
+ int mNaturalMediaWidth;
+ int mNaturalMediaHeight;
+
+ // Size that has been requested with setSize()
+ int mSetMediaWidth;
+ int mSetMediaHeight;
+
+ // Full calculated media size (before auto-scale and downsample calculations)
+ int mFullMediaWidth;
+ int mFullMediaHeight;
+
+ // Actual media size being set (after auto-scale)
+ int mRequestedMediaWidth;
+ int mRequestedMediaHeight;
+
+ // Texture size calculated from actual media size
+ int mRequestedTextureWidth;
+ int mRequestedTextureHeight;
+
+ // Size that the plugin has acknowledged
+ int mTextureWidth;
+ int mTextureHeight;
+ int mMediaWidth;
+ int mMediaHeight;
+
+ float mRequestedVolume;
+
+ // Priority of this media stream
+ EPriority mPriority;
+ int mLowPrioritySizeLimit;
+
+ bool mAllowDownsample;
+ int mPadding;
+
+
+ LLPluginProcessParent *mPlugin;
+
+ LLRect mDirtyRect;
+
+ std::string translateModifiers(MASK modifiers);
+
+ std::string mCursorName;
+ int mLastMouseX;
+ int mLastMouseY;
+
+ LLPluginClassMediaOwner::EMediaStatus mStatus;
+
+ F64 mSleepTime;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+
+ std::string mMediaName;
+ std::string mMediaDescription;
+
+ LLColor4 mBackgroundColor;
+
+ std::string mTarget;
+
+ /////////////////////////////////////////
+ // media_browser class
+ std::string mNavigateURI;
+ S32 mNavigateResultCode;
+ std::string mNavigateResultString;
+ bool mHistoryBackAvailable;
+ bool mHistoryForwardAvailable;
+ std::string mStatusText;
+ int mProgressPercent;
+ std::string mLocation;
+ std::string mClickURL;
+ std::string mClickNavType;
+ std::string mClickTarget;
+ std::string mClickUUID;
+ S32 mGeometryX;
+ S32 mGeometryY;
+ S32 mGeometryWidth;
+ S32 mGeometryHeight;
+ S32 mStatusCode;
+ std::string mAuthURL;
+ std::string mAuthRealm;
+ std::string mHoverText;
+ std::string mHoverLink;
+
+ /////////////////////////////////////////
+ // media_time class
+ F64 mCurrentTime;
+ F64 mDuration;
+ F64 mCurrentRate;
+ F64 mLoadedDuration;
+
+//--------------------------------------
+ //debug use only
+ //
+private:
+ bool mDeleteOK ;
+public:
+ void setDeleteOK(bool flag) { mDeleteOK = flag ;}
+//--------------------------------------
+};
+
+#endif // LL_LLPLUGINCLASSMEDIA_H
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 794cdb83d5..0463d5364b 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -50,7 +50,7 @@ std::string model_names[] =
"low_lod",
"medium_lod",
"high_lod",
- "physics_shape"
+ "physics_mesh"
};
const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
@@ -84,7 +84,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
domInputLocal_Array& v_inp = vertices->getInput_array();
if (inputs[j]->getOffset() != 0)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Vertex array offset MUST be zero." << llendl;
}
for (U32 k = 0; k < v_inp.getCount(); ++k)
@@ -98,7 +98,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
if (src->getTechnique_common()->getAccessor()->getStride() != 3)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Vertex array stride MUST be three." << llendl;
}
domListOfFloats& v = src->getFloat_array()->getValue();
@@ -149,9 +149,10 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
}
}
-void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
+bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
{
+
idx_stride = 0;
for (U32 j = 0; j < inputs.getCount(); ++j)
@@ -163,7 +164,11 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
-
+ if ( !vertices )
+ {
+ return false;
+ }
+
domInputLocal_Array& v_inp = vertices->getInput_array();
@@ -207,6 +212,8 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
}
idx_stride += 1;
+
+ return true;
}
LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
@@ -227,8 +234,12 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
S32 idx_stride = 0;
- get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
+ if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
+ {
+ return LLModel::BAD_ELEMENT;
+ }
+
domPRef p = tri->getP();
domListOfUInts& idx = p->getValue();
@@ -367,7 +378,10 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
S32 idx_stride = 0;
- get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
+ if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
+ {
+ return LLModel::BAD_ELEMENT;
+ }
LLVolumeFace face;
@@ -564,7 +578,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
-
+ if (!vertices)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
domInputLocal_Array& v_inp = vertices->getInput_array();
for (U32 k = 0; k < v_inp.getCount(); ++k)
@@ -574,6 +591,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = v_inp[k]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
+ if (!src)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
v = &(src->getFloat_array()->getValue());
}
}
@@ -585,6 +606,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
+ if (!src)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
n = &(src->getFloat_array()->getValue());
}
else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
@@ -593,6 +618,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
+ if (!src)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
t = &(src->getFloat_array()->getValue());
}
}
@@ -667,11 +696,6 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
}
}
- if (cur_idx != vert_idx.size())
- {
- llerrs << "WTF?" << llendl;
- }
-
//build vertex array from map
std::vector<LLVolumeFace::VertexData> new_verts;
new_verts.resize(vert_idx.size());
@@ -717,7 +741,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
//static
std::string LLModel::getStatusString(U32 status)
{
- const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow"};
+ const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"};
if(status < INVALID_STATUS)
{
@@ -755,7 +779,6 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
for (U32 i = 0; i < polys.getCount(); ++i)
{
domPolylistRef& poly = polys.get(i);
-
mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly);
if(mStatus != NO_ERRORS)
@@ -765,12 +788,12 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
return ; //abort
}
}
-
+
domPolygons_Array& polygons = mesh->getPolygons_array();
+
for (U32 i = 0; i < polygons.getCount(); ++i)
{
domPolygonsRef& poly = polygons.get(i);
-
mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly);
if(mStatus != NO_ERRORS)
@@ -780,7 +803,7 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
return ; //abort
}
}
-
+
}
BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
@@ -926,11 +949,6 @@ void LLModel::normalizeVolumeFaces()
{
LLVector4a min, max;
- if (mVolumeFaces[0].mNumVertices <= 0)
- {
- llerrs << "WTF?" << llendl;
- }
-
// For all of the volume faces
// in the model, loop over
// them and see what the extents
@@ -942,11 +960,6 @@ void LLModel::normalizeVolumeFaces()
{
LLVolumeFace& face = mVolumeFaces[i];
- if (face.mNumVertices <= 0)
- {
- llerrs << "WTF?" << llendl;
- }
-
update_min_max(min, max, face.mExtents[0]);
update_min_max(min, max, face.mExtents[1]);
}
@@ -991,6 +1004,9 @@ void LLModel::normalizeVolumeFaces()
scale.splat(1.f);
scale.div(size);
+ LLVector4a inv_scale(1.f);
+ inv_scale.div(scale);
+
for (U32 i = 0; i < mVolumeFaces.size(); ++i)
{
LLVolumeFace& face = mVolumeFaces[i];
@@ -1007,10 +1023,14 @@ void LLModel::normalizeVolumeFaces()
// For all the positions, we scale
// the positions to fit within the unit cube.
LLVector4a* pos = (LLVector4a*) face.mPositions;
+ LLVector4a* norm = (LLVector4a*) face.mNormals;
+
for (U32 j = 0; j < face.mNumVertices; ++j)
{
pos[j].add(trans);
pos[j].mul(scale);
+ norm[j].mul(inv_scale);
+ norm[j].normalize3();
}
}
@@ -1282,11 +1302,6 @@ void LLModel::generateNormals(F32 angle_cutoff)
{
LLVector4a& n = iter->second[k].getNormal();
- if (!iter->second[k].getPosition().equals3(new_face.mPositions[i]))
- {
- llerrs << "WTF?" << llendl;
- }
-
F32 cur = n.dot3(ref_norm).getF32();
if (cur > best)
@@ -1403,7 +1418,11 @@ LLSD LLModel::writeModel(
if (!decomp.mBaseHull.empty() ||
!decomp.mHull.empty())
{
- mdl["decomposition"] = decomp.asLLSD();
+ mdl["physics_convex"] = decomp.asLLSD();
+ if (!decomp.mHull.empty())
+ { //convex decomposition exists, physics mesh will not be used
+ model[LLModel::LOD_PHYSICS] = NULL;
+ }
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@@ -1428,8 +1447,9 @@ LLSD LLModel::writeModel(
for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
{ //for each face
const LLVolumeFace& face = model[idx]->getVolumeFace(i);
- if (!face.mNumVertices)
+ if (face.mNumVertices < 3)
{ //don't export an empty face
+ mdl[model_names[idx]][i]["NoGeometry"] = true;
continue;
}
LLSD::Binary verts(face.mNumVertices*3*2);
@@ -1462,7 +1482,6 @@ LLSD LLModel::writeModel(
//position + normal
for (U32 k = 0; k < 3; ++k)
{ //for each component
-
//convert to 16-bit normalized across domain
U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535);
@@ -1506,7 +1525,6 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
-
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
@@ -1532,11 +1550,6 @@ LLSD LLModel::writeModel(
weight_list& weights = high->getJointInfluences(pos);
- if (weights.size() > 4)
- {
- llerrs << "WTF?" << llendl;
- }
-
S32 count = 0;
for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)
{
@@ -1600,23 +1613,19 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
- else
- {
- llerrs << "WTF?" << llendl;
- }
}
std::string decomposition;
- if (mdl.has("decomposition"))
+ if (mdl.has("physics_convex"))
{ //write out convex decomposition
- decomposition = zip_llsd(mdl["decomposition"]);
+ decomposition = zip_llsd(mdl["physics_convex"]);
U32 size = decomposition.size();
if (size > 0)
{
- header["decomposition"]["offset"] = (LLSD::Integer) cur_offset;
- header["decomposition"]["size"] = (LLSD::Integer) size;
+ header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset;
+ header["physics_convex"]["size"] = (LLSD::Integer) size;
cur_offset += size;
bytes += size;
}
@@ -1637,11 +1646,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
- else
- {
- header[model_names[i]]["offset"] = -1;
- header[model_names[i]]["size"] = 0;
- }
}
if (!nowrite)
@@ -1655,7 +1659,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
if (!decomposition.empty())
{ //write decomposition block
- ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger());
+ ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());
}
for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
@@ -1678,7 +1682,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{
if ((iter->first - pos).magVec() > 0.1f)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Couldn't find weight list." << llendl;
}
return iter->second;
@@ -1771,7 +1775,7 @@ void LLModel::updateHullCenters()
if (mHullPoints > 0)
{
mCenterOfHullCenters *= 1.f / mHullPoints;
- llassert(mPhysics.asLLSD().has("HullList"));
+ llassert(mPhysics.hasHullList());
}
}
@@ -1794,7 +1798,7 @@ bool LLModel::loadModel(std::istream& is)
"low_lod",
"medium_lod",
"high_lod",
- "physics_shape",
+ "physics_mesh",
};
const S32 MODEL_LODS = 5;
@@ -1893,8 +1897,8 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
{
- S32 offset = header["decomposition"]["offset"].asInteger();
- S32 size = header["decomposition"]["size"].asInteger();
+ S32 offset = header["physics_convex"]["offset"].asInteger();
+ S32 size = header["physics_convex"]["size"].asInteger();
if (offset >= 0 && size > 0)
{
@@ -2034,7 +2038,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
// updated for const-correctness. gcc is picky about this type of thing - Nyx
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
- const LLSD::Binary& position = decomp["Position"].asBinary();
+ const LLSD::Binary& position = decomp["Positions"].asBinary();
U16* p = (U16*) &position[0];
@@ -2044,11 +2048,19 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
LLVector3 max;
LLVector3 range;
- min.setValue(decomp["Min"]);
- max.setValue(decomp["Max"]);
+ if (decomp.has("Min"))
+ {
+ min.setValue(decomp["Min"]);
+ max.setValue(decomp["Max"]);
+ }
+ else
+ {
+ min.set(-0.5f, -0.5f, -0.5f);
+ max.set(0.5f, 0.5f, 0.5f);
+ }
+
range = max-min;
-
for (U32 i = 0; i < hulls.size(); ++i)
{
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
@@ -2064,6 +2076,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
//point must be unique
//llassert(valid.find(test) == valid.end());
valid.insert(test);
+
mHull[i].push_back(LLVector3(
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
@@ -2078,9 +2091,9 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
}
}
- if (decomp.has("Hull"))
+ if (decomp.has("BoundingVerts"))
{
- const LLSD::Binary& position = decomp["Hull"].asBinary();
+ const LLSD::Binary& position = decomp["BoundingVerts"].asBinary();
U16* p = (U16*) &position[0];
@@ -2116,10 +2129,15 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
//empty base hull mesh to indicate decomposition has been loaded
//but contains no base hull
- mBaseHullMesh.clear();;
+ mBaseHullMesh.clear();
}
}
+bool LLModel::Decomposition::hasHullList() const
+{
+ return !mHull.empty() ;
+}
+
LLSD LLModel::Decomposition::asLLSD() const
{
LLSD ret;
@@ -2130,11 +2148,9 @@ LLSD LLModel::Decomposition::asLLSD() const
}
//write decomposition block
- // ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
- // ["decomposition"]["PositionDomain"]["Min"/"Max"]
- // ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
- // ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
-
+ // ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
+ // ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
+ // ["physics_convex"]["BoundingVerts"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
//get minimum and maximum
LLVector3 min;
@@ -2183,6 +2199,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(total*3*2);
+ LLVector3 min(-0.5f, -0.5f, -0.5f);
+ LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@@ -2198,17 +2216,24 @@ LLSD LLModel::Decomposition::asLLSD() const
U64 test = 0;
for (U32 k = 0; k < 3; k++)
{
+ F32* src = (F32*) (mHull[i][j].mV);
+
+ llassert(src[k] <= 0.501f && src[k] >= -0.501f);
+
//convert to 16-bit normalized across domain
- U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
+ U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
- switch (k)
+ if(valid.size() < 3)
{
- case 0: test = test | (U64) val; break;
- case 1: test = test | ((U64) val << 16); break;
- case 2: test = test | ((U64) val << 32); break;
- };
+ switch (k)
+ {
+ case 0: test = test | (U64) val; break;
+ case 1: test = test | ((U64) val << 16); break;
+ case 2: test = test | ((U64) val << 32); break;
+ };
- valid.insert(test);
+ valid.insert(test);
+ }
U8* buff = (U8*) &val;
//write to binary buffer
@@ -2220,17 +2245,21 @@ LLSD LLModel::Decomposition::asLLSD() const
}
}
- //must have at least 4 unique points
- llassert(valid.size() > 3);
+ //must have at least 3 unique points
+ llassert(valid.size() > 2);
}
- ret["Position"] = p;
+ ret["Positions"] = p;
}
+ //llassert(!mBaseHull.empty());
+
if (!mBaseHull.empty())
{
LLSD::Binary p(mBaseHull.size()*3*2);
+ LLVector3 min(-0.5f, -0.5f, -0.5f);
+ LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@@ -2238,6 +2267,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
for (U32 k = 0; k < 3; k++)
{
+ llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
+
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
@@ -2248,12 +2279,12 @@ LLSD LLModel::Decomposition::asLLSD() const
if (vert_idx > p.size())
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Index out of bounds" << llendl;
}
}
}
- ret["Hull"] = p;
+ ret["BoundingVerts"] = p;
}
return ret;
@@ -2283,10 +2314,5 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
{ //take physics shape mesh from rhs
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
}
-
- if (!mHull.empty())
- { //verify
- llassert(asLLSD().has("HullList"));
- }
}
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 23f4b5cb42..cd9f76fcb7 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -73,6 +73,7 @@ public:
{
NO_ERRORS = 0,
VERTEX_NUMBER_OVERFLOW, //vertex number is >= 65535.
+ BAD_ELEMENT,
INVALID_STATUS
} ;
@@ -106,6 +107,7 @@ public:
Decomposition(LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD() const;
+ bool hasHullList() const;
void merge(const Decomposition* rhs);
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index d6a31dc862..180ae4dfa6 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -554,7 +554,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
BOOL in_word = FALSE;
// avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
- F32 scaled_max_pixels = ceil(max_pixels * sScaleX);
+ F32 scaled_max_pixels = max_pixels * sScaleX;
F32 width_padding = 0.f;
LLFontGlyphInfo* next_glyph = NULL;
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index f29ee0e57e..c224ab0e9b 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -127,6 +127,11 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
+// GL_ARB_map_buffer_range
+PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
+
// vertex object prototypes
PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL;
PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL;
@@ -178,6 +183,12 @@ PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
+//GL_ARB_texture_multisample
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+PFNGLSAMPLEMASKIPROC glSampleMaski;
+
// GL_EXT_blend_func_separate
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
@@ -321,18 +332,26 @@ LLGLManager::LLGLManager() :
mHasMipMapGeneration(FALSE),
mHasCompressedTextures(FALSE),
mHasFramebufferObject(FALSE),
+ mMaxSamples(0),
mHasBlendFuncSeparate(FALSE),
mHasVertexBufferObject(FALSE),
+ mHasMapBufferRange(FALSE),
mHasPBuffer(FALSE),
mHasShaderObjects(FALSE),
mHasVertexShader(FALSE),
mHasFragmentShader(FALSE),
+ mNumTextureImageUnits(0),
mHasOcclusionQuery(FALSE),
mHasOcclusionQuery2(FALSE),
mHasPointParameters(FALSE),
mHasDrawBuffers(FALSE),
mHasTextureRectangle(FALSE),
+ mHasTextureMultisample(FALSE),
+ mMaxSampleMaskWords(0),
+ mMaxColorTextureSamples(0),
+ mMaxDepthTextureSamples(0),
+ mMaxIntegerSamples(0),
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
@@ -534,6 +553,33 @@ bool LLGLManager::initGL()
return false;
}
+ if (mHasFragmentShader)
+ {
+ GLint num_tex_image_units;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
+ mNumTextureImageUnits = llmin(num_tex_image_units, 32);
+ }
+
+ if (mHasTextureMultisample)
+ {
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
+ glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
+ glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
+ glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
+ }
+
+#if LL_WINDOWS
+ if (mIsATI)
+ { //using multisample textures on ATI results in black screen for some reason
+ mHasTextureMultisample = FALSE;
+ }
+#endif
+
+ if (mHasFramebufferObject)
+ {
+ glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
+ }
+
setToDebugGPU();
initGLStates();
@@ -640,6 +686,14 @@ std::string LLGLManager::getRawGLString()
return gl_string;
}
+U32 LLGLManager::getNumFBOFSAASamples(U32 samples)
+{
+ samples = llmin(samples, (U32) mMaxColorTextureSamples);
+ samples = llmin(samples, (U32) mMaxDepthTextureSamples);
+ samples = llmin(samples, (U32) 4);
+ return samples;
+}
+
void LLGLManager::shutdownGL()
{
if (mInited)
@@ -720,6 +774,7 @@ void LLGLManager::initExtensions()
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
+ mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
#ifdef GL_ARB_framebuffer_object
@@ -734,6 +789,7 @@ void LLGLManager::initExtensions()
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
+ mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
@@ -878,11 +934,13 @@ void LLGLManager::initExtensions()
LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL;
mHasMipMapGeneration = FALSE;
}
+#if !LL_DARWIN
if (mIsATI && mHasMipMapGeneration)
{
LL_INFOS("RenderInit") << "Disabling mip-map generation for ATI GPUs (performance opt)" << LL_ENDL;
mHasMipMapGeneration = FALSE;
}
+#endif
// Misc
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
@@ -911,6 +969,11 @@ void LLGLManager::initExtensions()
mHasVertexBufferObject = FALSE;
}
}
+ if (mHasMapBufferRange)
+ {
+ glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
+ glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
+ }
if (mHasFramebufferObject)
{
llinfos << "initExtensions() FramebufferObject-related procs..." << llendl;
@@ -943,6 +1006,13 @@ void LLGLManager::initExtensions()
{
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
}
+ if (mHasTextureMultisample)
+ {
+ glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
+ glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
+ glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
+ glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
+ }
#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
@@ -1360,10 +1430,6 @@ void LLGLState::checkTextureChannels(const std::string& msg)
}
}
- GLint maxTextureUnits = 0;
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
- stop_glerror();
-
static const char* label[] =
{
"GL_TEXTURE_2D",
@@ -1374,7 +1440,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
"GL_TEXTURE_GEN_T",
"GL_TEXTURE_GEN_Q",
"GL_TEXTURE_GEN_R",
- "GL_TEXTURE_RECTANGLE_ARB"
+ "GL_TEXTURE_RECTANGLE_ARB",
+ "GL_TEXTURE_2D_MULTISAMPLE"
};
static GLint value[] =
@@ -1387,7 +1454,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
GL_TEXTURE_GEN_T,
GL_TEXTURE_GEN_Q,
GL_TEXTURE_GEN_R,
- GL_TEXTURE_RECTANGLE_ARB
+ GL_TEXTURE_RECTANGLE_ARB,
+ GL_TEXTURE_2D_MULTISAMPLE
};
GLint stackDepth = 0;
@@ -1396,68 +1464,96 @@ void LLGLState::checkTextureChannels(const std::string& msg)
glh::matrix4f identity;
identity.identity();
- for (GLint i = 1; i < maxTextureUnits; i++)
+ for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
{
gGL.getTexUnit(i)->activate();
- glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
- stop_glerror();
- glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
- stop_glerror();
- if (stackDepth != 1)
+ if (i < gGLManager.mNumTextureUnits)
{
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+ glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
+ stop_glerror();
+ glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
+ stop_glerror();
- if (gDebugSession)
+ if (stackDepth != 1)
{
- gFailLog << "Texture matrix stack corrupted." << std::endl;
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix stack corrupted." << std::endl;
+ }
}
- }
- glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
- stop_glerror();
+ glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
+ stop_glerror();
- if (mat != identity)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
- if (gDebugSession)
+ if (mat != identity)
{
- gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+ }
+ }
+
+ for (S32 j = (i == 0 ? 1 : 0);
+ j < 9; j++)
+ {
+ if (j == 8 && !gGLManager.mHasTextureRectangle ||
+ j == 9 && !gGLManager.mHasTextureMultisample)
+ {
+ continue;
+ }
+
+ if (glIsEnabled(value[j]))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+ }
+ }
+ stop_glerror();
}
- }
-
- for (S32 j = (i == 0 ? 1 : 0);
- j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++)
- {
- if (glIsEnabled(value[j]))
+ glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
+ stop_glerror();
+
+ if (mat != identity)
{
error = TRUE;
- LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
if (gDebugSession)
{
- gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+ gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
}
}
- stop_glerror();
}
- glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
- stop_glerror();
-
- if (mat != identity)
{
- error = TRUE;
- LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
- if (gDebugSession)
+ GLint tex = 0;
+ stop_glerror();
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);
+ stop_glerror();
+
+ if (tex != 0)
{
- gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << llendl;
+
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl;
+ }
}
}
}
+ stop_glerror();
gGL.getTexUnit(0)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB);
stop_glerror();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 3d002fd8c4..d1bee00161 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -83,20 +83,28 @@ public:
BOOL mHasMipMapGeneration;
BOOL mHasCompressedTextures;
BOOL mHasFramebufferObject;
+ S32 mMaxSamples;
BOOL mHasBlendFuncSeparate;
-
+
// ARB Extensions
BOOL mHasVertexBufferObject;
+ BOOL mHasMapBufferRange;
BOOL mHasPBuffer;
BOOL mHasShaderObjects;
BOOL mHasVertexShader;
BOOL mHasFragmentShader;
+ S32 mNumTextureImageUnits;
BOOL mHasOcclusionQuery;
BOOL mHasOcclusionQuery2;
BOOL mHasPointParameters;
BOOL mHasDrawBuffers;
BOOL mHasDepthClamp;
BOOL mHasTextureRectangle;
+ BOOL mHasTextureMultisample;
+ S32 mMaxSampleMaskWords;
+ S32 mMaxColorTextureSamples;
+ S32 mMaxDepthTextureSamples;
+ S32 mMaxIntegerSamples;
// Other extensions.
BOOL mHasAnisotropic;
@@ -138,6 +146,7 @@ public:
void printGLInfoString();
void getGLInfo(LLSD& info);
+ U32 getNumFBOFSAASamples(U32 desired_samples = 32);
// In ALL CAPS
std::string mGLVendor;
std::string mGLVendorShort;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index d8140a124d..f35f329f00 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -68,6 +68,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -306,6 +310,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -474,6 +482,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
//GL_ARB_draw_buffers
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
+//GL_ARB_texture_multisample
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#elif LL_WINDOWS
//----------------------------------------------------------------------------
@@ -506,6 +519,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -673,6 +690,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
//GL_ARB_draw_buffers
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
+//GL_ARB_texture_multisample
+extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
+extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
+extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
+extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#elif LL_DARWIN
//----------------------------------------------------------------------------
@@ -714,13 +736,55 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
#ifndef GL_ARB_framebuffer_object
#define glGenerateMipmap glGenerateMipmapEXT
+#define GL_MAX_SAMPLES 0x8D57
#endif
+
// GL_ARB_draw_buffers
extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
#ifdef __cplusplus
extern "C" {
#endif
+
+//
+// Define map buffer range headers on Mac
+//
+#ifndef GL_ARB_map_buffer_range
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#endif
+
+//
+// Define multisample headers on Mac
+//
+#ifndef GL_ARB_texture_multisample
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#endif
+
//
// Define vertex buffer object headers on Mac
//
@@ -757,7 +821,7 @@ extern "C" {
#define GL_DYNAMIC_READ_ARB 0x88E9
#define GL_DYNAMIC_COPY_ARB 0x88EA
#endif
-
+
#ifndef GL_ARB_vertex_buffer_object
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 257bcd9380..ad2c662dfc 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -48,6 +48,8 @@ using std::pair;
using std::make_pair;
using std::string;
+GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+
BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
{
return v1 != v2;
@@ -56,7 +58,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
LLShaderFeatures::LLShaderFeatures()
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
+hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false)
{
}
@@ -107,16 +109,16 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
// Create program
mProgramObject = glCreateProgramObjectARB();
- // Attach existing objects
- if (!LLShaderMgr::instance()->attachShaderFeatures(this))
- {
- return FALSE;
+ if (gGLManager.mGLVersion < 3.1f)
+ { //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support)
+ mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
}
+ //compile new source
vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
{
- GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second);
+ GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
if (shaderhandle > 0)
{
@@ -128,6 +130,17 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
}
}
+ // Attach existing objects
+ if (!LLShaderMgr::instance()->attachShaderFeatures(this))
+ {
+ return FALSE;
+ }
+
+ if (gGLManager.mGLVersion < 3.1f)
+ { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
+ mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
+ }
+
// Map attributes and uniforms
if (success)
{
@@ -149,6 +162,29 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
return createShader(attributes,uniforms);
}
}
+ else if (mFeatures.mIndexedTextureChannels > 0)
+ { //override texture channels for indexed texture rendering
+ bind();
+ S32 channel_count = mFeatures.mIndexedTextureChannels;
+
+ for (S32 i = 0; i < channel_count; i++)
+ {
+ uniform1i(llformat("tex%d", i), i);
+ }
+
+ S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
+ for (U32 i = 0; i < mTexture.size(); i++)
+ {
+ if (mTexture[i] > -1 && mTexture[i] < channel_count)
+ {
+ llassert(cur_tex < gGLManager.mNumTextureImageUnits);
+ uniform1i(i, cur_tex);
+ mTexture[i] = cur_tex++;
+ }
+ }
+ unbind();
+ }
+
return success;
}
@@ -293,7 +329,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
{
- if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB)
+ if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB ||
+ type == GL_SAMPLER_2D_MULTISAMPLE)
{ //this here is a texture
glUniform1iARB(location, mActiveTextureChannels);
LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
@@ -342,7 +379,7 @@ void LLGLSLShader::bind()
if (gGLManager.mHasShaderObjects)
{
glUseProgramObjectARB(mProgramObject);
-
+ sCurBoundShader = mProgramObject;
if (mUniformsDirty)
{
LLShaderMgr::instance()->updateShaderUniforms(this);
@@ -365,6 +402,7 @@ void LLGLSLShader::unbind()
}
}
glUseProgramObjectARB(0);
+ sCurBoundShader = 0;
stop_glerror();
}
}
@@ -372,6 +410,7 @@ void LLGLSLShader::unbind()
void LLGLSLShader::bindNoShader(void)
{
glUseProgramObjectARB(0);
+ sCurBoundShader = 0;
}
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index d46ddbbe18..4922eb6d67 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -45,6 +45,8 @@ public:
bool hasObjectSkinning;
bool hasAtmospherics;
bool hasGamma;
+ S32 mIndexedTextureChannels;
+ bool disableTextureIndex;
// char numLights;
@@ -64,6 +66,8 @@ public:
LLGLSLShader();
+ static GLhandleARB sCurBoundShader;
+
void unload();
BOOL createShader(std::vector<std::string> * attributes,
std::vector<std::string> * uniforms);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index d408077c68..60a5962234 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1083,12 +1083,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
}
// static
-void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
+void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
{
for (S32 i = 0; i < numTextures; i++)
{
sDeadTextureList.push_back(textures[i]);
}
+
+ if (immediate)
+ {
+ LLImageGL::deleteDeadTextures();
+ }
}
// static
@@ -1413,11 +1418,13 @@ void LLImageGL::deleteDeadTextures()
{
GLuint tex = sDeadTextureList.front();
sDeadTextureList.pop_front();
- for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
+ for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++)
{
- if (sCurrentBoundTextures[i] == tex)
+ LLTexUnit* tex_unit = gGL.getTexUnit(i);
+
+ if (tex_unit->getCurrTexture() == tex)
{
- gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
+ tex_unit->unbind(tex_unit->getCurrType());
stop_glerror();
}
}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 6c980984c0..2cfb15b0d9 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -98,7 +98,7 @@ public:
// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()
// for tracking purposes and will be deprecated in the future
static void generateTextures(S32 numTextures, U32 *textures);
- static void deleteTextures(S32 numTextures, U32 *textures);
+ static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels);
BOOL createGLTexture() ;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 49e10c4790..1d82dda30f 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -30,6 +30,7 @@
#include "llvertexbuffer.h"
#include "llcubemap.h"
+#include "llglslshader.h"
#include "llimagegl.h"
#include "llrendertarget.h"
#include "lltexture.h"
@@ -46,14 +47,15 @@ S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
U32 LLRender::sUIVerts = 0;
-static const U32 LL_NUM_TEXTURE_LAYERS = 16;
+static const U32 LL_NUM_TEXTURE_LAYERS = 32;
static const U32 LL_NUM_LIGHT_UNITS = 8;
static GLenum sGLTextureType[] =
{
GL_TEXTURE_2D,
GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_CUBE_MAP_ARB
+ GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_2D_MULTISAMPLE
};
static GLint sGLAddressMode[] =
@@ -119,14 +121,29 @@ void LLTexUnit::refreshState(void)
gGL.flush();
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+
+ //
+ // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
+ // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
+ //
+ bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
+
if (mCurrTexType != TT_NONE)
{
- glEnable(sGLTextureType[mCurrTexType]);
+ if (enableDisable)
+ {
+ glEnable(sGLTextureType[mCurrTexType]);
+ }
+
glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
}
else
{
- glDisable(GL_TEXTURE_2D);
+ if (enableDisable)
+ {
+ glDisable(GL_TEXTURE_2D);
+ }
+
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -167,7 +184,11 @@ void LLTexUnit::enable(eTextureType type)
mCurrTexType = type;
gGL.flush();
- glEnable(sGLTextureType[type]);
+ if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ mIndex < gGLManager.mNumTextureUnits)
+ {
+ glEnable(sGLTextureType[type]);
+ }
}
}
@@ -180,7 +201,12 @@ void LLTexUnit::disable(void)
activate();
unbind(mCurrTexType);
gGL.flush();
- glDisable(sGLTextureType[mCurrTexType]);
+ if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ mIndex < gGLManager.mNumTextureUnits)
+ {
+ glDisable(sGLTextureType[mCurrTexType]);
+ }
+
mCurrTexType = TT_NONE;
}
}
@@ -378,6 +404,7 @@ void LLTexUnit::unbind(eTextureType type)
activate();
mCurrTexture = 0;
glBindTexture(sGLTextureType[type], 0);
+ stop_glerror();
}
}
@@ -399,7 +426,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
- if (mIndex < 0 || mCurrTexture == 0) return;
+ if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
gGL.flush();
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 7ba14f7b40..41e7b35341 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -57,6 +57,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
+ TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_NONE // No texture type is currently enabled
} eTextureType;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index cd2556d435..b6463309e1 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -44,6 +44,7 @@ void check_framebuffer_status()
case GL_FRAMEBUFFER_COMPLETE:
break;
default:
+ llwarns << "check_framebuffer_status failed -- " << std::hex << status << llendl;
ll_fail("check_framebuffer_status failed");
break;
}
@@ -62,8 +63,7 @@ LLRenderTarget::LLRenderTarget() :
mUseDepth(false),
mRenderDepth(false),
mUsage(LLTexUnit::TT_TEXTURE),
- mSamples(0),
- mSampleBuffer(NULL)
+ mSamples(0)
{
}
@@ -72,23 +72,32 @@ LLRenderTarget::~LLRenderTarget()
release();
}
-
-void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
-{
- mSampleBuffer = buffer;
-}
-
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo)
+void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
stop_glerror();
+
+ release();
+
mResX = resx;
mResY = resy;
mStencil = stencil;
mUsage = usage;
mUseDepth = depth;
+ mSamples = samples;
- release();
+ mSamples = gGLManager.getNumFBOFSAASamples(mSamples);
+
+ if (mSamples > 1 && gGLManager.mHasTextureMultisample)
+ {
+ mUsage = LLTexUnit::TT_MULTISAMPLE_TEXTURE;
+ //no support for multisampled stencil targets yet
+ mStencil = false;
+ }
+ else
+ {
+ mSamples = 0;
+ }
if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
{
@@ -145,29 +154,51 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
stop_glerror();
- LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- stop_glerror();
- if (offset == 0)
+#ifdef GL_ARB_texture_multisample
+ if (mSamples > 1)
{
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
}
else
- { //don't filter data attachments
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
- if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
+#else
+ llassert_always(mSamples <= 1);
+#endif
{
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
- else
- {
- // ATI doesn't support mirrored repeat for rectangular textures.
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+
+ stop_glerror();
+
+ if (mSamples == 0)
+ {
+ if (offset == 0)
+ { //use bilinear filtering on single texture render targets that aren't multisampled
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ stop_glerror();
+ }
+ else
+ { //don't filter data attachments
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ stop_glerror();
+ }
+
+ if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
+ {
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
+ stop_glerror();
+ }
+ else
+ {
+ // ATI doesn't support mirrored repeat for rectangular textures.
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+ }
}
+
if (mFBO)
{
+ stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
LLTexUnit::getInternalType(mUsage), tex, 0);
@@ -180,6 +211,12 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
mTex.push_back(tex);
+ if (gDebugGL)
+ { //bind and unbind to validate target
+ bindTarget();
+ flush();
+ }
+
}
void LLRenderTarget::allocateDepth()
@@ -196,9 +233,20 @@ void LLRenderTarget::allocateDepth()
{
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
- U32 internal_type = LLTexUnit::getInternalType(mUsage);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ if (mSamples == 0)
+ {
+ U32 internal_type = LLTexUnit::getInternalType(mUsage);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ }
+#ifdef GL_ARB_texture_multisample
+ else
+ {
+ glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
+ }
+#else
+ llassert_always(mSamples <= 1);
+#endif
}
}
@@ -238,6 +286,9 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
stop_glerror();
}
+
+ check_framebuffer_status();
+
glBindFramebuffer(GL_FRAMEBUFFER, 0);
target.mUseDepth = true;
@@ -255,7 +306,7 @@ void LLRenderTarget::release()
}
else
{
- LLImageGL::deleteTextures(1, &mDepth);
+ LLImageGL::deleteTextures(1, &mDepth, true);
stop_glerror();
}
mDepth = 0;
@@ -284,11 +335,12 @@ void LLRenderTarget::release()
if (mTex.size() > 0)
{
- LLImageGL::deleteTextures(mTex.size(), &mTex[0]);
+ LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
mTex.clear();
}
+
+ mResX = mResY = 0;
- mSampleBuffer = NULL;
sBoundTarget = NULL;
}
@@ -297,34 +349,27 @@ void LLRenderTarget::bindTarget()
if (mFBO)
{
stop_glerror();
- if (mSampleBuffer)
- {
- mSampleBuffer->bindTarget(this);
- stop_glerror();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ stop_glerror();
+ if (gGLManager.mHasDrawBuffers)
+ { //setup multiple render targets
+ GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1,
+ GL_COLOR_ATTACHMENT2,
+ GL_COLOR_ATTACHMENT3};
+ glDrawBuffersARB(mTex.size(), drawbuffers);
}
- else
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- stop_glerror();
- if (gGLManager.mHasDrawBuffers)
- { //setup multiple render targets
- GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
- GL_COLOR_ATTACHMENT1,
- GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3};
- glDrawBuffersARB(mTex.size(), drawbuffers);
- }
- if (mTex.empty())
- { //no color buffer to draw to
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
+ if (mTex.empty())
+ { //no color buffer to draw to
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
- check_framebuffer_status();
+ check_framebuffer_status();
- stop_glerror();
- }
+ stop_glerror();
}
glViewport(0, 0, mResX, mResY);
@@ -406,50 +451,8 @@ void LLRenderTarget::flush(bool fetch_depth)
else
{
stop_glerror();
-
glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
stop_glerror();
-
- if (mSampleBuffer)
- {
- LLGLEnable multisample(GL_MULTISAMPLE);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- stop_glerror();
- check_framebuffer_status();
- glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO);
- check_framebuffer_status();
-
- stop_glerror();
- glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
- stop_glerror();
-
- if (mTex.size() > 1)
- {
- for (U32 i = 1; i < mTex.size(); ++i)
- {
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- LLTexUnit::getInternalType(mUsage), mTex[i], 0);
- stop_glerror();
- glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
- stop_glerror();
- glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);
- stop_glerror();
- }
-
- for (U32 i = 0; i < mTex.size(); ++i)
- {
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
- LLTexUnit::getInternalType(mUsage), mTex[i], 0);
- stop_glerror();
- glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
- stop_glerror();
- }
- }
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
@@ -466,37 +469,36 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
}
- if (mSampleBuffer)
+
+ if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
{
- mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ stop_glerror();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
+ check_framebuffer_status();
+ gGL.getTexUnit(0)->bind(this, true);
+ stop_glerror();
+ glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
+ stop_glerror();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ stop_glerror();
}
else
{
- if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
- {
- stop_glerror();
-
- glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
- gGL.getTexUnit(0)->bind(this, true);
- stop_glerror();
- glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- stop_glerror();
- }
- else
- {
- glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
- stop_glerror();
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
- stop_glerror();
- check_framebuffer_status();
- stop_glerror();
- glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- stop_glerror();
- }
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
+ stop_glerror();
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
+ stop_glerror();
+ check_framebuffer_status();
+ stop_glerror();
+ glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ stop_glerror();
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
+ stop_glerror();
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ stop_glerror();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ stop_glerror();
}
}
@@ -539,179 +541,3 @@ void LLRenderTarget::getViewport(S32* viewport)
viewport[3] = mResY;
}
-//==================================================
-// LLMultisampleBuffer implementation
-//==================================================
-LLMultisampleBuffer::LLMultisampleBuffer()
-{
-
-}
-
-LLMultisampleBuffer::~LLMultisampleBuffer()
-{
- release();
-}
-
-void LLMultisampleBuffer::release()
-{
- if (mFBO)
- {
- glDeleteFramebuffers(1, (GLuint *) &mFBO);
- mFBO = 0;
- }
-
- if (mTex.size() > 0)
- {
- glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]);
- mTex.clear();
- }
-
- if (mDepth)
- {
- glDeleteRenderbuffers(1, (GLuint *) &mDepth);
- mDepth = 0;
- }
-}
-
-void LLMultisampleBuffer::bindTarget()
-{
- bindTarget(this);
-}
-
-void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
-{
- if (!ref)
- {
- ref = this;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- if (gGLManager.mHasDrawBuffers)
- { //setup multiple render targets
- GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
- GL_COLOR_ATTACHMENT1,
- GL_COLOR_ATTACHMENT2,
- GL_COLOR_ATTACHMENT3};
- glDrawBuffersARB(ref->mTex.size(), drawbuffers);
- }
-
- check_framebuffer_status();
-
- glViewport(0, 0, mResX, mResY);
-
- sBoundTarget = this;
-}
-
-void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo )
-{
- allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2);
-}
-
-void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples )
-{
- stop_glerror();
- mResX = resx;
- mResY = resy;
-
- mUsage = usage;
- mUseDepth = depth;
- mStencil = stencil;
-
- release();
-
- mSamples = samples;
-
- if (mSamples <= 1)
- {
- llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl;
- }
-
- stop_glerror();
-
- if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
- {
-
- if (depth)
- {
- stop_glerror();
- allocateDepth();
- stop_glerror();
- }
-
- glGenFramebuffers(1, (GLuint *) &mFBO);
-
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-
- if (mDepth)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- if (mStencil)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
- }
- }
-
- stop_glerror();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- stop_glerror();
- }
-
- addColorAttachment(color_fmt);
-}
-
-void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
-{
- if (color_fmt == 0)
- {
- return;
- }
-
- U32 offset = mTex.size();
- if (offset >= 4 ||
- (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)))
- {
- llerrs << "Too many color attachments!" << llendl;
- }
-
- U32 tex;
- glGenRenderbuffers(1, &tex);
-
- glBindRenderbuffer(GL_RENDERBUFFER, tex);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY);
- stop_glerror();
-
- if (mFBO)
- {
- glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex);
- stop_glerror();
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- switch (status)
- {
- case GL_FRAMEBUFFER_COMPLETE:
- break;
- default:
- llerrs << "WTF? " << std::hex << status << llendl;
- break;
- }
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- }
-
- mTex.push_back(tex);
-}
-
-void LLMultisampleBuffer::allocateDepth()
-{
- glGenRenderbuffers(1, (GLuint* ) &mDepth);
- glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
- if (mStencil)
- {
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);
- }
- else
- {
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16, mResX, mResY);
- }
-}
-
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 12dd1c8b90..094b58b562 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -71,10 +71,7 @@ public:
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
- void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE);
-
- //provide this render target with a multisample resource.
- void setSampleBuffer(LLMultisampleBuffer* buffer);
+ void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
//add color buffer attachment
//limit of 4 color attachments per render target
@@ -141,7 +138,6 @@ public:
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
protected:
- friend class LLMultisampleBuffer;
U32 mResX;
U32 mResY;
std::vector<U32> mTex;
@@ -152,26 +148,8 @@ protected:
bool mRenderDepth;
LLTexUnit::eTextureType mUsage;
U32 mSamples;
- LLMultisampleBuffer* mSampleBuffer;
-
- static LLRenderTarget* sBoundTarget;
-};
-
-class LLMultisampleBuffer : public LLRenderTarget
-{
-public:
- LLMultisampleBuffer();
- virtual ~LLMultisampleBuffer();
-
- virtual void release();
-
- virtual void bindTarget();
- void bindTarget(LLRenderTarget* ref);
- virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo);
- void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples);
- virtual void addColorAttachment(U32 color_fmt);
- virtual void allocateDepth();
+ static LLRenderTarget* sBoundTarget;
};
#endif //!LL_MESA_HEADLESS
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 98a0a93084..751b250d96 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -209,17 +209,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
- if (!shader->attachObject("lighting/lightF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -230,32 +252,76 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->isShiny && features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else if (features->isShiny)
{
- if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
- if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -266,17 +332,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
- if (!shader->attachObject("lighting/lightShinyF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightShinyF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -315,12 +403,12 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
else
{
- LL_INFOS("ShaderLoading") << log << LL_ENDL;
+ LL_DEBUGS("ShaderLoading") << log << LL_ENDL;
}
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
{
GLenum error = GL_NO_ERROR;
if (gDebugGL)
@@ -374,6 +462,117 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
GLcharARB* text[1024];
GLuint count = 0;
+ if (gGLManager.mGLVersion < 2.1f)
+ {
+ text[count++] = strdup("#version 110\n");
+ }
+ else if (gGLManager.mGLVersion < 3.f)
+ {
+ //set version to 1.20
+ text[count++] = strdup("#version 120\n");
+ }
+ else
+ { //set version to 1.30
+ text[count++] = strdup("#version 130\n");
+ }
+
+ //copy preprocessor definitions into buffer
+ for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
+ {
+ std::string define = "#define " + iter->first + " " + iter->second + "\n";
+ text[count++] = (GLcharARB *) strdup(define.c_str());
+ }
+
+ if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
+ {
+ //use specified number of texture channels for indexed texture rendering
+
+ /* prepend shader code that looks like this:
+
+ uniform sampler2D tex0;
+ uniform sampler2D tex1;
+ uniform sampler2D tex2;
+ .
+ .
+ .
+ uniform sampler2D texN;
+
+ varying float vary_texture_index;
+
+ vec4 diffuseLookup(vec2 texcoord)
+ {
+ switch (int(vary_texture_index+0.25))
+ {
+ case 0: return texture2D(tex0, texcoord);
+ case 1: return texture2D(tex1, texcoord);
+ case 2: return texture2D(tex2, texcoord);
+ .
+ .
+ .
+ case N: return texture2D(texN, texcoord);
+ }
+
+ return vec4(0,0,0,0);
+ }
+ */
+
+ //uniform declartion
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string decl = llformat("uniform sampler2D tex%d;\n", i);
+ text[count++] = strdup(decl.c_str());
+ }
+
+ text[count++] = strdup("varying float vary_texture_index;\n");
+ text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
+ text[count++] = strdup("{\n");
+
+
+ if (texture_index_channels == 1)
+ { //don't use flow control, that's silly
+ text[count++] = strdup("return texture2D(tex0, texcoord);\n");
+ text[count++] = strdup("}\n");
+ }
+ else if (gGLManager.mGLVersion >= 3.f)
+ {
+ text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
+ text[count++] = strdup("\t{\n");
+
+ //switch body
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i);
+ text[count++] = strdup(case_str.c_str());
+ }
+
+ text[count++] = strdup("\t}\n");
+ text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
+ text[count++] = strdup("}\n");
+ }
+ else
+ {
+ //switches aren't supported, make block that looks like:
+ /*
+ int ti = int(vary_texture_index+0.25);
+ if (ti == 0) return texture2D(tex0, texcoord);
+ if (ti == 1) return texture2D(tex1, texcoord);
+ .
+ .
+ .
+ if (ti == N) return texture2D(texN, texcoord);
+ */
+
+ text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n");
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i);
+ text[count++] = strdup(if_str.c_str());
+ }
+
+ text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
+ text[count++] = strdup("}\n");
+ }
+ }
//copy file into memory
while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) )
@@ -417,11 +616,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
}
- //free memory
- for (GLuint i = 0; i < count; i++)
- {
- free(text[i]);
- }
if (error == GL_NO_ERROR)
{
//check for errors
@@ -435,6 +629,16 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//an error occured, print log
LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL;
dumpObjectLog(ret);
+
+ std::stringstream ostr;
+ //dump shader source for debugging
+ for (GLuint i = 0; i < count; i++)
+ {
+ ostr << i << ": " << text[i];
+ }
+
+ LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl;
+
ret = 0;
}
}
@@ -445,6 +649,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
stop_glerror();
+ //free memory
+ for (GLuint i = 0; i < count; i++)
+ {
+ free(text[i]);
+ }
+
//successfully loaded, save results
if (ret)
{
@@ -457,7 +667,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (shader_level > 1)
{
shader_level--;
- return loadShaderFile(filename,shader_level,type);
+ return loadShaderFile(filename,shader_level,type,texture_index_channels);
}
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
}
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index c54c4608d7..2f30103811 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -43,7 +43,7 @@ public:
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type);
+ GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
@@ -60,6 +60,9 @@ public:
std::vector<std::string> mReservedUniforms;
+ //preprocessor definitions (name/value)
+ std::map<std::string, std::string> mDefinitions;
+
protected:
// our parameter manager singleton instance
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 8c9171ccf4..4a0b964e61 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -934,8 +934,26 @@ void LLVertexBuffer::allocateClientIndexBuffer()
}
}
+bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
+{
+ S32 end = index+count;
+ S32 region_end = region.mIndex+region.mCount;
+
+ if (end < region.mIndex ||
+ index > region_end)
+ { //gap exists, do not merge
+ return false;
+ }
+
+ S32 new_end = llmax(end, region_end);
+ S32 new_index = llmin(index, region.mIndex);
+ region.mIndex = new_index;
+ region.mCount = new_end-new_index;
+ return true;
+}
+
// Map for data access
-U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
+U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
@@ -947,8 +965,45 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
}
- if (!mVertexLocked && useVBOs())
+ if (useVBOs())
{
+
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ {
+ if (count == -1)
+ {
+ count = mNumVerts-index;
+ }
+
+ bool mapped = false;
+ //see if range is already mapped
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedVertexRegions[i];
+ if (region.mType == type)
+ {
+ if (expand_region(region, index, count))
+ {
+ mapped = true;
+ break;
+ }
+ }
+ }
+
+ if (!mapped)
+ {
+ //not already mapped, map new region
+ MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count);
+ mMappedVertexRegions.push_back(region);
+ }
+ }
+
+ if (mVertexLocked && map_range)
+ {
+ llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
+ }
+
+ if (!mVertexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
setBuffer(0, type);
@@ -957,61 +1012,95 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
if(sDisableVBOMapping)
{
+ map_range = false;
allocateClientVertexBuffer() ;
}
else
{
- U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (map_range)
+ {
+ S32 offset = mOffsets[type] + sTypeSize[type]*index;
+ S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+ }
+ else
+ {
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ }
+ }
+ else
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+ {
+ map_range = false;
+ src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+
mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedOffset = mMappedData - src;
stop_glerror();
}
- }
-
-
- if (!mMappedData)
- {
- log_glerror();
-
- //check the availability of memory
- U32 avail_phy_mem, avail_vir_mem;
- LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
- llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
- llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
-
- if(!sDisableVBOMapping)
- {
- //--------------------
- //print out more debug info before crash
- llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
- GLint size ;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
- llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
- //--------------------
+
+ if (!mMappedData)
+ {
+ log_glerror();
+
+ //check the availability of memory
+ U32 avail_phy_mem, avail_vir_mem;
+ LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
+ llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
+ llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
+
+ if(!sDisableVBOMapping)
+ {
+ //--------------------
+ //print out more debug info before crash
+ llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
+ GLint size ;
+ glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
+ llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
+ //--------------------
+
+ GLint buff;
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
+ if ((GLuint)buff != mGLBuffer)
+ {
+ llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ }
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
+
+ llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
+ }
+ else
{
- llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
+ llerrs << "memory allocation for vertex data failed." << llendl ;
}
-
-
- llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
- }
- else
- {
- llerrs << "memory allocation for vertex data failed." << llendl ;
}
+ sMappedCount++;
}
- sMappedCount++;
+ }
+ else
+ {
+ map_range = false;
}
- return mMappedData;
+ if (map_range && !sDisableVBOMapping)
+ {
+ return mMappedData;
+ }
+ else
+ {
+ return mMappedData+mOffsets[type]+sTypeSize[type]*index;
+ }
}
-U8* LLVertexBuffer::mapIndexBuffer(S32 access)
+U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
@@ -1023,8 +1112,41 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
}
- if (!mIndexLocked && useVBOs())
+ if (useVBOs())
{
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ {
+ if (count == -1)
+ {
+ count = mNumIndices-index;
+ }
+
+ bool mapped = false;
+ //see if range is already mapped
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedIndexRegions[i];
+ if (expand_region(region, index, count))
+ {
+ mapped = true;
+ break;
+ }
+ }
+
+ if (!mapped)
+ {
+ //not already mapped, map new region
+ MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count);
+ mMappedIndexRegions.push_back(region);
+ }
+ }
+
+ if (mIndexLocked && map_range)
+ {
+ llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
+ }
+
+ if (!mIndexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
@@ -1034,12 +1156,36 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
if(sDisableVBOMapping)
{
+ map_range = false;
allocateClientIndexBuffer() ;
}
else
{
- U8* src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
+ U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (map_range)
+ {
+ S32 offset = sizeof(U16)*index;
+ S32 length = sizeof(U16)*count;
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+ }
+ else
+ {
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ }
+ }
+ else
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+ {
+ map_range = false;
+ src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+
+ mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedIndexOffset = mMappedIndexData - src;
stop_glerror();
}
@@ -1068,31 +1214,81 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
sMappedCount++;
}
+ else
+ {
+ map_range = false;
+ }
- return mMappedIndexData ;
+ if (map_range && !sDisableVBOMapping)
+ {
+ return mMappedIndexData;
+ }
+ else
+ {
+ return mMappedIndexData + sizeof(U16)*index;
+ }
}
void LLVertexBuffer::unmapBuffer(S32 type)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
- if (!useVBOs())
+ if (!useVBOs() || type == -2)
{
return ; //nothing to unmap
}
bool updated_all = false ;
+
if (mMappedData && mVertexLocked && type != TYPE_INDEX)
{
updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating
if(sDisableVBOMapping)
{
- stop_glerror();
- glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
- stop_glerror();
+ if (!mMappedVertexRegions.empty())
+ {
+ stop_glerror();
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedVertexRegions[i];
+ S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+ S32 length = sTypeSize[region.mType]*region.mCount;
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset);
+ stop_glerror();
+ }
+
+ mMappedVertexRegions.clear();
+ }
+ else
+ {
+ stop_glerror();
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
+ stop_glerror();
+ }
}
else
{
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (!mMappedVertexRegions.empty())
+ {
+ stop_glerror();
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedVertexRegions[i];
+ S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+ S32 length = sTypeSize[region.mType]*region.mCount;
+ glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+ stop_glerror();
+ }
+
+ mMappedVertexRegions.clear();
+ }
+ }
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1103,17 +1299,53 @@ void LLVertexBuffer::unmapBuffer(S32 type)
mVertexLocked = FALSE ;
sMappedCount--;
}
-
- if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
+
+ if (mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
{
if(sDisableVBOMapping)
{
- stop_glerror();
- glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
- stop_glerror();
+ if (!mMappedIndexRegions.empty())
+ {
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedIndexRegions[i];
+ S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+ S32 length = sizeof(U16)*region.mCount;
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset);
+ stop_glerror();
+ }
+
+ mMappedIndexRegions.clear();
+ }
+ else
+ {
+ stop_glerror();
+ glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
+ stop_glerror();
+ }
}
else
{
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (!mMappedIndexRegions.empty())
+ {
+ for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedIndexRegions[i];
+ S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+ S32 length = sizeof(U16)*region.mCount;
+ glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+ stop_glerror();
+ }
+
+ mMappedIndexRegions.clear();
+ }
+ }
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
stop_glerror();
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1152,19 +1384,19 @@ template <class T,S32 type> struct VertexBufferStrider
typedef LLStrider<T> strider_t;
static bool get(LLVertexBuffer& vbo,
strider_t& strider,
- S32 index)
+ S32 index, S32 count, bool map_range)
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
- S32 stride = sizeof(T);
+ U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
- if (vbo.mapIndexBuffer() == NULL)
+ if (ptr == NULL)
{
llwarns << "mapIndexBuffer failed!" << llendl;
return FALSE;
}
- strider = (T*)(vbo.getMappedIndices() + index*stride);
+ strider = (T*)ptr;
strider.setStride(0);
return TRUE;
}
@@ -1172,13 +1404,15 @@ template <class T,S32 type> struct VertexBufferStrider
{
S32 stride = LLVertexBuffer::sTypeSize[type];
- if (vbo.mapVertexBuffer(type) == NULL)
+ U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+
+ if (ptr == NULL)
{
llwarns << "mapVertexBuffer failed!" << llendl;
return FALSE;
}
- strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride);
+ strider = (T*)ptr;
strider.setStride(stride);
return TRUE;
}
@@ -1190,55 +1424,48 @@ template <class T,S32 type> struct VertexBufferStrider
}
};
-bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
-{
- return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
-}
-bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index)
+bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index)
+bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index);
+ return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index)
+bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
}
-/*bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
+bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index)
-{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index);
-}*/
-bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index)
+
+bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index)
+bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index)
+bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index);
+ return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
+bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
+ return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index)
+bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
}
-bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
+bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
{
- return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
+ return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
}
//----------------------------------------------------------------------------
@@ -1497,17 +1724,16 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
}
if (data_mask & MAP_VERTEX)
{
- glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+ if (data_mask & MAP_TEXTURE_INDEX)
+ {
+ glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+ }
+ else
+ {
+ glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
+ }
}
llglassertok();
}
-void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
-{
- // TODO: use GL_APPLE_flush_buffer_range here
- /*if (useVBOs() && !mFilthy)
- {
-
- }*/
-}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index a9f22193f8..aa5df305a6 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -77,6 +77,18 @@ protected:
class LLVertexBuffer : public LLRefCount
{
public:
+ class MappedRegion
+ {
+ public:
+ S32 mType;
+ S32 mIndex;
+ S32 mCount;
+
+ MappedRegion(S32 type, S32 index, S32 count)
+ : mType(type), mIndex(index), mCount(count)
+ { }
+ };
+
LLVertexBuffer(const LLVertexBuffer& rhs)
{
*this = rhs;
@@ -130,6 +142,9 @@ public:
TYPE_CLOTHWEIGHT,
TYPE_MAX,
TYPE_INDEX,
+
+ //no actual additional data, but indicates position.w is texture index
+ TYPE_TEXTURE_INDEX,
};
enum {
MAP_VERTEX = (1<<TYPE_VERTEX),
@@ -144,6 +159,7 @@ public:
MAP_WEIGHT = (1<<TYPE_WEIGHT),
MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
+ MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX),
};
protected:
@@ -173,8 +189,8 @@ public:
LLVertexBuffer(U32 typemask, S32 usage);
// map for data access
- U8* mapVertexBuffer(S32 type = -1, S32 access = -1);
- U8* mapIndexBuffer(S32 access = -1);
+ U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
+ U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
// set for rendering
virtual void setBuffer(U32 data_mask, S32 type = -1); // calls setupVertexBuffer() if data_mask is not 0
@@ -189,16 +205,16 @@ public:
// vb->getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
- bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
- bool getIndexStrider(LLStrider<U16>& strider, S32 index=0);
- bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0);
- bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0);
- bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
- bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
- bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
- bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
- bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);
- bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
+ bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+ bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
BOOL isEmpty() const { return mEmpty; }
BOOL isLocked() const { return mVertexLocked || mIndexLocked; }
@@ -218,8 +234,6 @@ public:
S32 getOffset(S32 type) const { return mOffsets[type]; }
S32 getUsage() const { return mUsage; }
- void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
-
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
@@ -253,20 +267,8 @@ protected:
BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
S32 mOffsets[TYPE_MAX];
- class DirtyRegion
- {
- public:
- U32 mIndex;
- U32 mCount;
- U32 mIndicesIndex;
- U32 mIndicesCount;
-
- DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic)
- : mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic)
- { }
- };
-
- std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild
+ std::vector<MappedRegion> mMappedVertexRegions;
+ std::vector<MappedRegion> mMappedIndexRegions;
public:
static S32 sCount;
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 684e393cba..0bbdcfd6ff 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -28,6 +28,8 @@ include_directories(
set(llui_SOURCE_FILES
llaccordionctrl.cpp
llaccordionctrltab.cpp
+ llbadge.cpp
+ llbadgeowner.cpp
llbutton.cpp
llcheckboxctrl.cpp
llclipboard.cpp
@@ -93,6 +95,7 @@ set(llui_SOURCE_FILES
lltextparser.cpp
lltextutil.cpp
lltextvalidate.cpp
+ lltimectrl.cpp
lltransutil.cpp
lltoggleablemenu.cpp
lltooltip.cpp
@@ -119,6 +122,8 @@ set(llui_HEADER_FILES
llaccordionctrl.h
llaccordionctrltab.h
+ llbadge.h
+ llbadgeowner.h
llbutton.h
llcallbackmap.h
llcheckboxctrl.h
@@ -191,6 +196,7 @@ set(llui_HEADER_FILES
lltextparser.h
lltextutil.h
lltextvalidate.h
+ lltimectrl.h
lltoggleablemenu.h
lltooltip.h
lltransutil.h
@@ -245,11 +251,11 @@ target_link_libraries(llui
)
# Add tests
-if (LL_TESTS)
- include(LLAddBuildTest)
- SET(llui_TEST_SOURCE_FILES
- llurlmatch.cpp
- llurlentry.cpp
- )
- LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
-endif (LL_TESTS) \ No newline at end of file
+if(LL_TESTS)
+ include(LLAddBuildTest)
+ SET(llui_TEST_SOURCE_FILES
+ llurlmatch.cpp
+ llurlentry.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
+endif(LL_TESTS)
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 9e4849c58b..6afe276379 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -1022,7 +1022,7 @@ void LLAccordionCtrlTab::updateLayout ( const LLRect& child_rect )
S32 panel_width = child_rect.getWidth();
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
- if(mScrollbar->getVisible() != false)
+ if(mScrollbar && mScrollbar->getVisible() != false)
{
panel_top+=mScrollbar->getDocPos();
panel_width-=scrollbar_size;
diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp
new file mode 100644
index 0000000000..c28a947a7f
--- /dev/null
+++ b/indra/llui/llbadge.cpp
@@ -0,0 +1,274 @@
+/**
+ * @file llbadge.cpp
+ * @brief Implementation for badges
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#define LLBADGE_CPP
+#include "llbadge.h"
+
+#include "lluictrlfactory.h"
+
+
+static LLDefaultChildRegistry::Register<LLBadge> r("badge");
+
+// Compiler optimization, generate extern template
+template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+
+
+LLBadge::Params::Params()
+ : image("image")
+ , border_image("border_image")
+ , border_color("border_color")
+ , image_color("image_color")
+ , label("label")
+ , label_color("label_color")
+ , location("location", LLRelPos::TOP_LEFT)
+ , location_percent_hcenter("location_percent_hcenter")
+ , location_percent_vcenter("location_percent_vcenter")
+ , padding_horiz("padding_horiz")
+ , padding_vert("padding_vert")
+{
+ // We set a name here so the name isn't necessary in any xml files that use badges
+ name = "badge";
+}
+
+bool LLBadge::Params::equals(const Params& a) const
+{
+ bool comp = true;
+
+ // skip owner in comparison on purpose
+
+ comp &= (border_image() == a.border_image());
+ comp &= (border_color() == a.border_color());
+ comp &= (image() == a.image());
+ comp &= (image_color() == a.image_color());
+ comp &= (label() == a.label());
+ comp &= (label_color() == a.label_color());
+ comp &= (location() == a.location());
+ comp &= (location_percent_hcenter() == a.location_percent_hcenter());
+ comp &= (location_percent_vcenter() == a.location_percent_vcenter());
+ comp &= (padding_horiz() == a.padding_horiz());
+ comp &= (padding_vert() == a.padding_vert());
+
+ return comp;
+}
+
+LLBadge::LLBadge(const LLBadge::Params& p)
+ : LLUICtrl(p)
+ , mOwner(p.owner)
+ , mBorderImage(p.border_image)
+ , mBorderColor(p.border_color)
+ , mGLFont(p.font)
+ , mImage(p.image)
+ , mImageColor(p.image_color)
+ , mLabel(p.label)
+ , mLabelColor(p.label_color)
+ , mLocation(p.location)
+ , mLocationPercentHCenter(0.5f)
+ , mLocationPercentVCenter(0.5f)
+ , mPaddingHoriz(p.padding_horiz)
+ , mPaddingVert(p.padding_vert)
+{
+ if (mImage.isNull())
+ {
+ llwarns << "Badge: " << getName() << " with no image!" << llendl;
+ }
+
+ //
+ // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter
+ // based on the Location enum and our horizontal and vertical location percentages. The
+ // draw code then uses this on the owner rectangle to compute the screen location for
+ // the badge.
+ //
+
+ if (!LLRelPos::IsCenter(mLocation))
+ {
+ F32 h_center = p.location_percent_hcenter * 0.01f;
+ F32 v_center = p.location_percent_vcenter * 0.01f;
+
+ if (LLRelPos::IsRight(mLocation))
+ {
+ mLocationPercentHCenter = 0.5f * (1.0f + h_center);
+ }
+ else if (LLRelPos::IsLeft(mLocation))
+ {
+ mLocationPercentHCenter = 0.5f * (1.0f - h_center);
+ }
+
+ if (LLRelPos::IsTop(mLocation))
+ {
+ mLocationPercentVCenter = 0.5f * (1.0f + v_center);
+ }
+ else if (LLRelPos::IsBottom(mLocation))
+ {
+ mLocationPercentVCenter = 0.5f * (1.0f - v_center);
+ }
+ }
+}
+
+LLBadge::~LLBadge()
+{
+}
+
+void LLBadge::setLabel(const LLStringExplicit& label)
+{
+ mLabel = label;
+}
+
+//
+// This is a fallback function to render a rectangle for badges without a valid image
+//
+void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color)
+{
+ gGL.pushUIMatrix();
+ gGL.loadUIIdentity();
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4ubv(color.mV);
+ gGL.texCoord2i(0, 0);
+
+ F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f;
+ F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f;
+
+ LLRectf screen_rect(llround(x),
+ llround(y),
+ llround(x) + width,
+ llround(y) + height);
+
+ LLVector3 vertices[4];
+ vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
+ vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
+ vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
+ vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
+
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, 4);
+ }
+ gGL.end();
+
+ gGL.popUIMatrix();
+}
+
+
+// virtual
+void LLBadge::draw()
+{
+ if (!mLabel.empty())
+ {
+ LLView* owner_view = mOwner.get();
+
+ if (owner_view)
+ {
+ //
+ // Calculate badge position based on owner
+ //
+
+ LLRect owner_rect;
+ owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this);
+
+ F32 badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter;
+ F32 badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter;
+
+ //
+ // Calculate badge size based on label text
+ //
+
+ LLWString badge_label_wstring = mLabel;
+
+ S32 badge_label_begin_offset = 0;
+ S32 badge_char_length = S32_MAX;
+ S32 badge_pixel_length = S32_MAX;
+ F32 *right_position_out = NULL;
+ BOOL do_not_use_ellipses = false;
+
+ F32 badge_width = (2.0f * mPaddingHoriz) +
+ mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length);
+
+ F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight();
+
+ //
+ // Draw button image, if available.
+ // Otherwise draw basic rectangular button.
+ //
+
+ F32 alpha = getDrawContext().mAlpha;
+
+ if (!mImage.isNull())
+ {
+ F32 badge_x = badge_center_x - badge_width * 0.5f;
+ F32 badge_y = badge_center_y - badge_height * 0.5f;
+
+ mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha);
+
+ if (!mBorderImage.isNull())
+ {
+ mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha);
+ }
+ }
+ else
+ {
+ lldebugs << "No image for badge " << getName() << " on owner " << owner_view->getName() << llendl;
+
+ renderBadgeBackground(badge_center_x, badge_center_y,
+ badge_width, badge_height,
+ mImageColor % alpha);
+ }
+
+ //
+ // Draw the label
+ //
+
+ mGLFont->render(badge_label_wstring, badge_label_begin_offset,
+ badge_center_x, badge_center_y,
+ mLabelColor % alpha,
+ LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
+ LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
+ LLFontGL::DROP_SHADOW_SOFT,
+ badge_char_length, badge_pixel_length,
+ right_position_out, do_not_use_ellipses);
+ }
+ }
+}
+
+
+namespace LLInitParam
+{
+ void TypeValues<LLRelPos::Location>::declareValues()
+ {
+ declare("bottom", LLRelPos::BOTTOM);
+ declare("bottom_left", LLRelPos::BOTTOM_LEFT);
+ declare("bottom_right", LLRelPos::BOTTOM_RIGHT);
+ declare("center", LLRelPos::CENTER);
+ declare("left", LLRelPos::LEFT);
+ declare("right", LLRelPos::RIGHT);
+ declare("top", LLRelPos::TOP);
+ declare("top_left", LLRelPos::TOP_LEFT);
+ declare("top_right", LLRelPos::TOP_RIGHT);
+ }
+}
+
+
+// eof
diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h
new file mode 100644
index 0000000000..0f923ef01b
--- /dev/null
+++ b/indra/llui/llbadge.h
@@ -0,0 +1,159 @@
+/**
+ * @file llbadge.h
+ * @brief Header for badges
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLBADGE_H
+#define LL_LLBADGE_H
+
+#include <string>
+
+#include "lluicolor.h"
+#include "lluictrl.h"
+#include "llstring.h"
+#include "lluiimage.h"
+#include "llview.h"
+
+//
+// Declarations
+//
+
+class LLUICtrlFactory;
+class LLFontGL;
+
+//
+// Relative Position Alignment
+//
+
+namespace LLRelPos
+{
+ enum Location
+ {
+ CENTER = 0,
+
+ LEFT = (1 << 0),
+ RIGHT = (1 << 1),
+
+ TOP = (1 << 2),
+ BOTTOM = (1 << 3),
+
+ BOTTOM_LEFT = (BOTTOM | LEFT),
+ BOTTOM_RIGHT = (BOTTOM | RIGHT),
+
+ TOP_LEFT = (TOP | LEFT),
+ TOP_RIGHT = (TOP | RIGHT),
+ };
+
+ inline bool IsBottom(Location relPos) { return (relPos & BOTTOM) == BOTTOM; }
+ inline bool IsCenter(Location relPos) { return (relPos == CENTER); }
+ inline bool IsLeft(Location relPos) { return (relPos & LEFT) == LEFT; }
+ inline bool IsRight(Location relPos) { return (relPos & RIGHT) == RIGHT; }
+ inline bool IsTop(Location relPos) { return (relPos & TOP) == TOP; }
+}
+
+// NOTE: This needs to occur before Optional<LLRelPos::Location> declaration for proper compilation.
+namespace LLInitParam
+{
+ template<>
+ struct TypeValues<LLRelPos::Location> : public TypeValuesHelper<LLRelPos::Location>
+ {
+ static void declareValues();
+ };
+}
+
+//
+// Classes
+//
+
+class LLBadge
+: public LLUICtrl
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional< LLHandle<LLView> > owner; // Mandatory in code but not in xml
+
+ Optional< LLUIImage* > border_image;
+ Optional< LLUIColor > border_color;
+
+ Optional< LLUIImage* > image;
+ Optional< LLUIColor > image_color;
+
+ Optional< std::string > label;
+ Optional< LLUIColor > label_color;
+
+ Optional< LLRelPos::Location > location;
+ Optional< U32 > location_percent_hcenter;
+ Optional< U32 > location_percent_vcenter;
+
+ Optional< F32 > padding_horiz;
+ Optional< F32 > padding_vert;
+
+ Params();
+
+ bool equals(const Params&) const;
+ };
+
+protected:
+ friend class LLUICtrlFactory;
+ LLBadge(const Params& p);
+
+public:
+
+ ~LLBadge();
+
+ virtual void draw();
+
+ const std::string getLabel() const { return wstring_to_utf8str(mLabel); }
+ void setLabel( const LLStringExplicit& label);
+
+private:
+ LLPointer< LLUIImage > mBorderImage;
+ LLUIColor mBorderColor;
+
+ const LLFontGL* mGLFont;
+
+ LLPointer< LLUIImage > mImage;
+ LLUIColor mImageColor;
+
+ LLUIString mLabel;
+ LLUIColor mLabelColor;
+
+ LLRelPos::Location mLocation;
+ F32 mLocationPercentHCenter;
+ F32 mLocationPercentVCenter;
+
+ LLHandle< LLView > mOwner;
+
+ F32 mPaddingHoriz;
+ F32 mPaddingVert;
+};
+
+// Build time optimization, generate once in .cpp file
+#ifndef LLBADGE_CPP
+extern template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+#endif
+
+#endif // LL_LLBADGE_H
diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
new file mode 100644
index 0000000000..77f15567bf
--- /dev/null
+++ b/indra/llui/llbadgeowner.cpp
@@ -0,0 +1,126 @@
+/**
+ * @file llbadgeowner.cpp
+ * @brief Class to manage badges attached to a UI control
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llbadgeowner.h"
+#include "llpanel.h"
+
+//
+// Classes
+//
+
+LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle)
+ : mBadge(NULL)
+ , mBadgeOwnerView(viewHandle)
+{
+}
+
+void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
+{
+ if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
+ {
+ mBadge = createBadge(p);
+ }
+}
+
+void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
+{
+ if (mBadge == NULL)
+ {
+ mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
+
+ addBadgeToParentPanel();
+ }
+
+ if (mBadge)
+ {
+ mBadge->setLabel(label);
+
+ //
+ // Push the badge to the front so it renders on top
+ //
+
+ LLView * parent = mBadge->getParent();
+
+ if (parent)
+ {
+ parent->sendChildToFront(mBadge);
+ }
+ }
+}
+
+void LLBadgeOwner::setBadgeVisibility(bool visible)
+{
+ if (mBadge)
+ {
+ mBadge->setVisible(visible);
+ }
+}
+
+void LLBadgeOwner::addBadgeToParentPanel()
+{
+ LLView * owner_view = mBadgeOwnerView.get();
+
+ if (mBadge && owner_view)
+ {
+ // Badge parent is badge owner by default
+ LLView * badge_parent = owner_view;
+
+ // Find the appropriate parent for the badge
+ LLView * parent = owner_view->getParent();
+
+ while (parent)
+ {
+ LLPanel * parent_panel = dynamic_cast<LLPanel *>(parent);
+
+ if (parent_panel && parent_panel->acceptsBadge())
+ {
+ badge_parent = parent;
+ break;
+ }
+
+ parent = parent->getParent();
+ }
+
+ if (badge_parent)
+ {
+ badge_parent->addChild(mBadge);
+ }
+ else
+ {
+ llwarns << "Unable to find parent panel for badge " << mBadge->getName() << " on " << owner_view->getName() << llendl;
+ }
+ }
+}
+
+LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p)
+{
+ LLBadge::Params badge_params(p);
+ badge_params.owner = mBadgeOwnerView;
+
+ return LLUICtrlFactory::create<LLBadge>(badge_params);
+}
diff --git a/indra/newview/lldrawpoolclouds.h b/indra/llui/llbadgeowner.h
index 019f11a795..a2399189a5 100644
--- a/indra/newview/lldrawpoolclouds.h
+++ b/indra/llui/llbadgeowner.h
@@ -1,8 +1,8 @@
/**
- * @file lldrawpoolclouds.h
- * @brief LLDrawPoolClouds class definition
+ * @file llbadgeowner.h
+ * @brief Header for badge owners
*
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -24,31 +24,38 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLDRAWPOOLCLOUDS_H
-#define LL_LLDRAWPOOLCLOUDS_H
+#ifndef LL_LLBADGEOWNER_H
+#define LL_LLBADGEOWNER_H
-#include "lldrawpool.h"
+#include "llbadge.h"
+#include "llview.h"
-class LLDrawPoolClouds : public LLDrawPool
+//
+// Classes
+//
+
+class LLBadgeOwner
{
public:
- enum
- {
- VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TEXCOORD0
- };
-
- BOOL addFace(LLFace* face);
- virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
-
- LLDrawPoolClouds();
-
- /*virtual*/ void prerender();
- /*virtual*/ LLDrawPool *instancePool();
- /*virtual*/ void enqueue(LLFace *face);
- /*virtual*/ void beginRenderPass(S32 pass);
- /*virtual*/ void render(S32 pass = 0);
+
+ LLBadgeOwner(LLHandle< LLView > viewHandle);
+
+ void initBadgeParams(const LLBadge::Params& p);
+ void addBadgeToParentPanel();
+
+ bool badgeHasParent() const { return (mBadge && mBadge->getParent()); }
+
+ void setBadgeLabel(const LLStringExplicit& label);
+ void setBadgeVisibility(bool visible);
+
+private:
+
+ LLBadge* createBadge(const LLBadge::Params& p);
+
+private:
+
+ LLBadge* mBadge;
+ LLHandle< LLView > mBadgeOwnerView;
};
-#endif // LL_LLDRAWPOOLSKY_H
+#endif // LL_LLBADGEOWNER_H
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 45ceaff696..7b015bd576 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -99,7 +99,9 @@ LLButton::Params::Params()
scale_image("scale_image", true),
hover_glow_amount("hover_glow_amount"),
commit_on_return("commit_on_return", true),
- use_draw_context_alpha("use_draw_context_alpha", true)
+ use_draw_context_alpha("use_draw_context_alpha", true),
+ badge("badge"),
+ handle_right_mouse("handle_right_mouse")
{
addSynonym(is_toggle, "toggle");
held_down_delay.seconds = 0.5f;
@@ -109,6 +111,7 @@ LLButton::Params::Params()
LLButton::LLButton(const LLButton::Params& p)
: LLUICtrl(p),
+ LLBadgeOwner(LLView::getHandle()),
mMouseDownFrame(0),
mMouseHeldDownCount(0),
mBorderEnabled( FALSE ),
@@ -160,8 +163,8 @@ LLButton::LLButton(const LLButton::Params& p)
mMouseDownSignal(NULL),
mMouseUpSignal(NULL),
mHeldDownSignal(NULL),
- mUseDrawContextAlpha(p.use_draw_context_alpha)
-
+ mUseDrawContextAlpha(p.use_draw_context_alpha),
+ mHandleRightMouse(p.handle_right_mouse)
{
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
@@ -244,6 +247,11 @@ LLButton::LLButton(const LLButton::Params& p)
{
setHeldDownCallback(initCommitCallback(p.mouse_held_callback));
}
+
+ if (p.badge.isProvided())
+ {
+ LLBadgeOwner::initBadgeParams(p.badge());
+ }
}
LLButton::~LLButton()
@@ -327,8 +335,12 @@ boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb,
BOOL LLButton::postBuild()
{
autoResize();
- return TRUE;
+
+ addBadgeToParentPanel();
+
+ return LLUICtrl::postBuild();
}
+
BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
{
BOOL handled = FALSE;
@@ -447,7 +459,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (!childrenHandleRightMouseDown(x, y, mask))
+ if (mHandleRightMouse && !childrenHandleRightMouseDown(x, y, mask))
{
// Route future Mouse messages here preemptively. (Release on mouse up.)
gFocusMgr.setMouseCapture( this );
@@ -460,37 +472,42 @@ BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
// if (pointInView(x, y))
// {
// }
+ // send the mouse down signal
+ LLUICtrl::handleRightMouseDown(x,y,mask);
+ // *TODO: Return result of LLUICtrl call above? Should defer to base class
+ // but this might change the mouse handling of existing buttons in a bad way
+ // if they are not mouse opaque.
}
- // send the mouse down signal
- LLUICtrl::handleRightMouseDown(x,y,mask);
- // *TODO: Return result of LLUICtrl call above? Should defer to base class
- // but this might change the mouse handling of existing buttons in a bad way
- // if they are not mouse opaque.
+
return TRUE;
}
BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- // We only handle the click if the click both started and ended within us
- if( hasMouseCapture() )
+ if (mHandleRightMouse)
{
- // Always release the mouse
- gFocusMgr.setMouseCapture( NULL );
+ // We only handle the click if the click both started and ended within us
+ if( hasMouseCapture() )
+ {
+ // Always release the mouse
+ gFocusMgr.setMouseCapture( NULL );
-// if (pointInView(x, y))
-// {
-// mRightMouseUpSignal(this, x,y,mask);
-// }
- }
- else
- {
- childrenHandleRightMouseUp(x, y, mask);
+ // if (pointInView(x, y))
+ // {
+ // mRightMouseUpSignal(this, x,y,mask);
+ // }
+ }
+ else
+ {
+ childrenHandleRightMouseUp(x, y, mask);
+ }
+
+ // send the mouse up signal
+ LLUICtrl::handleRightMouseUp(x,y,mask);
+ // *TODO: Return result of LLUICtrl call above? Should defer to base class
+ // but this might change the mouse handling of existing buttons in a bad way.
+ // if they are not mouse opaque.
}
- // send the mouse up signal
- LLUICtrl::handleRightMouseUp(x,y,mask);
- // *TODO: Return result of LLUICtrl call above? Should defer to base class
- // but this might change the mouse handling of existing buttons in a bad way.
- // if they are not mouse opaque.
return TRUE;
}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 0cfc393e05..5968916006 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -27,6 +27,8 @@
#ifndef LL_LLBUTTON_H
#define LL_LLBUTTON_H
+#include "lluuid.h"
+#include "llbadgeowner.h"
#include "llcontrol.h"
#include "lluictrl.h"
#include "v4color.h"
@@ -52,15 +54,13 @@ S32 round_up(S32 grid, S32 value);
class LLUICtrlFactory;
-class LLUIImage;
-class LLUUID;
//
// Classes
//
class LLButton
-: public LLUICtrl
+: public LLUICtrl, public LLBadgeOwner
{
public:
struct Params
@@ -125,7 +125,11 @@ public:
Optional<F32> hover_glow_amount;
Optional<TimeIntervalParam> held_down_delay;
- Optional<bool> use_draw_context_alpha;
+ Optional<bool> use_draw_context_alpha;
+
+ Optional<LLBadge::Params> badge;
+
+ Optional<bool> handle_right_mouse;
Params();
};
@@ -249,7 +253,7 @@ public:
void setImageDisabledSelected(LLPointer<LLUIImage> image);
void setImageFlash(LLPointer<LLUIImage> image);
void setImagePressed(LLPointer<LLUIImage> image);
-
+
void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
BOOL getCommitOnReturn() const { return mCommitOnReturn; }
@@ -357,6 +361,8 @@ private:
bool mForcePressedState;
LLFrameTimer mFlashingTimer;
+
+ bool mHandleRightMouse;
};
// Build time optimization, generate once in .cpp file
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 06bad1f371..04040200d0 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -132,6 +132,9 @@ void LLConsole::setFontSize(S32 size_index)
void LLConsole::draw()
{
+ // Units in pixels
+ static const F32 padding_horizontal = 10;
+ static const F32 padding_vertical = 3;
LLGLSUIDefault gls_ui;
// skip lines added more than mLinePersistTime ago
@@ -176,11 +179,9 @@ void LLConsole::draw()
// draw remaining lines
F32 y_pos = 0.f;
- LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
+ LLUIImagePtr imagep = LLUI::getUIImage("transparent");
-// F32 console_opacity = llclamp(gSavedSettings.getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
F32 console_opacity = llclamp(LLUI::sSettingGroups["config"]->getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
-// LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
color.mV[VALPHA] *= console_opacity;
@@ -188,8 +189,8 @@ void LLConsole::draw()
for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++)
{
- S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8);
- S32 target_width = llfloor( (*paragraph_it).mMaxWidth +15);
+ S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + padding_vertical);
+ S32 target_width = llfloor( (*paragraph_it).mMaxWidth + padding_horizontal);
y_pos += ((*paragraph_it).mLines.size()) * line_height;
imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color);
@@ -234,7 +235,7 @@ void LLConsole::draw()
y_off += line_height;
}
}
- y_pos += 8;
+ y_pos += padding_vertical;
}
}
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 9b6830a816..6a91ec56e4 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -49,6 +49,8 @@ void LLLayoutStack::OrientationNames::declareValues()
//
LLLayoutPanel::LLLayoutPanel(const Params& p)
: LLPanel(p),
+ mExpandedMinDimSpecified(false),
+ mExpandedMinDim(p.min_dim),
mMinDim(p.min_dim),
mMaxDim(p.max_dim),
mAutoResize(p.auto_resize),
@@ -58,6 +60,13 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
mVisibleAmt(1.f), // default to fully visible
mResizeBar(NULL)
{
+ // Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value
+ if (p.expanded_min_dim.isProvided())
+ {
+ mExpandedMinDimSpecified = true;
+ mExpandedMinDim = p.expanded_min_dim();
+ }
+
// panels initialized as hidden should not start out partially visible
if (!getVisible())
{
@@ -78,20 +87,20 @@ LLLayoutPanel::~LLLayoutPanel()
delete mResizeBar;
mResizeBar = NULL;
}
-
+
F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation)
{
if (orientation == LLLayoutStack::HORIZONTAL)
{
F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinDim / (F32)llmax(1, getRect().getWidth()));
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth()));
return mVisibleAmt * collapse_amt;
}
else
{
- F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinDim / (F32)llmax(1, getRect().getHeight())));
- return mVisibleAmt * collapse_amt;
+ F32 collapse_amt =
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight())));
+ return mVisibleAmt * collapse_amt;
}
}
@@ -182,14 +191,14 @@ BOOL LLLayoutStack::postBuild()
}
bool LLLayoutStack::addChild(LLView* child, S32 tab_group)
- {
+{
LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);
- if (panelp)
- {
+ if (panelp)
+ {
mPanels.push_back(panelp);
- }
+ }
return LLView::addChild(child, tab_group);
- }
+}
S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
@@ -281,9 +290,9 @@ bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp
{
LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
- if (panel)
+ if (panel && min_dimp)
{
- if (min_dimp) *min_dimp = panel->mMinDim;
+ *min_dimp = panel->getRelevantMinDim();
}
return NULL != panel;
@@ -316,23 +325,23 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it);
+ LLLayoutPanel* panelp = (*panel_it);
if (panelp->getVisible())
{
if (mAnimate)
{
if (!mAnimatedThisFrame)
{
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant));
- if ((*panel_it)->mVisibleAmt > 0.99f)
+ panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant));
+ if (panelp->mVisibleAmt > 0.99f)
{
- (*panel_it)->mVisibleAmt = 1.f;
+ panelp->mVisibleAmt = 1.f;
}
}
}
else
{
- (*panel_it)->mVisibleAmt = 1.f;
+ panelp->mVisibleAmt = 1.f;
}
}
else // not visible
@@ -341,36 +350,36 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
if (!mAnimatedThisFrame)
{
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
- if ((*panel_it)->mVisibleAmt < 0.001f)
+ panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+ if (panelp->mVisibleAmt < 0.001f)
{
- (*panel_it)->mVisibleAmt = 0.f;
+ panelp->mVisibleAmt = 0.f;
}
}
}
else
{
- (*panel_it)->mVisibleAmt = 0.f;
+ panelp->mVisibleAmt = 0.f;
}
}
- if ((*panel_it)->mCollapsed)
+ if (panelp->mCollapsed)
{
- (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+ panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
}
else
{
- (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+ panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
}
if (mOrientation == HORIZONTAL)
{
// enforce minimize size constraint by default
- if (panelp->getRect().getWidth() < (*panel_it)->mMinDim)
+ if (panelp->getRect().getWidth() < panelp->getRelevantMinDim())
{
- panelp->reshape((*panel_it)->mMinDim, panelp->getRect().getHeight());
+ panelp->reshape(panelp->getRelevantMinDim(), panelp->getRect().getHeight());
}
- total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor(mOrientation));
+ total_width += llround(panelp->getRect().getWidth() * panelp->getCollapseFactor(mOrientation));
// want n-1 panel gaps for n panels
if (panel_it != mPanels.begin())
{
@@ -380,11 +389,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
else //VERTICAL
{
// enforce minimize size constraint by default
- if (panelp->getRect().getHeight() < (*panel_it)->mMinDim)
+ if (panelp->getRect().getHeight() < panelp->getRelevantMinDim())
{
- panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinDim);
+ panelp->reshape(panelp->getRect().getWidth(), panelp->getRelevantMinDim());
}
- total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor(mOrientation));
+ total_height += llround(panelp->getRect().getHeight() * panelp->getCollapseFactor(mOrientation));
if (panel_it != mPanels.begin())
{
total_height += mPanelSpacing;
@@ -403,34 +412,23 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
continue;
}
+ S32 relevant_dimension = (mOrientation == HORIZONTAL) ? (*panel_it)->getRect().getWidth() : (*panel_it)->getRect().getHeight();
+ S32 relevant_min = (*panel_it)->getRelevantMinDim();
+
// if currently resizing a panel or the panel is flagged as not automatically resizing
// only track total available headroom, but don't use it for automatic resize logic
if ((*panel_it)->mResizeBar->hasMouseCapture()
|| (!(*panel_it)->mAutoResize
&& !force_resize))
{
- if (mOrientation == HORIZONTAL)
- {
- shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
- }
- else //VERTICAL
- {
- shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
- }
+ shrink_headroom_total += relevant_dimension - relevant_min;
}
else
{
num_resizable_panels++;
- if (mOrientation == HORIZONTAL)
- {
- shrink_headroom_available += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
- shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
- }
- else //VERTICAL
- {
- shrink_headroom_available += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
- shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
- }
+
+ shrink_headroom_available += relevant_dimension - relevant_min;
+ shrink_headroom_total += relevant_dimension - relevant_min;
}
}
@@ -452,27 +450,28 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it);
+ LLLayoutPanel* panelp = (*panel_it);
S32 cur_width = panelp->getRect().getWidth();
S32 cur_height = panelp->getRect().getHeight();
S32 new_width = cur_width;
- S32 new_height = cur_height;
+ S32 new_height = cur_height;
+ S32 relevant_min = panelp->getRelevantMinDim();
if (mOrientation == HORIZONTAL)
{
- new_width = llmax((*panel_it)->mMinDim, new_width);
+ new_width = llmax(relevant_min, new_width);
}
else
{
- new_height = llmax((*panel_it)->mMinDim, new_height);
+ new_height = llmax(relevant_min, new_height);
}
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
- if ((*panel_it)->getCollapseFactor(mOrientation) == 1.f
- && (force_resize || (*panel_it)->mAutoResize)
- && !(*panel_it)->mResizeBar->hasMouseCapture())
+ if (panelp->getCollapseFactor(mOrientation) == 1.f
+ && (force_resize || panelp->mAutoResize)
+ && !panelp->mResizeBar->hasMouseCapture())
{
if (mOrientation == HORIZONTAL)
{
@@ -481,8 +480,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_width - (*panel_it)->mMinDim);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - relevant_min) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_width - relevant_min);
}
else
{
@@ -491,7 +490,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
- new_width = llmax((*panel_it)->mMinDim, cur_width + delta_size);
+ new_width = llmax(relevant_min, cur_width + delta_size);
}
else
{
@@ -504,8 +503,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_height - (*panel_it)->mMinDim);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - relevant_min) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_height - relevant_min);
}
else
{
@@ -513,7 +512,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
- new_height = llmax((*panel_it)->mMinDim, cur_height + delta_size);
+ new_height = llmax(relevant_min, cur_height + delta_size);
}
else
{
@@ -566,19 +565,20 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
LLLayoutPanel* last_resizeable_panel = NULL;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it);
+ LLLayoutPanel* panelp = (*panel_it);
+ S32 relevant_min = panelp->getRelevantMinDim();
if (mOrientation == HORIZONTAL)
{
(*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinDim,
- (*panel_it)->mMinDim + shrink_headroom_total);
+ relevant_min,
+ relevant_min + shrink_headroom_total);
}
else //VERTICAL
{
(*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinDim,
- (*panel_it)->mMinDim + shrink_headroom_total);
+ relevant_min,
+ relevant_min + shrink_headroom_total);
}
// toggle resize bars based on panel visibility, resizability, etc
@@ -658,7 +658,7 @@ void LLLayoutStack::calcMinExtents()
{
if (mOrientation == HORIZONTAL)
{
- mMinWidth += (*panel_it)->mMinDim;
+ mMinWidth += (*panel_it)->getRelevantMinDim();
if (panel_it != mPanels.begin())
{
mMinWidth += mPanelSpacing;
@@ -666,7 +666,7 @@ void LLLayoutStack::calcMinExtents()
}
else //VERTICAL
{
- mMinHeight += (*panel_it)->mMinDim;
+ mMinHeight += (*panel_it)->getRelevantMinDim();
if (panel_it != mPanels.begin())
{
mMinHeight += mPanelSpacing;
@@ -688,7 +688,7 @@ void LLLayoutStack::createResizeBars()
LLResizeBar::Params resize_params;
resize_params.name("resize");
resize_params.resizing_view(lp);
- resize_params.min_size(lp->mMinDim);
+ resize_params.min_size(lp->getRelevantMinDim());
resize_params.side(side);
resize_params.snapping_enabled(false);
LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 4ac8ef0ee9..d8ef0aeaca 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -30,10 +30,10 @@
#include "llpanel.h"
-class LLPanel;
class LLLayoutPanel;
+
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
@@ -149,6 +149,7 @@ private:
F32 mCloseTimeConstant;
}; // end class LLLayoutStack
+
class LLLayoutPanel : public LLPanel
{
friend class LLLayoutStack;
@@ -156,13 +157,15 @@ friend class LLUICtrlFactory;
public:
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
- Optional<S32> min_dim,
+ Optional<S32> expanded_min_dim,
+ min_dim,
max_dim;
Optional<bool> user_resize,
auto_resize;
Params()
- : min_dim("min_dim", 0),
+ : expanded_min_dim("expanded_min_dim", 0),
+ min_dim("min_dim", 0),
max_dim("max_dim", 0),
user_resize("user_resize", true),
auto_resize("auto_resize", true)
@@ -177,15 +180,36 @@ public:
~LLLayoutPanel();
void initFromParams(const Params& p);
- void setMinDim(S32 value) { mMinDim = value; }
+
+ S32 getMinDim() const { return mMinDim; }
+ void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; }
+
+ S32 getMaxDim() const { return mMaxDim; }
void setMaxDim(S32 value) { mMaxDim = value; }
-protected:
- LLLayoutPanel(const Params& p) ;
+ S32 getExpandedMinDim() const { return mExpandedMinDim; }
+ void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; }
+
+ S32 getRelevantMinDim() const
+ {
+ S32 min_dim = mMinDim;
+
+ if (!mCollapsed)
+ {
+ min_dim = mExpandedMinDim;
+ }
+
+ return min_dim;
+ }
+protected:
+ LLLayoutPanel(const Params& p);
F32 getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation);
+ bool mExpandedMinDimSpecified;
+ S32 mExpandedMinDim;
+
S32 mMinDim;
S32 mMaxDim;
BOOL mAutoResize;
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 0196080d90..06fbc0f234 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -37,6 +37,7 @@
#include "llgl.h"
#include "lltimer.h"
+#include "llcalc.h"
//#include "llclipboard.h"
#include "llcontrol.h"
#include "llbutton.h"
@@ -81,6 +82,7 @@ LLLineEditor::Params::Params()
: max_length(""),
keystroke_callback("keystroke_callback"),
prevalidate_callback("prevalidate_callback"),
+ prevalidate_input_callback("prevalidate_input_callback"),
background_image("background_image"),
background_image_disabled("background_image_disabled"),
background_image_focused("background_image_focused"),
@@ -132,6 +134,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mIgnoreTab( p.ignore_tab ),
mDrawAsterixes( p.is_password ),
mSelectAllonFocusReceived( p.select_on_focus ),
+ mSelectAllonCommit( TRUE ),
mPassDelete(FALSE),
mReadOnly(FALSE),
mBgImage( p.background_image ),
@@ -173,6 +176,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
updateTextPadding();
setCursor(mText.length());
+ setPrevalidateInput(p.prevalidate_input_callback());
setPrevalidate(p.prevalidate_callback());
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
@@ -228,7 +232,10 @@ void LLLineEditor::onCommit()
setControlValue(getValue());
LLUICtrl::onCommit();
- selectAll();
+
+ // Selection on commit needs to be turned off when evaluating maths
+ // expressions, to allow indication of the error position
+ if (mSelectAllonCommit) selectAll();
}
// Returns TRUE if user changed value at all
@@ -405,23 +412,15 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
// Picks a new cursor position based on the actual screen size of text being drawn.
void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )
{
- const llwchar* wtext = mText.getWString().c_str();
- LLWString asterix_text;
- if (mDrawAsterixes)
- {
- for (S32 i = 0; i < mText.length(); i++)
- {
- asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);
- }
- wtext = asterix_text.c_str();
- }
+ S32 cursor_pos = calcCursorPos(local_mouse_x);
+
+ S32 left_pos = llmin( mSelectionStart, cursor_pos );
+ S32 length = llabs( mSelectionStart - cursor_pos );
+ const LLWString& substr = mText.getWString().substr(left_pos, length);
+
+ if (mIsSelecting && !prevalidateInput(substr))
+ return;
- S32 cursor_pos =
- mScrollHPos +
- mGLFont->charFromPixelOffset(
- wtext, mScrollHPos,
- (F32)(local_mouse_x - mTextLeftEdge),
- (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive
setCursor(cursor_pos);
}
@@ -505,6 +504,11 @@ BOOL LLLineEditor::canSelectAll() const
void LLLineEditor::selectAll()
{
+ if (!prevalidateInput(mText.getWString()))
+ {
+ return;
+ }
+
mSelectionStart = mText.length();
mSelectionEnd = 0;
setCursor(mSelectionEnd);
@@ -590,6 +594,9 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
if (mask & MASK_SHIFT)
{
+ // assume we're starting a drag select
+ mIsSelecting = TRUE;
+
// Handle selection extension
S32 old_cursor_pos = getCursor();
setCursorAtLocalPos(x);
@@ -624,8 +631,6 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
mSelectionStart = old_cursor_pos;
mSelectionEnd = getCursor();
}
- // assume we're starting a drag select
- mIsSelecting = TRUE;
}
else
{
@@ -796,6 +801,9 @@ void LLLineEditor::removeChar()
{
if( getCursor() > 0 )
{
+ if (!prevalidateInput(mText.getWString().substr(getCursor()-1, 1)))
+ return;
+
mText.erase(getCursor() - 1, 1);
setCursor(getCursor() - 1);
@@ -816,6 +824,9 @@ void LLLineEditor::addChar(const llwchar uni_char)
}
else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
{
+ if (!prevalidateInput(mText.getWString().substr(getCursor(), 1)))
+ return;
+
mText.erase(getCursor(), 1);
}
@@ -864,6 +875,13 @@ void LLLineEditor::extendSelection( S32 new_cursor_pos )
startSelection();
}
+ S32 left_pos = llmin( mSelectionStart, new_cursor_pos );
+ S32 selection_length = llabs( mSelectionStart - new_cursor_pos );
+ const LLWString& selection = mText.getWString().substr(left_pos, selection_length);
+
+ if (!prevalidateInput(selection))
+ return;
+
setCursor(new_cursor_pos);
mSelectionEnd = getCursor();
}
@@ -994,8 +1012,12 @@ void LLLineEditor::deleteSelection()
{
if( !mReadOnly && hasSelection() )
{
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 selection_length = llabs( mSelectionStart - mSelectionEnd );
+ S32 left_pos, selection_length;
+ getSelectionRange(&left_pos, &selection_length);
+ const LLWString& selection = mText.getWString().substr(left_pos, selection_length);
+
+ if (!prevalidateInput(selection))
+ return;
mText.erase(left_pos, selection_length);
deselect();
@@ -1013,12 +1035,16 @@ void LLLineEditor::cut()
{
if( canCut() )
{
+ S32 left_pos, length;
+ getSelectionRange(&left_pos, &length);
+ const LLWString& selection = mText.getWString().substr(left_pos, length);
+
+ if (!prevalidateInput(selection))
+ return;
+
// Prepare for possible rollback
LLLineEditorRollback rollback( this );
-
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
deleteSelection();
@@ -1098,6 +1124,9 @@ void LLLineEditor::pasteHelper(bool is_primary)
if (!paste.empty())
{
+ if (!prevalidateInput(paste))
+ return;
+
// Prepare for possible rollback
LLLineEditorRollback rollback(this);
@@ -1445,6 +1474,13 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
LLLineEditorRollback rollback( this );
+ {
+ LLWString u_char;
+ u_char.assign(1, uni_char);
+ if (!prevalidateInput(u_char))
+ return handled;
+ }
+
addChar(uni_char);
mKeystrokeTimer.reset();
@@ -1496,6 +1532,15 @@ void LLLineEditor::doDelete()
}
else if ( getCursor() < mText.length())
{
+ const LLWString& text_to_delete = mText.getWString().substr(getCursor(), 1);
+
+ if (!prevalidateInput(text_to_delete))
+ {
+ if( mKeystrokeCallback )
+ mKeystrokeCallback( this );
+
+ return;
+ }
setCursor(getCursor() + 1);
removeChar();
}
@@ -1843,6 +1888,27 @@ S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const
return result;
}
+S32 LLLineEditor::calcCursorPos(S32 mouse_x)
+{
+ const llwchar* wtext = mText.getWString().c_str();
+ LLWString asterix_text;
+ if (mDrawAsterixes)
+ {
+ for (S32 i = 0; i < mText.length(); i++)
+ {
+ asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);
+ }
+ wtext = asterix_text.c_str();
+ }
+
+ S32 cur_pos = mScrollHPos +
+ mGLFont->charFromPixelOffset(
+ wtext, mScrollHPos,
+ (F32)(mouse_x - mTextLeftEdge),
+ (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive
+
+ return cur_pos;
+}
//virtual
void LLLineEditor::clear()
{
@@ -1936,6 +2002,22 @@ void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func)
updateAllowingLanguageInput();
}
+void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func)
+{
+ mPrevalidateInputFunc = func;
+ updateAllowingLanguageInput();
+}
+
+bool LLLineEditor::prevalidateInput(const LLWString& wstr)
+{
+ if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
// static
BOOL LLLineEditor::postvalidateFloat(const std::string &str)
{
@@ -1995,6 +2077,32 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str)
return success;
}
+BOOL LLLineEditor::evaluateFloat()
+{
+ bool success;
+ F32 result = 0.f;
+ std::string expr = getText();
+ LLStringUtil::toUpper(expr);
+
+ success = LLCalc::getInstance()->evalString(expr, result);
+
+ if (!success)
+ {
+ // Move the cursor to near the error on failure
+ setCursor(LLCalc::getInstance()->getLastErrorPos());
+ // *TODO: Translated error message indicating the type of error? Select error text?
+ }
+ else
+ {
+ // Replace the expression with the result
+ std::string result_str = llformat("%f",result);
+ setText(result_str);
+ selectAll();
+ }
+
+ return success;
+}
+
void LLLineEditor::onMouseCaptureLost()
{
endSelection();
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index fe191e5971..583bde360a 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -76,6 +76,7 @@ public:
Optional<keystroke_callback_t> keystroke_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
+ Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_input_callback;
Optional<LLViewBorder::Params> border;
@@ -220,6 +221,7 @@ public:
void deleteSelection();
void setSelectAllonFocusReceived(BOOL b);
+ void setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; }
typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t;
void setKeystrokeCallback(callback_t callback, void* user_data);
@@ -232,8 +234,16 @@ public:
// Prevalidation controls which keystrokes can affect the editor
void setPrevalidate( LLTextValidate::validate_func_t func );
+ // This method sets callback that prevents from:
+ // - deleting, selecting, typing, cutting, pasting characters that are not valid.
+ // Also callback that this method sets differs from setPrevalidate in a way that it validates just inputed
+ // symbols, before existing text is modified, but setPrevalidate validates line after it was modified.
+ void setPrevalidateInput(LLTextValidate::validate_func_t func);
static BOOL postvalidateFloat(const std::string &str);
+ bool prevalidateInput(const LLWString& wstr);
+ BOOL evaluateFloat();
+
// line history support:
void setEnableLineHistory( BOOL enabled ) { mHaveHistory = enabled; } // switches line history on or off
void updateHistory(); // stores current line in history
@@ -251,6 +261,7 @@ private:
void addChar(const llwchar c);
void setCursorAtLocalPos(S32 local_mouse_x);
S32 findPixelNearestPos(S32 cursor_offset = 0) const;
+ S32 calcCursorPos(S32 mouse_x);
BOOL handleSpecialKey(KEY key, MASK mask);
BOOL handleSelectionKey(KEY key, MASK mask);
BOOL handleControlKey(KEY key, MASK mask);
@@ -312,6 +323,7 @@ protected:
S32 mLastSelectionEnd;
LLTextValidate::validate_func_t mPrevalidateFunc;
+ LLTextValidate::validate_func_t mPrevalidateInputFunc;
LLFrameTimer mKeystrokeTimer;
LLTimer mTripleClickTimer;
@@ -330,6 +342,7 @@ protected:
BOOL mDrawAsterixes;
BOOL mSelectAllonFocusReceived;
+ BOOL mSelectAllonCommit;
BOOL mPassDelete;
BOOL mReadOnly;
diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h
index 4c47cc267c..7c44478848 100644
--- a/indra/llui/llloadingindicator.h
+++ b/indra/llui/llloadingindicator.h
@@ -86,6 +86,8 @@ public:
*/
void start();
+ void reset() { mCurImageIdx = 0; }
+
private:
LLLoadingIndicator(const Params&);
void initFromParams(const Params&);
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index f744e9db41..9052bc7d1d 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -511,7 +511,7 @@ void LLMultiSlider::draw()
mIt->second.mTop + extra_triangle_height,
mIt->second.mLeft + mIt->second.getWidth() / 2,
mIt->second.mBottom - extra_triangle_height,
- mTriangleColor.get(), TRUE);
+ mTriangleColor.get() % opacity, TRUE);
}
}
else if (!thumb_imagep)
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index b2383106a8..1dcdd79efa 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -87,7 +87,8 @@ LLPanel::Params::Params()
filename("filename"),
class_name("class"),
help_topic("help_topic"),
- visible_callback("visible_callback")
+ visible_callback("visible_callback"),
+ accepts_badge("accepts_badge")
{
name = "panel";
addSynonym(background_visible, "bg_visible");
@@ -113,7 +114,8 @@ LLPanel::LLPanel(const LLPanel::Params& p)
mCommitCallbackRegistrar(false),
mEnableCallbackRegistrar(false),
mXMLFilename(p.filename),
- mVisibleSignal(NULL)
+ mVisibleSignal(NULL),
+ mAcceptsBadge(p.accepts_badge)
// *NOTE: Be sure to also change LLPanel::initFromParams(). We have too
// many classes derived from LLPanel to retrofit them all to pass in params.
{
@@ -485,6 +487,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
mBgAlphaImage = p.bg_alpha_image();
mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
+
+ mAcceptsBadge = p.accepts_badge;
}
static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 7bbbeaf709..67674fab7e 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -89,6 +89,8 @@ public:
Multiple<LocalizedString> strings;
Optional<CommitCallbackParam> visible_callback;
+
+ Optional<bool> accepts_badge;
Params();
};
@@ -250,6 +252,8 @@ public:
boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
+ bool acceptsBadge() const { return mAcceptsBadge; }
+
protected:
// Override to set not found list
LLButton* getDefaultButton() { return mDefaultBtn; }
@@ -264,6 +268,7 @@ protected:
static factory_stack_t sFactoryStack;
private:
+ bool mAcceptsBadge;
BOOL mBgVisible; // any background at all?
BOOL mBgOpaque; // use opaque color or image
LLUIColor mBgOpaqueColor;
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 39385786bc..820e7cb26a 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -337,7 +337,7 @@ LLLocale::LLLocale(const std::string& locale_string)
char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());
if ( new_locale_string == NULL)
{
- llwarns << "Failed to set locale " << locale_string << llendl;
+ LL_WARNS_ONCE("LLLocale") << "Failed to set locale " << locale_string << LL_ENDL;
setlocale(LC_ALL, SYSTEM_LOCALE.c_str());
}
//else
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 6b4e9cf923..934879cdfd 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -44,7 +44,7 @@
#include "llresmgr.h"
#include "lluictrlfactory.h"
-const U32 MAX_STRING_LENGTH = 32;
+const U32 MAX_STRING_LENGTH = 255;
static LLDefaultChildRegistry::Register<LLSpinCtrl> r2("spinner");
@@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params()
: label_width("label_width"),
decimal_digits("decimal_digits"),
allow_text_entry("allow_text_entry", true),
+ label_wrap("label_wrap", false),
text_enabled_color("text_enabled_color"),
text_disabled_color("text_disabled_color"),
up_button("up_button"),
@@ -80,6 +81,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
{
LLRect label_rect( 0, centered_top, label_width, centered_bottom );
LLTextBox::Params params;
+ params.wrap(p.label_wrap);
params.name("SpinCtrl Label");
params.rect(label_rect);
params.initial_value(p.label());
@@ -122,14 +124,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
- if( mPrecision>0 )//should accept float numbers
- {
- params.prevalidate_callback(&LLTextValidate::validateFloat);
- }
- else //should accept int numbers
- {
- params.prevalidate_callback(&LLTextValidate::validateInt);
- }
+ //*NOTE: allow entering of any chars for LLCalc, proper input will be evaluated on commit
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
@@ -138,6 +133,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
// than when it doesn't. Instead, if you always have to double click to select all the text,
// it's easier to understand
//mEditor->setSelectAllonFocusReceived(TRUE);
+ mEditor->setSelectAllonCommit(FALSE);
addChild(mEditor);
updateEditor();
@@ -302,9 +298,10 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data )
{
BOOL success = FALSE;
- std::string text = mEditor->getText();
- if( LLLineEditor::postvalidateFloat( text ) )
+ if( mEditor->evaluateFloat() )
{
+ std::string text = mEditor->getText();
+
LLLocale locale(LLLocale::USER_LOCALE);
F32 val = (F32) atof(text.c_str());
@@ -325,7 +322,11 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data )
}
updateEditor();
- if( !success )
+ if( success )
+ {
+ updateEditor();
+ }
+ else
{
reportInvalidData();
}
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index 8960971594..d197084e38 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -44,6 +44,7 @@ public:
Optional<S32> label_width;
Optional<U32> decimal_digits;
Optional<bool> allow_text_entry;
+ Optional<bool> label_wrap;
Optional<LLUIColor> text_enabled_color;
Optional<LLUIColor> text_disabled_color;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 1cc3cc04d6..349dbc3405 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -280,7 +280,7 @@ bool LLTextBase::truncate()
if (getLength() >= S32(mMaxTextByteLength / 4))
{
// Have to check actual byte size
- LLWString text(getWText());
+ LLWString text(getWText());
S32 utf8_byte_size = wstring_utf8_length(text);
if ( utf8_byte_size > mMaxTextByteLength )
{
@@ -547,8 +547,7 @@ void LLTextBase::drawText()
}
LLRect text_rect(line.mRect);
- text_rect.mRight = llmin(mDocumentView->getRect().getWidth(), text_rect.mRight); // clamp right edge to document extents
- text_rect.translate(mVisibleTextRect.mLeft, mVisibleTextRect.mBottom); // translate into display region of text widget
+ text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents
text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position
// draw a single line of text
@@ -655,7 +654,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
}
text.insert(pos, wstr);
- getViewModel()->setDisplay(text);
+ getViewModel()->setDisplay(text);
if ( truncate() )
{
@@ -670,7 +669,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
{
- LLWString text(getWText());
+ LLWString text(getWText());
segment_set_t::iterator seg_iter = getSegIterContaining(pos);
while(seg_iter != mSegments.end())
{
@@ -717,7 +716,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
}
text.erase(pos, length);
- getViewModel()->setDisplay(text);
+ getViewModel()->setDisplay(text);
// recreate default segment in case we erased everything
createDefaultSegment();
@@ -734,9 +733,9 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
{
return 0;
}
- LLWString text(getWText());
+ LLWString text(getWText());
text[pos] = wc;
- getViewModel()->setDisplay(text);
+ getViewModel()->setDisplay(text);
onValueChange(pos, pos + 1);
needsReflow(pos);
@@ -857,7 +856,7 @@ BOOL LLTextBase::handleMouseUp(S32 x, S32 y, MASK mask)
// Did we just click on a link?
if (mURLClickSignal
&& cur_segment->getStyle()
- && cur_segment->getStyle()->isLink())
+ && cur_segment->getStyle()->isLink())
{
// *TODO: send URL here?
(*mURLClickSignal)(this, LLSD() );
@@ -1035,27 +1034,27 @@ void LLTextBase::draw()
gl_rect_2d(text_rect, bg_color % alpha, TRUE);
}
- bool should_clip = mClip || mScroller != NULL;
- { LLLocalClipRect clip(text_rect, should_clip);
+ bool should_clip = mClip || mScroller != NULL;
+ { LLLocalClipRect clip(text_rect, should_clip);
- // draw document view
- if (mScroller)
+ // draw document view
+ if (mScroller)
+ {
+ drawChild(mScroller);
+ }
+ else
{
- drawChild(mScroller);
- }
- else
- {
- drawChild(mDocumentView);
- }
+ drawChild(mDocumentView);
+ }
drawSelectionBackground();
drawText();
drawCursor();
}
- mDocumentView->setVisible(FALSE);
- LLUICtrl::draw();
- mDocumentView->setVisible(TRUE);
+ mDocumentView->setVisible(FALSE);
+ LLUICtrl::draw();
+ mDocumentView->setVisible(TRUE);
}
@@ -1119,8 +1118,7 @@ void LLTextBase::updateScrollFromCursor()
// scroll so that the cursor is at the top of the page
LLRect scroller_doc_window = getVisibleDocumentRect();
- LLRect cursor_rect_doc = getLocalRectFromDocIndex(mCursorPos);
- cursor_rect_doc.translate(scroller_doc_window.mLeft, scroller_doc_window.mBottom);
+ LLRect cursor_rect_doc = getDocRectFromDocIndex(mCursorPos);
mScroller->scrollToShowRect(cursor_rect_doc, LLRect(0, scroller_doc_window.getHeight() - 5, scroller_doc_window.getWidth(), 5));
}
@@ -1366,9 +1364,9 @@ S32 LLTextBase::getLineStart( S32 line ) const
{
S32 num_lines = getLineCount();
if (num_lines == 0)
- {
+ {
return 0;
- }
+ }
line = llclamp(line, 0, num_lines-1);
return mLineInfoList[line].mDocIndexStart;
@@ -1378,9 +1376,9 @@ S32 LLTextBase::getLineEnd( S32 line ) const
{
S32 num_lines = getLineCount();
if (num_lines == 0)
- {
+ {
return 0;
- }
+ }
line = llclamp(line, 0, num_lines-1);
return mLineInfoList[line].mDocIndexEnd;
@@ -1656,7 +1654,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
LLUrlMatch match;
std::string text = new_text;
while ( LLUrlRegistry::instance().findUrl(text, match,
- boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
+ boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
{
LLTextUtil::processUrlMatch(&match,this);
@@ -1949,7 +1947,7 @@ void LLTextBase::setWText(const LLWString& text)
const LLWString& LLTextBase::getWText() const
{
- return getViewModel()->getDisplay();
+ return getViewModel()->getDisplay();
}
// If round is true, if the position is on the right half of a character, the cursor
@@ -1960,9 +1958,12 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
{
// Figure out which line we're nearest to.
LLRect visible_region = getVisibleDocumentRect();
+ LLRect doc_rect = mDocumentView->getRect();
+
+ S32 doc_y = local_y - doc_rect.mBottom;
// binary search for line that starts before local_y
- line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), local_y - mVisibleTextRect.mBottom + visible_region.mBottom, compare_bottom());
+ line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), doc_y, compare_bottom());
if (line_iter == mLineInfoList.end())
{
@@ -1970,7 +1971,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
}
S32 pos = getLength();
- S32 start_x = mVisibleTextRect.mLeft + line_iter->mRect.mLeft - visible_region.mLeft;
+ S32 start_x = line_iter->mRect.mLeft + doc_rect.mLeft;
segment_set_t::iterator line_seg_iter;
S32 line_seg_offset;
@@ -1992,7 +1993,7 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
}
// if we've reached a line of text *below* the mouse cursor, doc index is first character on that line
- if (hit_past_end_of_line && local_y - mVisibleTextRect.mBottom + visible_region.mBottom > line_iter->mRect.mTop)
+ if (hit_past_end_of_line && doc_y > line_iter->mRect.mTop)
{
pos = segment_line_start;
break;
@@ -2461,7 +2462,7 @@ LLRect LLTextBase::getVisibleDocumentRect() const
LLRect doc_rect = mDocumentView->getLocalRect();
doc_rect.mLeft -= mDocumentView->getRect().mLeft;
// adjust for height of text above widget baseline
- doc_rect.mBottom = llmin(0, doc_rect.getHeight() - mVisibleTextRect.getHeight());
+ doc_rect.mBottom = doc_rect.getHeight() - mVisibleTextRect.getHeight();
return doc_rect;
}
}
@@ -2575,21 +2576,21 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
LLColor4 color = (mEditor.getReadOnly() ? mStyle->getReadOnlyColor() : mStyle->getColor()) % alpha;
- if( selection_start > seg_start )
+ if( selection_start > seg_start )
{
// Draw normally
S32 start = seg_start;
S32 end = llmin( selection_start, seg_end );
S32 length = end - start;
font->render(text, start,
- rect,
- color,
- LLFontGL::LEFT, mEditor.mVAlign,
- LLFontGL::NORMAL,
- mStyle->getShadowType(),
- length,
- &right_x,
- mEditor.getUseEllipses());
+ rect,
+ color,
+ LLFontGL::LEFT, mEditor.mVAlign,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length,
+ &right_x,
+ mEditor.getUseEllipses());
}
rect.mLeft = (S32)ceil(right_x);
@@ -2601,14 +2602,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 length = end - start;
font->render(text, start,
- rect,
- mStyle->getSelectedColor().get(),
- LLFontGL::LEFT, mEditor.mVAlign,
- LLFontGL::NORMAL,
- LLFontGL::NO_SHADOW,
- length,
- &right_x,
- mEditor.getUseEllipses());
+ rect,
+ mStyle->getSelectedColor().get(),
+ LLFontGL::LEFT, mEditor.mVAlign,
+ LLFontGL::NORMAL,
+ LLFontGL::NO_SHADOW,
+ length,
+ &right_x,
+ mEditor.getUseEllipses());
}
rect.mLeft = (S32)ceil(right_x);
if( selection_end < seg_end )
@@ -2618,14 +2619,14 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
S32 end = seg_end;
S32 length = end - start;
font->render(text, start,
- rect,
- color,
- LLFontGL::LEFT, mEditor.mVAlign,
- LLFontGL::NORMAL,
- mStyle->getShadowType(),
- length,
- &right_x,
- mEditor.getUseEllipses());
+ rect,
+ color,
+ LLFontGL::LEFT, mEditor.mVAlign,
+ LLFontGL::NORMAL,
+ mStyle->getShadowType(),
+ length,
+ &right_x,
+ mEditor.getUseEllipses());
}
return right_x;
}
diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp
index 4b9faa0560..234e600ccd 100644
--- a/indra/llui/lltextvalidate.cpp
+++ b/indra/llui/lltextvalidate.cpp
@@ -188,6 +188,39 @@ namespace LLTextValidate
return success;
}
+ bool validateNonNegativeS32NoSpace(const LLWString &str)
+ {
+ LLLocale locale(LLLocale::USER_LOCALE);
+
+ LLWString test_str = str;
+ S32 len = test_str.length();
+ bool success = TRUE;
+ if(0 < len)
+ {
+ if('-' == test_str[0])
+ {
+ success = FALSE;
+ }
+ S32 i = 0;
+ while(success && (i < len))
+ {
+ if(!LLStringOps::isDigit(test_str[i]) || LLStringOps::isSpace(test_str[i++]))
+ {
+ success = FALSE;
+ }
+ }
+ }
+ if (success)
+ {
+ S32 val = strtol(wstring_to_utf8str(test_str).c_str(), NULL, 10);
+ if (val < 0)
+ {
+ success = FALSE;
+ }
+ }
+ return success;
+ }
+
bool validateAlphaNum(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h
index 84644be30c..5c830d7db3 100644
--- a/indra/llui/lltextvalidate.h
+++ b/indra/llui/lltextvalidate.h
@@ -46,6 +46,7 @@ namespace LLTextValidate
bool validateInt(const LLWString &str );
bool validatePositiveS32(const LLWString &str);
bool validateNonNegativeS32(const LLWString &str);
+ bool validateNonNegativeS32NoSpace(const LLWString &str);
bool validateAlphaNum(const LLWString &str );
bool validateAlphaNumSpace(const LLWString &str );
bool validateASCIIPrintableNoPipe(const LLWString &str);
diff --git a/indra/llui/lltimectrl.cpp b/indra/llui/lltimectrl.cpp
new file mode 100644
index 0000000000..9ea1e8815e
--- /dev/null
+++ b/indra/llui/lltimectrl.cpp
@@ -0,0 +1,432 @@
+/**
+ * @file lltimectrl.cpp
+ * @brief LLTimeCtrl base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltimectrl.h"
+
+#include "llui.h"
+#include "lluiconstants.h"
+
+#include "llbutton.h"
+#include "llfontgl.h"
+#include "lllineeditor.h"
+#include "llkeyboard.h"
+#include "llstring.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+
+static LLDefaultChildRegistry::Register<LLTimeCtrl> time_r("time");
+
+const U32 AMPM_LEN = 3;
+const U32 MINUTES_MIN = 0;
+const U32 MINUTES_MAX = 59;
+const U32 HOURS_MIN = 1;
+const U32 HOURS_MAX = 12;
+const U32 MINUTES_PER_HOUR = 60;
+const U32 MINUTES_PER_DAY = 24 * MINUTES_PER_HOUR;
+
+
+LLTimeCtrl::Params::Params()
+: label_width("label_width"),
+ snap_to("snap_to"),
+ allow_text_entry("allow_text_entry", true),
+ text_enabled_color("text_enabled_color"),
+ text_disabled_color("text_disabled_color"),
+ up_button("up_button"),
+ down_button("down_button")
+{}
+
+LLTimeCtrl::LLTimeCtrl(const LLTimeCtrl::Params& p)
+: LLUICtrl(p),
+ mLabelBox(NULL),
+ mTextEnabledColor(p.text_enabled_color()),
+ mTextDisabledColor(p.text_disabled_color()),
+ mTime(0),
+ mSnapToMin(5)
+{
+ static LLUICachedControl<S32> spinctrl_spacing ("UISpinctrlSpacing", 0);
+ static LLUICachedControl<S32> spinctrl_btn_width ("UISpinctrlBtnWidth", 0);
+ static LLUICachedControl<S32> spinctrl_btn_height ("UISpinctrlBtnHeight", 0);
+ S32 centered_top = getRect().getHeight();
+ S32 centered_bottom = getRect().getHeight() - 2 * spinctrl_btn_height;
+ S32 label_width = llclamp(p.label_width(), 0, llmax(0, getRect().getWidth() - 40));
+ S32 editor_left = label_width + spinctrl_spacing;
+
+ //================= Label =================//
+ if( !p.label().empty() )
+ {
+ LLRect label_rect( 0, centered_top, label_width, centered_bottom );
+ LLTextBox::Params params;
+ params.name("TimeCtrl Label");
+ params.rect(label_rect);
+ params.initial_value(p.label());
+ if (p.font.isProvided())
+ {
+ params.font(p.font);
+ }
+ mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
+ addChild(mLabelBox);
+
+ editor_left = label_rect.mRight + spinctrl_spacing;
+ }
+
+ S32 editor_right = getRect().getWidth() - spinctrl_btn_width - spinctrl_spacing;
+
+ //================= Editor ================//
+ LLRect editor_rect( editor_left, centered_top, editor_right, centered_bottom );
+ LLLineEditor::Params params;
+ params.name("SpinCtrl Editor");
+ params.rect(editor_rect);
+ if (p.font.isProvided())
+ {
+ params.font(p.font);
+ }
+
+ params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
+ params.max_length.chars(8);
+ params.keystroke_callback(boost::bind(&LLTimeCtrl::onTextEntry, this, _1));
+ mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
+ mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
+ mEditor->setPrevalidate(boost::bind(&LLTimeCtrl::isTimeStringValid, this, _1));
+ mEditor->setText(LLStringExplicit("12:00 AM"));
+ addChild(mEditor);
+
+ //================= Spin Buttons ==========//
+ LLButton::Params up_button_params(p.up_button);
+ up_button_params.rect = LLRect(editor_right + 1, getRect().getHeight(), editor_right + spinctrl_btn_width, getRect().getHeight() - spinctrl_btn_height);
+
+ up_button_params.click_callback.function(boost::bind(&LLTimeCtrl::onUpBtn, this));
+ up_button_params.mouse_held_callback.function(boost::bind(&LLTimeCtrl::onUpBtn, this));
+ mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);
+ addChild(mUpBtn);
+
+ LLButton::Params down_button_params(p.down_button);
+ down_button_params.rect = LLRect(editor_right + 1, getRect().getHeight() - spinctrl_btn_height, editor_right + spinctrl_btn_width, getRect().getHeight() - 2 * spinctrl_btn_height);
+ down_button_params.click_callback.function(boost::bind(&LLTimeCtrl::onDownBtn, this));
+ down_button_params.mouse_held_callback.function(boost::bind(&LLTimeCtrl::onDownBtn, this));
+ mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);
+ addChild(mDownBtn);
+
+ setUseBoundingRect( TRUE );
+}
+
+F32 LLTimeCtrl::getTime24() const
+{
+ // 0.0 - 23.99;
+ return mTime / 60.0f;
+}
+
+U32 LLTimeCtrl::getHours24() const
+{
+ return (U32) getTime24();
+}
+
+U32 LLTimeCtrl::getMinutes() const
+{
+ return mTime % MINUTES_PER_HOUR;
+}
+
+void LLTimeCtrl::setTime24(F32 time)
+{
+ time = llclamp(time, 0.0f, 23.99f); // fix out of range values
+ mTime = llround(time * MINUTES_PER_HOUR); // fixes values like 4.99999
+
+ updateText();
+}
+
+BOOL LLTimeCtrl::handleKeyHere(KEY key, MASK mask)
+{
+ if (mEditor->hasFocus())
+ {
+ if(key == KEY_UP)
+ {
+ onUpBtn();
+ return TRUE;
+ }
+ if(key == KEY_DOWN)
+ {
+ onDownBtn();
+ return TRUE;
+ }
+ if (key == KEY_RETURN)
+ {
+ onCommit();
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void LLTimeCtrl::onUpBtn()
+{
+ switch(getEditingPart())
+ {
+ case HOURS:
+ increaseHours();
+ break;
+ case MINUTES:
+ increaseMinutes();
+ break;
+ case DAYPART:
+ switchDayPeriod();
+ break;
+ default:
+ break;
+ }
+
+ updateText();
+ onCommit();
+}
+
+void LLTimeCtrl::onDownBtn()
+{
+ switch(getEditingPart())
+ {
+ case HOURS:
+ decreaseHours();
+ break;
+ case MINUTES:
+ decreaseMinutes();
+ break;
+ case DAYPART:
+ switchDayPeriod();
+ break;
+ default:
+ break;
+ }
+
+ updateText();
+ onCommit();
+}
+
+void LLTimeCtrl::onFocusLost()
+{
+ updateText();
+ onCommit();
+ LLUICtrl::onFocusLost();
+}
+
+void LLTimeCtrl::onTextEntry(LLLineEditor* line_editor)
+{
+ std::string time_str = line_editor->getText();
+ U32 h12 = parseHours(getHoursString(time_str));
+ U32 m = parseMinutes(getMinutesString(time_str));
+ bool pm = parseAMPM(getAMPMString(time_str));
+
+ if (h12 == 12)
+ {
+ h12 = 0;
+ }
+
+ U32 h24 = pm ? h12 + 12 : h12;
+
+ mTime = h24 * MINUTES_PER_HOUR + m;
+}
+
+bool LLTimeCtrl::isTimeStringValid(const LLWString &wstr)
+{
+ std::string str = wstring_to_utf8str(wstr);
+
+ return isHoursStringValid(getHoursString(str)) &&
+ isMinutesStringValid(getMinutesString(str)) &&
+ isPMAMStringValid(getAMPMString(str));
+}
+
+void LLTimeCtrl::increaseMinutes()
+{
+ mTime = (mTime + mSnapToMin) % MINUTES_PER_DAY - (mTime % mSnapToMin);
+}
+
+void LLTimeCtrl::increaseHours()
+{
+ mTime = (mTime + MINUTES_PER_HOUR) % MINUTES_PER_DAY;
+}
+
+void LLTimeCtrl::decreaseMinutes()
+{
+ if (mTime < mSnapToMin)
+ {
+ mTime = MINUTES_PER_DAY - mTime;
+ }
+
+ mTime -= (mTime % mSnapToMin) ? mTime % mSnapToMin : mSnapToMin;
+}
+
+void LLTimeCtrl::decreaseHours()
+{
+ if (mTime < MINUTES_PER_HOUR)
+ {
+ mTime = 23 * MINUTES_PER_HOUR + mTime;
+ }
+ else
+ {
+ mTime -= MINUTES_PER_HOUR;
+ }
+}
+
+bool LLTimeCtrl::isPM() const
+{
+ return mTime >= (MINUTES_PER_DAY / 2);
+}
+
+void LLTimeCtrl::switchDayPeriod()
+{
+ if (isPM())
+ {
+ mTime -= MINUTES_PER_DAY / 2;
+ }
+ else
+ {
+ mTime += MINUTES_PER_DAY / 2;
+ }
+}
+
+void LLTimeCtrl::updateText()
+{
+ U32 h24 = getHours24();
+ U32 m = getMinutes();
+ U32 h12 = h24 > 12 ? h24 - 12 : h24;
+
+ if (h12 == 0)
+ h12 = 12;
+
+ mEditor->setText(llformat("%d:%02d %s", h12, m, isPM() ? "PM":"AM"));
+}
+
+LLTimeCtrl::EEditingPart LLTimeCtrl::getEditingPart()
+{
+ S32 cur_pos = mEditor->getCursor();
+ std::string time_str = mEditor->getText();
+
+ S32 colon_index = time_str.find_first_of(':');
+
+ if (cur_pos <= colon_index)
+ {
+ return HOURS;
+ }
+ else if (cur_pos > colon_index && cur_pos <= (S32)(time_str.length() - AMPM_LEN))
+ {
+ return MINUTES;
+ }
+ else if (cur_pos > (S32)(time_str.length() - AMPM_LEN))
+ {
+ return DAYPART;
+ }
+
+ return NONE;
+}
+
+// static
+std::string LLTimeCtrl::getHoursString(const std::string& str)
+{
+ size_t colon_index = str.find_first_of(':');
+ std::string hours_str = str.substr(0, colon_index);
+
+ return hours_str;
+}
+
+// static
+std::string LLTimeCtrl::getMinutesString(const std::string& str)
+{
+ size_t colon_index = str.find_first_of(':');
+ ++colon_index;
+
+ int minutes_len = str.length() - colon_index - AMPM_LEN;
+ std::string minutes_str = str.substr(colon_index, minutes_len);
+
+ return minutes_str;
+}
+
+// static
+std::string LLTimeCtrl::getAMPMString(const std::string& str)
+{
+ return str.substr(str.size() - 2, 2); // returns last two characters
+}
+
+// static
+bool LLTimeCtrl::isHoursStringValid(const std::string& str)
+{
+ U32 hours;
+ if ((!LLStringUtil::convertToU32(str, hours) || (hours <= HOURS_MAX)) && str.length() < 3)
+ return true;
+
+ return false;
+}
+
+// static
+bool LLTimeCtrl::isMinutesStringValid(const std::string& str)
+{
+ U32 minutes;
+ if (!LLStringUtil::convertToU32(str, minutes) || (minutes <= MINUTES_MAX) && str.length() < 3)
+ return true;
+
+ return false;
+}
+
+// static
+bool LLTimeCtrl::isPMAMStringValid(const std::string& str)
+{
+ S32 len = str.length();
+
+ bool valid = (str[--len] == 'M') && (str[--len] == 'P' || str[len] == 'A');
+
+ return valid;
+}
+
+// static
+U32 LLTimeCtrl::parseHours(const std::string& str)
+{
+ U32 hours;
+ if (LLStringUtil::convertToU32(str, hours) && (hours >= HOURS_MIN) && (hours <= HOURS_MAX))
+ {
+ return hours;
+ }
+ else
+ {
+ return HOURS_MIN;
+ }
+}
+
+// static
+U32 LLTimeCtrl::parseMinutes(const std::string& str)
+{
+ U32 minutes;
+ if (LLStringUtil::convertToU32(str, minutes) && (minutes >= MINUTES_MIN) && (minutes <= MINUTES_MAX))
+ {
+ return minutes;
+ }
+ else
+ {
+ return MINUTES_MIN;
+ }
+}
+
+// static
+bool LLTimeCtrl::parseAMPM(const std::string& str)
+{
+ return str == "PM";
+}
diff --git a/indra/llui/lltimectrl.h b/indra/llui/lltimectrl.h
new file mode 100644
index 0000000000..b5f268c76a
--- /dev/null
+++ b/indra/llui/lltimectrl.h
@@ -0,0 +1,131 @@
+/**
+ * @file lltimectrl.h
+ * @brief Time control
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLTIMECTRL_H_
+#define LLTIMECTRL_H_
+
+#include "stdtypes.h"
+#include "llbutton.h"
+#include "v4color.h"
+#include "llrect.h"
+
+class LLLineEditor;
+
+class LLTimeCtrl
+: public LLUICtrl
+{
+ LOG_CLASS(LLTimeCtrl);
+public:
+ struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional<S32> label_width;
+ Optional<S32> snap_to;
+ Optional<bool> allow_text_entry;
+
+ Optional<LLUIColor> text_enabled_color;
+ Optional<LLUIColor> text_disabled_color;
+
+ Optional<LLButton::Params> up_button;
+ Optional<LLButton::Params> down_button;
+
+ Params();
+ };
+
+ F32 getTime24() const; // 0.0 - 24.0
+ U32 getHours24() const; // 0 - 23
+ U32 getMinutes() const; // 0 - 59
+
+ void setTime24(F32 time); // 0.0 - 23.98(3)
+
+protected:
+ LLTimeCtrl(const Params&);
+ friend class LLUICtrlFactory;
+
+private:
+
+ enum EDayPeriod
+ {
+ AM,
+ PM
+ };
+
+ enum EEditingPart
+ {
+ HOURS,
+ MINUTES,
+ DAYPART,
+ NONE
+ };
+
+ virtual void onFocusLost();
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ void onUpBtn();
+ void onDownBtn();
+ void onTextEntry(LLLineEditor* line_editor);
+
+ bool isTimeStringValid(const LLWString& wstr);
+
+ void increaseMinutes();
+ void increaseHours();
+
+ void decreaseMinutes();
+ void decreaseHours();
+
+ bool isPM() const;
+ void switchDayPeriod();
+
+ void updateText();
+
+ EEditingPart getEditingPart();
+
+ static std::string getHoursString(const std::string& str);
+ static std::string getMinutesString(const std::string& str);
+ static std::string getAMPMString(const std::string& str);
+
+ static bool isHoursStringValid(const std::string& str);
+ static bool isMinutesStringValid(const std::string& str);
+ static bool isPMAMStringValid(const std::string& str);
+
+ static U32 parseHours(const std::string& str);
+ static U32 parseMinutes(const std::string& str);
+ static bool parseAMPM(const std::string& str);
+
+ class LLTextBox* mLabelBox;
+
+ class LLLineEditor* mEditor;
+ LLUIColor mTextEnabledColor;
+ LLUIColor mTextDisabledColor;
+
+ class LLButton* mUpBtn;
+ class LLButton* mDownBtn;
+
+ U32 mTime; // minutes since midnight: 0 - 1439
+ U32 mSnapToMin; // interval in minutes to snap to
+
+ BOOL mAllowEdit;
+};
+#endif /* LLTIMECTRL_H_ */
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 0a06b5e74f..d58df5801b 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -68,6 +68,7 @@ LLUICtrl::ControlVisibility::ControlVisibility()
LLUICtrl::Params::Params()
: tab_stop("tab_stop", true),
chrome("chrome", false),
+ requests_front("requests_front", false),
label("label"),
initial_value("value"),
init_callback("init_callback"),
@@ -96,9 +97,10 @@ const LLUICtrl::Params& LLUICtrl::getDefaultParams()
LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
: LLView(p),
- mTentative(FALSE),
mIsChrome(FALSE),
+ mRequestsFront(p.requests_front),
mTabStop(FALSE),
+ mTentative(FALSE),
mViewModel(viewmodel),
mControlVariable(NULL),
mEnabledControlVariable(NULL),
@@ -123,6 +125,8 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLView::initFromParams(p);
+ mRequestsFront = p.requests_front;
+
setIsChrome(p.chrome);
setControlName(p.control_name);
if(p.enabled_controls.isProvided())
@@ -403,6 +407,36 @@ LLViewModel* LLUICtrl::getViewModel() const
return mViewModel;
}
+//virtual
+BOOL LLUICtrl::postBuild()
+{
+ //
+ // Find all of the children that want to be in front and move them to the front
+ //
+
+ if (getChildCount() > 0)
+ {
+ std::vector<LLUICtrl*> childrenToMoveToFront;
+
+ for (LLView::child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it)
+ {
+ LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(*child_it);
+
+ if (uictrl && uictrl->mRequestsFront)
+ {
+ childrenToMoveToFront.push_back(uictrl);
+ }
+ }
+
+ for (std::vector<LLUICtrl*>::iterator it = childrenToMoveToFront.begin(); it != childrenToMoveToFront.end(); ++it)
+ {
+ sendChildToFront(*it);
+ }
+ }
+
+ return LLView::postBuild();
+}
+
bool LLUICtrl::setControlValue(const LLSD& value)
{
if (mControlVariable)
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index b37e9f6b1b..09bed9b958 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -94,7 +94,8 @@ public:
{
Optional<std::string> label;
Optional<bool> tab_stop,
- chrome;
+ chrome,
+ requests_front;
Optional<LLSD> initial_value;
Optional<CommitCallbackParam> init_callback,
@@ -143,6 +144,8 @@ protected:
virtual LLViewModel* getViewModel() const;
// We shouldn't ever need to set this directly
//virtual void setViewModel(const LLViewModelPtr&);
+
+ virtual BOOL postBuild();
public:
// LLView interface
@@ -301,8 +304,9 @@ protected:
private:
- BOOL mTabStop;
BOOL mIsChrome;
+ BOOL mRequestsFront;
+ BOOL mTabStop;
BOOL mTentative;
LLRootHandle<LLUICtrl> mUICtrlHandle;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 245126d178..8803d106ba 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1299,15 +1299,7 @@ void LLView::drawChildren()
{
if (!mChildList.empty())
{
- static const LLRect* rootRect = NULL;
-
- if (!mParentView)
- {
- rootRect = &mRect;
- }
-
- LLRect screenRect;
-
+ LLView* rootp = LLUI::getRootView();
++sDepth;
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter)
@@ -1317,9 +1309,8 @@ void LLView::drawChildren()
if (viewp->getVisible() && viewp->getRect().isValid())
{
- // Only draw views that are within the root view
- localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect->overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
+ LLRect screen_rect = viewp->calcScreenRect();
+ if ( rootp->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
{
LLUI::pushMatrix();
{
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index e09ef33d49..3cd61e574e 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -95,7 +95,7 @@ namespace LLInitParam
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
- mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
}
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; }
diff --git a/indra/llvfs/CMakeLists.txt b/indra/llvfs/CMakeLists.txt
index b6d1ce61e5..2c581cf8d6 100644
--- a/indra/llvfs/CMakeLists.txt
+++ b/indra/llvfs/CMakeLists.txt
@@ -62,11 +62,15 @@ list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES})
add_library (llvfs ${llvfs_SOURCE_FILES})
-target_link_libraries(llvfs
+set(vfs_BOOST_LIBRARIES
${BOOST_FILESYSTEM_LIBRARY}
${BOOST_SYSTEM_LIBRARY}
)
+target_link_libraries(llvfs
+ ${vfs_BOOST_LIBRARIES}
+ )
+
if (DARWIN)
include(CMakeFindFrameworks)
find_library(CARBON_LIBRARY Carbon)
@@ -76,15 +80,21 @@ endif (DARWIN)
# Add tests
if (LL_TESTS)
- include(LLAddBuildTest)
- # UNIT TESTS
- SET(llvfs_TEST_SOURCE_FILES
- # none so far
- )
- LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}")
-
- # INTEGRATION TESTS
- set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
- # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
- LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llvfs_TEST_SOURCE_FILES
+ lldiriterator.cpp
+ )
+
+ set_source_files_properties(lldiriterator.cpp
+ PROPERTIES
+ LL_TEST_ADDITIONAL_LIBRARIES "${vfs_BOOST_LIBRARIES}"
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}")
+
+ # INTEGRATION TESTS
+ set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+
+ # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
+ LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")
endif (LL_TESTS)
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 8f48f92e2a..489bc3e4a7 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -258,38 +258,6 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma
return (file_count);
}
-S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
-{
- glob_t g;
- S32 result = 0;
-
- std::string tmp_str;
- tmp_str = dirname;
- tmp_str += mask;
-
- if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
- {
- int i;
-
- for(i = 0; i < g.gl_pathc; i++)
- {
-// llinfos << "deleteFilesInDir: deleting number " << i << ", path is " << g.gl_pathv[i] << llendl;
-
- if(unlink(g.gl_pathv[i]) != 0)
- {
- result = errno;
-
- llwarns << "Problem removing " << g.gl_pathv[i] << " - errorcode: "
- << result << llendl;
- }
- }
-
- globfree(&g);
- }
-
- return(result);
-}
-
std::string LLDir_Mac::getCurPath()
{
char tmp_str[LL_MAX_PATH]; /* Flawfinder: ignore */
diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h
index bc3f0fac00..d190d70be4 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -44,7 +44,6 @@ public:
/*virtual*/ void initAppDirs(const std::string &app_name,
const std::string& app_read_only_data_dir);
- virtual S32 deleteFilesInDir(const std::string &dirname, const std::string &mask);
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
virtual BOOL fileExists(const std::string &filename) const;
diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp
index 041436ed92..25550321f0 100644
--- a/indra/llvfs/lldiriterator.cpp
+++ b/indra/llvfs/lldiriterator.cpp
@@ -121,6 +121,14 @@ bool LLDirIterator::Impl::next(std::string &fname)
return found;
}
+/**
+Converts the incoming glob into a regex. This involves
+converting incoming glob expressions to regex equivilents and
+at the same time, escaping any regex meaningful characters which
+do not have glob meaning, i.e.
+ .()+|^$
+in the input.
+*/
std::string glob_to_regex(const std::string& glob)
{
std::string regex;
@@ -135,9 +143,6 @@ std::string glob_to_regex(const std::string& glob)
switch (c)
{
- case '.':
- regex+="\\.";
- break;
case '*':
if (glob.begin() == i)
{
@@ -170,8 +175,16 @@ std::string glob_to_regex(const std::string& glob)
case '!':
regex+= square_brace_open ? '^' : c;
break;
+ case '.': // This collection have different regex meaning
+ case '^': // and so need escaping.
+ case '(':
+ case ')':
+ case '+':
+ case '|':
+ case '$':
+ regex += '\\';
default:
- regex+=c;
+ regex += c;
break;
}
diff --git a/indra/llvfs/tests/lldiriterator_test.cpp b/indra/llvfs/tests/lldiriterator_test.cpp
new file mode 100644
index 0000000000..505d86faa7
--- /dev/null
+++ b/indra/llvfs/tests/lldiriterator_test.cpp
@@ -0,0 +1,65 @@
+/**
+ * @file lldiriterator_test.cpp
+ * @date 2011-06
+ * @brief LLDirIterator test cases.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.,
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltut.h"
+#include "../lldiriterator.h"
+
+
+namespace tut
+{
+
+ struct LLDirIteratorFixture
+ {
+ LLDirIteratorFixture()
+ {
+ }
+ };
+ typedef test_group<LLDirIteratorFixture> LLDirIteratorTest_factory;
+ typedef LLDirIteratorTest_factory::object LLDirIteratorTest_t;
+ LLDirIteratorTest_factory tf("LLDirIterator");
+
+ /*
+ CHOP-662 was originally introduced to deal with crashes deleting files from
+ a directory (VWR-25500). However, this introduced a crash looking for
+ old chat logs as the glob_to_regex function in lldiriterator wasn't escaping lots of regexp characters
+ */
+ void test_chop_662(void)
+ {
+ // Check a selection of bad group names from the crash reports
+ LLDirIterator iter(".","+bad-group-name]+??-??.*");
+ LLDirIterator iter1(".","))--@---bad-group-name2((??-??.*\\.txt");
+ LLDirIterator iter2(".","__^v--x)Cuide d sua vida(x--v^__??-??.*");
+ }
+
+ template<> template<>
+ void LLDirIteratorTest_t::test<1>()
+ {
+ test_chop_662();
+ }
+
+}
diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp
index 4dfaaed4e1..c87617c9ff 100644
--- a/indra/llwindow/llkeyboardheadless.cpp
+++ b/indra/llwindow/llkeyboardheadless.cpp
@@ -46,5 +46,28 @@ MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event)
{ return MASK_NONE; }
void LLKeyboardHeadless::scanKeyboard()
-{ }
+{
+ for (S32 key = 0; key < KEY_COUNT; key++)
+ {
+ // Generate callback if any event has occurred on this key this frame.
+ // Can't just test mKeyLevel, because this could be a slow frame and
+ // key might have gone down then up. JC
+ if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
+ {
+ mCurScanKey = key;
+ mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
+ }
+ }
+
+ // Reset edges for next frame
+ for (S32 key = 0; key < KEY_COUNT; key++)
+ {
+ mKeyUp[key] = FALSE;
+ mKeyDown[key] = FALSE;
+ if (mKeyLevel[key])
+ {
+ mKeyLevelFrameCount[key]++;
+ }
+ }
+}
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index b3312798dd..c024fd405e 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -40,7 +40,7 @@ namespace LLInitParam
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
- mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
}
//
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index a853999e94..35c889b69f 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -34,6 +34,8 @@
#include <boost/unordered_map.hpp>
#include <boost/shared_ptr.hpp>
+#include "llerror.h"
+
namespace LLInitParam
{
template<typename T> const T& defaultValue() { static T value; return value; }
@@ -302,8 +304,9 @@ namespace LLInitParam
private:
friend class BaseBlock;
- U16 mEnclosingBlockOffset;
- bool mIsProvided;
+ U32 mEnclosingBlockOffset:31;
+ U32 mIsProvided:1;
+
};
// various callbacks and constraints associated with an individual param
diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l
index 188c9e1950..4e103ae2ba 100644
--- a/indra/lscript/lscript_compile/indra.l
+++ b/indra/lscript/lscript_compile/indra.l
@@ -603,6 +603,8 @@ extern "C" { int yyerror(const char *fmt, ...); }
"PARCEL_DETAILS_OWNER" { count(); yylval.ival = PARCEL_DETAILS_OWNER; return(INTEGER_CONSTANT); }
"PARCEL_DETAILS_GROUP" { count(); yylval.ival = PARCEL_DETAILS_GROUP; return(INTEGER_CONSTANT); }
"PARCEL_DETAILS_AREA" { count(); yylval.ival = PARCEL_DETAILS_AREA; return(INTEGER_CONSTANT); }
+"PARCEL_DETAILS_ID" { count(); yylval.ival = PARCEL_DETAILS_ID; return(INTEGER_CONSTANT); }
+"PARCEL_DETAILS_SEE_AVATARS" { count(); yylval.ival = PARCEL_DETAILS_SEE_AVATARS; return(INTEGER_CONSTANT); }
"STRING_TRIM_HEAD" { count(); yylval.ival = STRING_TRIM_HEAD; return(INTEGER_CONSTANT); }
"STRING_TRIM_TAIL" { count(); yylval.ival = STRING_TRIM_TAIL; return(INTEGER_CONSTANT); }
diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp
index 967c69fea9..7ffe53a307 100644
--- a/indra/lscript/lscript_library/lscript_library.cpp
+++ b/indra/lscript/lscript_library/lscript_library.cpp
@@ -461,6 +461,9 @@ void LLScriptLibrary::init()
addFunction(10.f, 0.f, dummy_func, "llGetDisplayName", "s", "k");
addFunction(10.f, 0.f, dummy_func, "llRequestDisplayName", "k", "k");
+ addFunction(10.f, 0.f, dummy_func, "llGetEnv", "s", "s");
+ addFunction(10.f, 0.f, dummy_func, "llRegionSayTo", NULL, "kis");
+
// energy, sleep, dummy_func, name, return type, parameters, help text, gods-only
// IF YOU ADD NEW SCRIPT CALLS, YOU MUST PUT THEM AT THE END OF THIS LIST.
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index 9ba8edbb59..fca071c628 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -1168,6 +1168,72 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
authResponse(message_in);
}
else
+ if(message_name == "js_enable_object")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ bool enable = message_in.getValueBoolean( "enable" );
+ LLQtWebKit::getInstance()->setSLObjectEnabled( enable );
+#endif
+ }
+ else
+ if(message_name == "js_agent_location")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ F32 x = message_in.getValueReal("x");
+ F32 y = message_in.getValueReal("y");
+ F32 z = message_in.getValueReal("z");
+ LLQtWebKit::getInstance()->setAgentLocation( x, y, z );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_global_location")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ F32 x = message_in.getValueReal("x");
+ F32 y = message_in.getValueReal("y");
+ F32 z = message_in.getValueReal("z");
+ LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_orientation")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ F32 angle = message_in.getValueReal("angle");
+ LLQtWebKit::getInstance()->setAgentOrientation( angle );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_region")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& region = message_in.getValue("region");
+ LLQtWebKit::getInstance()->setAgentRegion( region );
+ LLQtWebKit::getInstance()->emitLocation();
+#endif
+ }
+ else
+ if(message_name == "js_agent_maturity")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& maturity = message_in.getValue("maturity");
+ LLQtWebKit::getInstance()->setAgentMaturity( maturity );
+ LLQtWebKit::getInstance()->emitMaturity();
+#endif
+ }
+ else
+ if(message_name == "js_agent_language")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& language = message_in.getValue("language");
+ LLQtWebKit::getInstance()->setAgentLanguage( language );
+ LLQtWebKit::getInstance()->emitLanguage();
+#endif
+ }
+ else
{
// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl;
}
@@ -1325,3 +1391,4 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void
return 0;
}
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index cbf22b75e8..da9a145423 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -77,6 +77,7 @@ include_directories(
set(viewer_SOURCE_FILES
groupchatlistener.cpp
+ llaccountingquotamanager.cpp
llagent.cpp
llagentaccess.cpp
llagentcamera.cpp
@@ -119,7 +120,6 @@ set(viewer_SOURCE_FILES
llchiclet.cpp
llclassifiedinfo.cpp
llclassifiedstatsresponder.cpp
- llcloud.cpp
llcofwearables.cpp
llcolorswatch.cpp
llcommanddispatcherlistener.cpp
@@ -130,6 +130,7 @@ set(viewer_SOURCE_FILES
llcurrencyuimanager.cpp
llcylinder.cpp
lldateutil.cpp
+ lldaycyclemanager.cpp
lldebugmessagebox.cpp
lldebugview.cpp
lldelayedgestureerror.cpp
@@ -149,6 +150,7 @@ set(viewer_SOURCE_FILES
lldrawpoolwlsky.cpp
lldriverparam.cpp
lldynamictexture.cpp
+ llenvmanager.cpp
llemote.cpp
lleventnotifier.cpp
lleventpoll.cpp
@@ -178,9 +180,12 @@ set(viewer_SOURCE_FILES
llfloaterbuyland.cpp
llfloatercamera.cpp
llfloatercolorpicker.cpp
- llfloaterdaycycle.cpp
+ llfloaterdeleteenvpreset.cpp
llfloaterdisplayname.cpp
- llfloaterenvsettings.cpp
+ llfloatereditdaycycle.cpp
+ llfloatereditsky.cpp
+ llfloatereditwater.cpp
+ llfloaterenvironmentsettings.cpp
llfloaterevent.cpp
llfloaterfonttest.cpp
llfloatergesture.cpp
@@ -233,16 +238,15 @@ set(viewer_SOURCE_FILES
llfloateruipreview.cpp
llfloaterurlentry.cpp
llfloatervoiceeffect.cpp
- llfloaterwater.cpp
llfloaterwebcontent.cpp
llfloaterwhitelistentry.cpp
- llfloaterwindlight.cpp
llfloaterwindowsize.cpp
llfloaterworldmap.cpp
llfolderview.cpp
llfolderviewitem.cpp
llfollowcam.cpp
llfriendcard.cpp
+ llgesturelistener.cpp
llgesturemgr.cpp
llgiveinventory.cpp
llglsandbox.cpp
@@ -320,6 +324,7 @@ set(viewer_SOURCE_FILES
llnearbychat.cpp
llnearbychatbar.cpp
llnearbychathandler.cpp
+ llnearbychatbarlistener.cpp
llnetmap.cpp
llnotificationalerthandler.cpp
llnotificationgrouphandler.cpp
@@ -358,6 +363,9 @@ set(viewer_SOURCE_FILES
llpanellogin.cpp
llpanelloginlistener.cpp
llpanelmaininventory.cpp
+ llpanelmarketplaceinbox.cpp
+ llpanelmarketplaceinboxinventory.cpp
+ llpanelmarketplaceoutbox.cpp
llpanelmediasettingsgeneral.cpp
llpanelmediasettingspermissions.cpp
llpanelmediasettingssecurity.cpp
@@ -408,6 +416,7 @@ set(viewer_SOURCE_FILES
llproductinforequest.cpp
llprogressview.cpp
llrecentpeople.cpp
+ llregioninfomodel.cpp
llregionposition.cpp
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
@@ -516,7 +525,7 @@ set(viewer_SOURCE_FILES
llviewerfloaterreg.cpp
llviewerfoldertype.cpp
llviewergenericmessage.cpp
- llviewergesture.cpp
+ llviewergesture.cpp
llviewerhelp.cpp
llviewerhelputil.cpp
llviewerhome.cpp
@@ -563,7 +572,6 @@ set(viewer_SOURCE_FILES
llvoavatardefines.cpp
llvoavatarself.cpp
llvocache.cpp
- llvoclouds.cpp
llvograss.cpp
llvoground.cpp
llvoicecallhandler.cpp
@@ -592,6 +600,7 @@ set(viewer_SOURCE_FILES
llwind.cpp
llwlanimator.cpp
llwldaycycle.cpp
+ llwlhandlers.cpp
llwlparammanager.cpp
llwlparamset.cpp
llworld.cpp
@@ -626,6 +635,7 @@ set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
groupchatlistener.h
+ llaccountingquotamanager.h
llagent.h
llagentaccess.h
llagentcamera.h
@@ -669,7 +679,6 @@ set(viewer_HEADER_FILES
llchiclet.h
llclassifiedinfo.h
llclassifiedstatsresponder.h
- llcloud.h
llcofwearables.h
llcolorswatch.h
llcommanddispatcherlistener.h
@@ -680,6 +689,7 @@ set(viewer_HEADER_FILES
llcurrencyuimanager.h
llcylinder.h
lldateutil.h
+ lldaycyclemanager.h
lldebugmessagebox.h
lldebugview.h
lldelayedgestureerror.h
@@ -690,7 +700,6 @@ set(viewer_HEADER_FILES
lldrawpoolalpha.h
lldrawpoolavatar.h
lldrawpoolbump.h
- lldrawpoolclouds.h
lldrawpoolground.h
lldrawpoolsimple.h
lldrawpoolsky.h
@@ -701,6 +710,7 @@ set(viewer_HEADER_FILES
lldriverparam.h
lldynamictexture.h
llemote.h
+ llenvmanager.h
lleventnotifier.h
lleventpoll.h
llexpandabletextbox.h
@@ -729,9 +739,12 @@ set(viewer_HEADER_FILES
llfloaterbuyland.h
llfloatercamera.h
llfloatercolorpicker.h
- llfloaterdaycycle.h
+ llfloaterdeleteenvpreset.h
llfloaterdisplayname.h
- llfloaterenvsettings.h
+ llfloatereditdaycycle.h
+ llfloatereditsky.h
+ llfloatereditwater.h
+ llfloaterenvironmentsettings.h
llfloaterevent.h
llfloaterfonttest.h
llfloatergesture.h
@@ -784,10 +797,8 @@ set(viewer_HEADER_FILES
llfloateruipreview.h
llfloaterurlentry.h
llfloatervoiceeffect.h
- llfloaterwater.h
llfloaterwebcontent.h
llfloaterwhitelistentry.h
- llfloaterwindlight.h
llfloaterwindowsize.h
llfloaterworldmap.h
llfolderview.h
@@ -795,6 +806,7 @@ set(viewer_HEADER_FILES
llfolderviewitem.h
llfollowcam.h
llfriendcard.h
+ llgesturelistener.h
llgesturemgr.h
llgiveinventory.h
llgroupactions.h
@@ -871,6 +883,7 @@ set(viewer_HEADER_FILES
llnearbychat.h
llnearbychatbar.h
llnearbychathandler.h
+ llnearbychatbarlistener.h
llnetmap.h
llnotificationhandler.h
llnotificationmanager.h
@@ -903,6 +916,9 @@ set(viewer_HEADER_FILES
llpanellogin.h
llpanelloginlistener.h
llpanelmaininventory.h
+ llpanelmarketplaceinbox.h
+ llpanelmarketplaceinboxinventory.h
+ llpanelmarketplaceoutbox.h
llpanelmediasettingsgeneral.h
llpanelmediasettingspermissions.h
llpanelmediasettingssecurity.h
@@ -953,6 +969,7 @@ set(viewer_HEADER_FILES
llproductinforequest.h
llprogressview.h
llrecentpeople.h
+ llregioninfomodel.h
llregionposition.h
llremoteparcelrequest.h
llresourcedata.h
@@ -992,7 +1009,7 @@ set(viewer_HEADER_FILES
llsurface.h
llsurfacepatch.h
llsyswellitem.h
- llsyswellwindow.h
+ llsyswellwindow.h
lltable.h
llteleporthistory.h
llteleporthistorystorage.h
@@ -1064,7 +1081,7 @@ set(viewer_HEADER_FILES
llviewerfloaterreg.h
llviewerfoldertype.h
llviewergenericmessage.h
- llviewergesture.h
+ llviewergesture.h
llviewerhelp.h
llviewerhome.h
llviewerinventory.h
@@ -1108,7 +1125,6 @@ set(viewer_HEADER_FILES
llvoavatardefines.h
llvoavatarself.h
llvocache.h
- llvoclouds.h
llvograss.h
llvoground.h
llvoicechannel.h
@@ -1137,6 +1153,7 @@ set(viewer_HEADER_FILES
llwind.h
llwlanimator.h
llwldaycycle.h
+ llwlhandlers.h
llwlparammanager.h
llwlparamset.h
llworld.h
@@ -1219,7 +1236,7 @@ if (WINDOWS)
# precompiled header configuration
# llviewerprecompiledheaders.cpp generates
# the .pch file.
- # All sources added to viewer_SOURCE_FILES
+ # All sources added to viewer_SOURCE_FILES
# at this point use it.
if(USE_PRECOMPILED_HEADERS)
set_source_files_properties(llviewerprecompiledheaders.cpp
@@ -1228,7 +1245,7 @@ if (WINDOWS)
)
set(viewer_SOURCE_FILES "${viewer_SOURCE_FILES}" llviewerprecompiledheaders.cpp)
endif(USE_PRECOMPILED_HEADERS)
-
+
# Add resource files to the project.
# viewerRes.rc is the only buildable file, but
# the rest are all dependencies of it.
@@ -1273,8 +1290,8 @@ if (WINDOWS)
set_source_files_properties(${viewer_RESOURCE_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
- set(viewer_RESOURCE_FILES
- res/viewerRes.rc
+ set(viewer_RESOURCE_FILES
+ res/viewerRes.rc
${viewer_RESOURCE_FILES}
)
@@ -1282,7 +1299,7 @@ if (WINDOWS)
if (NOT STANDALONE)
list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES})
- endif (NOT STANDALONE)
+ endif (NOT STANDALONE)
find_library(DINPUT_LIBRARY dinput8 ${DIRECTX_LIBRARY_DIR})
find_library(DXGUID_LIBRARY dxguid ${DIRECTX_LIBRARY_DIR})
@@ -1459,7 +1476,7 @@ set(PACKAGE ON CACHE BOOL
"Add a package target that builds an installer package.")
if (WINDOWS)
- set_target_properties(${VIEWER_BINARY_NAME}
+ set_target_properties(${VIEWER_BINARY_NAME}
PROPERTIES
# *TODO -reenable this once we get server usage sorted out
#LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\""
@@ -1491,7 +1508,7 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll
)
endif(USE_GOOGLE_PERFTOOLS)
-
+
set(COPY_INPUT_DEPENDENCIES
# The following commented dependencies are determined at variably at build time. Can't do this here.
@@ -1589,24 +1606,24 @@ if (WINDOWS)
--grid=${GRID}
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat
- DEPENDS
+ DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
stage_third_party_libs
${COPY_INPUT_DEPENDENCIES}
COMMENT "Performing viewer_manifest copy"
)
-
- add_custom_target(copy_w_viewer_manifest ALL DEPENDS ${CMAKE_CFG_INTDIR}/copy_touched.bat)
+
+ add_custom_target(copy_w_viewer_manifest ALL DEPENDS ${CMAKE_CFG_INTDIR}/copy_touched.bat)
add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon copy_w_viewer_manifest)
-
+
if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
-
- add_dependencies(${VIEWER_BINARY_NAME}
- SLPlugin
- windows-updater
+
+ add_dependencies(${VIEWER_BINARY_NAME}
+ SLPlugin
+ windows-updater
windows-crash-logger
)
@@ -1616,7 +1633,7 @@ if (WINDOWS)
TARGET ${VIEWER_BINARY_NAME} POST_BUILD
COMMAND ${CMAKE_SOURCE_DIR}/tools/vstool/vstool.exe
ARGS
- --solution
+ --solution
${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.sln
--workingdir
${VIEWER_BINARY_NAME}
@@ -1634,12 +1651,12 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CFG_INTDIR}
- DEPENDS
- lleventhost
+ DEPENDS
+ lleventhost
${EVENT_HOST_SCRIPTS}
${CMAKE_CURRENT_SOURCE_DIR}/event_host_manifest.py
)
-
+
add_custom_command(
OUTPUT ${CMAKE_CFG_INTDIR}/touched.bat
COMMAND ${PYTHON_EXECUTABLE}
@@ -1655,15 +1672,15 @@ if (WINDOWS)
--login_channel=${VIEWER_LOGIN_CHANNEL}
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat
- DEPENDS
- ${VIEWER_BINARY_NAME}
+ DEPENDS
+ ${VIEWER_BINARY_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
${COPY_INPUT_DEPENDENCIES}
)
- add_custom_target(package ALL DEPENDS
+ add_custom_target(package ALL DEPENDS
${CMAKE_CFG_INTDIR}/touched.bat
- windows-setup-build-all
+ windows-setup-build-all
)
# temporarily disable packaging of event_host until hg subrepos get
# sorted out on the parabuild cluster...
@@ -1731,7 +1748,7 @@ else (USE_KDU)
${LLIMAGEJ2COJ_LIBRARIES}
)
endif (USE_KDU)
-
+
build_version(viewer)
set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
@@ -1790,13 +1807,13 @@ if (LINUX)
--dest=${CMAKE_CURRENT_BINARY_DIR}/packaged
--grid=${GRID}
--source=${CMAKE_CURRENT_SOURCE_DIR}
- DEPENDS
+ DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
${COPY_INPUT_DEPENDENCIES}
COMMENT "Performing viewer_manifest copy"
)
-
- add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched)
+
+ add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched)
if (PACKAGE)
add_custom_target(package ALL DEPENDS ${product}.tar.bz2)
@@ -1841,7 +1858,7 @@ if (DARWIN)
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-updater mac-crash-logger)
if (PACKAGE)
- add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME})
+ add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME})
add_custom_command(
TARGET package POST_BUILD
@@ -1936,7 +1953,7 @@ if (LL_TESTS)
)
##################################################
- # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
+ # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
##################################################
# if(USE_PRECOMPILED_HEADERS)
# set_source_files_properties(
@@ -1950,33 +1967,33 @@ if (LL_TESTS)
#set(TEST_DEBUG on)
set(test_sources llcapabilitylistener.cpp)
##################################################
- # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
+ # DISABLING PRECOMPILED HEADERS USAGE FOR TESTS
##################################################
# if(USE_PRECOMPILED_HEADERS)
# set(test_sources "${test_sources}" llviewerprecompiledheaders.cpp)
# endif(USE_PRECOMPILED_HEADERS)
- set(test_libs
- ${LLMESSAGE_LIBRARIES}
- ${WINDOWS_LIBRARIES}
+ set(test_libs
+ ${LLMESSAGE_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
${GOOGLEMOCK_LIBRARIES}
)
- LL_ADD_INTEGRATION_TEST(llcapabilitylistener
- "${test_sources}"
+ LL_ADD_INTEGRATION_TEST(llcapabilitylistener
+ "${test_sources}"
"${test_libs}"
${PYTHON_EXECUTABLE}
"${CMAKE_SOURCE_DIR}/llmessage/tests/test_llsdmessage_peer.py"
)
- set(test_libs
- ${LLMESSAGE_LIBRARIES}
- ${WINDOWS_LIBRARIES}
+ set(test_libs
+ ${LLMESSAGE_LIBRARIES}
+ ${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
- ${LLCOMMON_LIBRARIES}
+ ${LLCOMMON_LIBRARIES}
${GOOGLEMOCK_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
@@ -2024,6 +2041,22 @@ if (LL_TESTS)
#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
#ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
+include(LLAddBuildTest)
+SET(viewer_TEST_SOURCE_FILES
+ llagentaccess.cpp
+ llwlparammanager.cpp
+ # Not *actually* a unit test, it's an integration test.
+ # Because it won't work in the new unit test iface, i've commented out
+ # and notified Nat. Delete this when it's replaced!
+ # + poppy & brad 2009-06-05
+ # llcapabilitylistener.cpp
+ )
+set_source_files_properties(
+ ${viewer_TEST_SOURCE_FILES}
+ PROPERTIES
+ LL_TEST_ADDITIONAL_SOURCE_FILES llviewerprecompiledheaders.cpp
+ )
+
endif (LL_TESTS)
check_message_template(${VIEWER_BINARY_NAME})
diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml
index d085475c6c..6e3673e7d9 100644
--- a/indra/newview/app_settings/keys.xml
+++ b/indra/newview/app_settings/keys.xml
@@ -181,7 +181,7 @@
<binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
</third_person>
- # Basic editing camera control
+ <!-- Basic editing camera control -->
<edit>
<binding key="A" mask="NONE" command="spin_around_cw"/>
<binding key="D" mask="NONE" command="spin_around_ccw"/>
diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini
index 263b73ba23..9fa4046fdf 100644
--- a/indra/newview/app_settings/keywords.ini
+++ b/indra/newview/app_settings/keywords.ini
@@ -498,6 +498,7 @@ PARCEL_DETAILS_OWNER Used with llGetParcelDetails to get the parcel owner id.
PARCEL_DETAILS_GROUP Used with llGetParcelDetails to get the parcel group id.
PARCEL_DETAILS_AREA Used with llGetParcelDetails to get the parcel area in square meters.
PARCEL_DETAILS_ID Used with llGetParcelDetails to get the parcel id.
+PARCEL_DETAILS_SEE_AVATARS Used with llGetParcelDetails to get the avatars visibility setting.
STRING_TRIM_HEAD Used with llStringTrim to trim leading spaces from a string.
STRING_TRIM_TAIL Used with llStringTrim to trim trailing spaces from a string.
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index 937c4e4c6a..9f4e89691f 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -20,6 +20,7 @@
<key>tags</key>
<array>
<string>AppInit</string>
+ <string>Capabilities</string>
<string>SystemInfo</string>
<string>TextureCache</string>
<string>AppCache</string>
@@ -43,6 +44,7 @@
<array>
<!-- sample entry for debugging a specific item -->
<!-- <string>Voice</string> -->
+ <string>Capabilities</string>
</array>
</map>
</array>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 78db307d64..4b62e376b5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -708,6 +708,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>BrowserEnableJSObject</key>
+ <map>
+ <key>Comment</key>
+ <string>(WARNING: Advanced feature. Use if you are aware of the implications). Enable or disable the viewer to Javascript bridge object.</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>BlockAvatarAppearanceMessages</key>
<map>
<key>Comment</key>
@@ -3047,6 +3058,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>EnableGestureSounds</key>
+ <map>
+ <key>Comment</key>
+ <string>Play sounds from gestures</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>EnableMouselook</key>
<map>
<key>Comment</key>
@@ -3245,17 +3267,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>FirstLoginThisInstall</key>
- <map>
- <key>Comment</key>
- <string>Specifies that you have not successfully logged in since you installed the latest update</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>FirstName</key>
<map>
<key>Comment</key>
@@ -3980,7 +3991,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
+ <string>http://search-beta.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
</map>
<key>WebProfileURL</key>
<map>
@@ -4169,6 +4180,28 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>InventoryDisplayInbox</key>
+ <map>
+ <key>Comment</key>
+ <string>Override received items inventory inbox display</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>InventoryDisplayOutbox</key>
+ <map>
+ <key>Comment</key>
+ <string>Override merchant inventory outbox display</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>InventoryLinking</key>
<map>
<key>Comment</key>
@@ -4411,6 +4444,17 @@
<key>Value</key>
<real>2.0</real>
</map>
+ <key>LastInventoryInboxExpand</key>
+ <map>
+ <key>Comment</key>
+ <string>The last time the received items inbox was expanded.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>LCDDestination</key>
<map>
<key>Comment</key>
@@ -5565,7 +5609,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <real>1</real>
+ <real>0</real>
</map>
<key>MeshImportUseSLM</key>
<map>
@@ -5578,10 +5622,10 @@
<key>Value</key>
<real>0</real>
</map>
- <key>MeshUseWholeModelUpload</key>
+ <key>MeshUploadLogXML</key>
<map>
<key>Comment</key>
- <string>Upload model in its entirety instead of mesh-by-mesh (new caps)</string>
+ <string>Verbose XML logging on mesh upload</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -5589,6 +5633,17 @@
<key>Value</key>
<real>0</real>
</map>
+ <key>MeshUploadFakeErrors</key>
+ <map>
+ <key>Comment</key>
+ <string>Force upload errors (for testing)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <real>0</real>
+ </map>
<key>MigrateCacheDirectory</key>
<map>
<key>Comment</key>
@@ -6524,7 +6579,28 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+ <key>PostFirstLoginIntroURL</key>
+ <map>
+ <key>Comment</key>
+ <string>URL of intro presenatation after first time users first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
+ <key>PostFirstLoginIntroViewed</key>
+ <map>
+ <key>Comment</key>
+ <string>Flag indicating if user has seen intro presenatation after first time users first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <string>0</string>
+ </map>
<key>PrecachingDelay</key>
<map>
<key>Comment</key>
@@ -7091,6 +7167,75 @@
<key>Value</key>
<integer>1</integer>
</map>
+
+ <key>OctreeMaxNodeCapacity</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum number of elements to store in a single octree node</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>128</integer>
+ </map>
+
+ <key>OctreeStaticObjectSizeFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Multiplier on static object size for determining octree node size </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>4</integer>
+ </map>
+
+ <key>OctreeAlphaDistanceFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Multiplier on alpha object distance for determining octree node size </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>0.1</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
+
+ <key>OctreeAttachmentSizeFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Multiplier on attachment size for determining octree node size </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>4</integer>
+ </map>
+
+ <key>OctreeDistanceFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Multiplier on distance for determining octree node size </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Vector3</string>
+ <key>Value</key>
+ <array>
+ <real>0.01</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ </map>
+
<key>RenderAnisotropic</key>
<map>
<key>Comment</key>
@@ -7188,7 +7333,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <integer>1.0</integer>
+ <real>1.0</real>
</map>
<key>RenderAvatarVP</key>
<map>
@@ -7444,6 +7589,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderMaxTextureIndex</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum texture index to use for indexed texture rendering.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>6</integer>
+ </map>
<key>RenderDebugTextureBind</key>
<map>
<key>Comment</key>
@@ -8589,7 +8745,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>8192</integer>
+ <integer>65536</integer>
</map>
<key>RenderMaxVBOSize</key>
<map>
@@ -8867,17 +9023,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>RenderUseTriStrips</key>
- <map>
- <key>Comment</key>
- <string>Use triangle strips for rendering prims.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>RenderUseFarClip</key>
<map>
<key>Comment</key>
@@ -8942,7 +9087,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>RenderUseStreamVBO</key>
<map>
@@ -9052,7 +9197,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>3.0</real>
+ <real>2.0</real>
</map>
<key>MeshThreadCount</key>
<map>
@@ -9536,7 +9681,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>ShowSnapshotButton</key>
<map>
@@ -9648,6 +9793,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>NearbyListShowMap</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide map above nearby people list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>NearbyListShowIcons</key>
<map>
<key>Comment</key>
@@ -10135,17 +10291,6 @@
<key>Value</key>
<real>0.300000011921</real>
</map>
- <key>SkyEditPresets</key>
- <map>
- <key>Comment</key>
- <string>Whether to be able to edit the sky defaults or not</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>SkyNightColorShift</key>
<map>
<key>Comment</key>
@@ -10187,17 +10332,6 @@
<real>0.1</real>
</array>
</map>
- <key>SkyUseClassicClouds</key>
- <map>
- <key>Comment</key>
- <string>Whether to use the old Second Life particle clouds or not</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>SnapEnabled</key>
<map>
<key>Comment</key>
@@ -10812,7 +10946,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <real>-2</real>
+ <real>-1</real>
</map>
<key>UIExtraTriangleWidth</key>
<map>
@@ -10823,7 +10957,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <real>2</real>
+ <real>4</real>
</map>
<key>UIFloaterCloseBoxSize</key>
<map>
@@ -11815,6 +11949,61 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>UseEnvironmentFromRegion</key>
+ <map>
+ <key>Comment</key>
+ <string>Choose whether to use the region's environment settings, or override them with the local settings.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>UseDayCycle</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether to use use a day cycle or a fixed sky.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>WaterPresetName</key>
+ <map>
+ <key>Comment</key>
+ <string>Water preset to use. May be superseded by region settings.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>Default</string>
+ </map>
+ <key>SkyPresetName</key>
+ <map>
+ <key>Comment</key>
+ <string>Sky preset to use. May be superseded by region settings or by a day cycle (see DayCycleName).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>Default</string>
+ </map>
+ <key>DayCycleName</key>
+ <map>
+ <key>Comment</key>
+ <string>Day cycle to use. May be superseded by region settings.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>Default</string>
+ </map>
<key>UseExternalBrowser</key>
<map>
<key>Comment</key>
@@ -12395,45 +12584,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>-1</integer>
- </map>
- <key>WaterEditPresets</key>
- <map>
- <key>Comment</key>
- <string>Whether to be able to edit the water defaults or not</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>WaterFogColor</key>
- <map>
- <key>Comment</key>
- <string>Water fog color</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Color4</string>
- <key>Value</key>
- <array>
- <real>0.0863</real>
- <real>0.168</real>
- <real>0.212</real>
- <real>0</real>
- </array>
- </map>
- <key>WaterFogDensity</key>
- <map>
- <key>Comment</key>
- <string>Water fog density</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>16.0</real>
+ <integer>20</integer>
</map>
<key>WaterGLFogDensityScale</key>
<map>
@@ -12743,6 +12894,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>SLURLPassToOtherInstance</key>
+ <map>
+ <key>Comment</key>
+ <string>Pass execution to prevoius viewer instances if there is a given slurl</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>soundsbeacon</key>
<map>
<key>Comment</key>
@@ -13238,5 +13400,43 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>WebProfileRect</key>
+ <map>
+ <key>Comment</key>
+ <string>Web profile dimensions</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Rect</string>
+ <key>Value</key>
+ <array>
+ <integer>0</integer>
+ <integer>650</integer>
+ <integer>490</integer>
+ <integer>0</integer>
+ </array>
+ </map>
+ <key>HelpFloaterOpen</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Help Floater on login?</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ShowHelpOnFirstLogin</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Help Floater on first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml
index 70a75cb4ca..29e52ab054 100644
--- a/indra/newview/app_settings/settings_minimal.xml
+++ b/indra/newview/app_settings/settings_minimal.xml
@@ -459,5 +459,16 @@
<key>Value</key>
<integer>0</integer>
</map>
- </map>
+ <key>ShowHelpOnFirstLogin</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Help Floater on first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ </map>
</llsd>
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl
index 3f6b8b3323..b0fa0ddd3e 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void default_lighting();
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
index 1ad87badfe..d9f29ced4f 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
attribute vec4 weight; //1
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
index a15846f192..2796222c68 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl
index 05fe100372..d86ef19a04 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void default_lighting();
diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
index 4b8a7604a1..2eb814bd91 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
index ef823c28b1..7613e50dca 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
attribute vec4 object_weight;
diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl
index 27ac59a840..2638351e96 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl
index f1aa549a47..86b189b282 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 3b12a07a27..4a0815a163 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -5,13 +5,14 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
-uniform sampler2D diffuseMap;
uniform sampler2DRect depthMap;
+vec4 diffuseLookup(vec2 texcoord);
+
uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
@@ -47,7 +48,7 @@ void main()
vec4 pos = vec4(vary_position, 1.0);
- vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 diff= diffuseLookup(gl_TexCoord[0].xy);
vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
vec4 color = diff * col;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl
new file mode 100644
index 0000000000..b0d029dbf4
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl
@@ -0,0 +1,67 @@
+/**
+ * @file alphaF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRect depthMap;
+uniform sampler2D diffuseMap;
+
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_pointlight_col;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+ frag *= screen_res;
+
+ vec4 pos = vec4(vary_position, 1.0);
+
+ vec4 diff= texture2D(diffuseMap,gl_TexCoord[0].xy);
+
+ vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
+ vec4 color = diff * col;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ color.rgb += diff.rgb * vary_pointlight_col.rgb;
+
+ gl_FragColor = color;
+ //gl_FragColor = vec4(1,0,1,1);
+ //gl_FragColor = vec4(1,0,1,1)*shadow;
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index 5addbbb176..ac3f7189c2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getObjectSkinnedTransform();
@@ -35,19 +35,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
//get distance
float d = length(lv);
- //normalize light vector
- lv *= 1.0/d;
+ float da = 0.0;
+
+ if (d > 0.0 && la > 0.0 && fa > 0.0)
+ {
+ //normalize light vector
+ lv *= 1.0/d;
- //distance attenuation
- float dist2 = d*d/(la*la);
- float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
- //angular attenuation
- da *= calcDirectionalLight(n, lv);
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+ }
return da;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 525b68c437..44cb78e914 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
@@ -23,6 +23,7 @@ varying vec3 vary_fragcoord;
varying vec3 vary_position;
varying vec3 vary_light;
varying vec3 vary_pointlight_col;
+varying float vary_texture_index;
uniform float near_clip;
uniform float shadow_offset;
@@ -36,19 +37,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
//get distance
float d = length(lv);
- //normalize light vector
- lv *= 1.0/d;
+ float da = 0.0;
+
+ if (d > 0.0 && la > 0.0 && fa > 0.0)
+ {
+ //normalize light vector
+ lv *= 1.0/d;
- //distance attenuation
- float dist2 = d*d/(la*la);
- float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
- //angular attenuation
- da *= calcDirectionalLight(n, lv);
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+ }
return da;
}
@@ -56,11 +62,13 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
void main()
{
//transform vertex
- gl_Position = ftransform();
+ vec4 vert = vec4(gl_Vertex.xyz, 1.0);
+ vary_texture_index = gl_Vertex.w;
+ gl_Position = gl_ModelViewProjectionMatrix * vert;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+ vec4 pos = (gl_ModelViewMatrix * vert);
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
@@ -97,7 +105,7 @@ void main()
gl_FogFragCoord = pos.z;
- pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ pos = gl_ModelViewProjectionMatrix * vert;
vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
index 164322c3a7..870d593311 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
index 5ae41cb730..c7a4f86727 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
mat4 getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index a2a7dea20d..68e4055cf2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();
@@ -35,19 +35,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
//get distance
float d = length(lv);
- //normalize light vector
- lv *= 1.0/d;
+ float da = 0.0;
+
+ if (d > 0.0 && la > 0.0 && fa > 0.0)
+ {
+ //normalize light vector
+ lv *= 1.0/d;
- //distance attenuation
- float dist2 = d*d/(la*la);
- float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
- //angular attenuation
- da *= calcDirectionalLight(n, lv);
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+ }
return da;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
new file mode 100644
index 0000000000..7bc78fe407
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl
@@ -0,0 +1,21 @@
+/**
+ * @file avatarEyesV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+varying vec3 vary_normal;
+
+void main()
+{
+ //transform vertex
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+
+ vary_normal = normalize(gl_NormalMatrix * gl_Normal);
+
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 9748727147..3268618093 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
index 1b7ae06888..78986ab12e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
@@ -5,14 +5,17 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
+varying vec4 post_pos;
void main()
{
//gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
gl_FragColor = vec4(1,1,1,1);
+
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
index cf6579a40d..f177fcd8f1 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
@@ -5,12 +5,14 @@
* $/LicenseInfo$
*/
-#version 120
+
mat4 getSkinnedTransform();
attribute vec4 weight;
+varying vec4 post_pos;
+
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
@@ -30,8 +32,9 @@ void main()
norm = normalize(norm);
pos = gl_ProjectionMatrix * pos;
- pos.z = max(pos.z, -pos.w+0.01);
- gl_Position = pos;
+ post_pos = pos;
+
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
gl_FrontColor = gl_Color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
index 69c93799b5..7eac11287a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index d9f021b114..8c75c8045a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -26,7 +26,7 @@ uniform vec2 screen_res;
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
@@ -39,7 +39,7 @@ vec4 getPosition(vec2 pos_screen)
void main()
{
- vec2 tc = vary_fragcoord.xy;
+ vec2 tc = vary_fragcoord.xy;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
vec3 pos = getPosition(tc).xyz;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl
new file mode 100644
index 0000000000..6ca51377c1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightMSF.glsl
@@ -0,0 +1,113 @@
+/**
+ * @file blurLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+
+uniform float dist_factor;
+uniform float blur_size;
+uniform vec2 delta;
+uniform vec3 kern[4];
+uniform float kern_scale;
+
+varying vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec3 texture2DMS3(sampler2DMS tex, ivec2 tc)
+{
+ vec3 ret = vec3(0,0,0);
+ for (int i = 0; i < samples; i++)
+ {
+ ret += texelFetch(tex, tc, i).rgb;
+ }
+
+ return ret/samples;
+}
+
+float texture2DMS1(sampler2DMS tex, ivec2 tc)
+{
+ float ret = 0;
+ for (int i = 0; i < samples; i++)
+ {
+ ret += texelFetch(tex, tc, i).r;
+ }
+
+ return ret/samples;
+}
+
+vec4 getPosition(ivec2 pos_screen)
+{
+ float depth = texture2DMS1(depthMap, pos_screen.xy);
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ ivec2 itc = ivec2(tc);
+
+ vec3 norm = texture2DMS3(normalMap, itc).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+ vec3 pos = getPosition(itc).xyz;
+ vec4 ccol = texture2DRect(lightMap, tc).rgba;
+
+ vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+ dlt /= max(-pos.z*dist_factor, 1.0);
+
+ vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+ vec4 col = defined_weight.xyxx * ccol;
+
+ // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
+ float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
+
+ // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
+ tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 );
+
+ for (int i = 1; i < 4; i++)
+ {
+ vec2 samptc = tc + kern[i].z*dlt;
+ vec3 samppos = getPosition(ivec2(samptc)).xyz;
+ float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+ if (d*d <= pointplanedist_tolerance_pow2)
+ {
+ col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+ defined_weight += kern[i].xy;
+ }
+ }
+ for (int i = 1; i < 4; i++)
+ {
+ vec2 samptc = vec2(tc - kern[i].z*dlt);
+ vec3 samppos = getPosition(ivec2(samptc)).xyz;
+ float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+ if (d*d <= pointplanedist_tolerance_pow2)
+ {
+ col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+ defined_weight += kern[i].xy;
+ }
+ }
+
+ col /= defined_weight.xyxx;
+ col.y *= col.y;
+
+ gl_FragColor = col;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
index c2d05c601a..862f809de5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index 37bfaac32c..75b4dc624a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
index d884f2e4a5..dc69519a85 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
varying vec3 vary_mat0;
varying vec3 vary_mat1;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
index 9b109b2db6..5b6726488b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_mat0;
varying vec3 vary_mat1;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
new file mode 100644
index 0000000000..ef300d5631
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
@@ -0,0 +1,79 @@
+/**
+ * @file WLCloudsF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// The fragment shader for the sky
+/////////////////////////////////////////////////////////////////////////
+
+varying vec4 vary_CloudColorSun;
+varying vec4 vary_CloudColorAmbient;
+varying float vary_CloudDensity;
+
+uniform sampler2D cloud_noise_texture;
+uniform vec4 cloud_pos_density1;
+uniform vec4 cloud_pos_density2;
+uniform vec4 gamma;
+
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light) {
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ // Set variables
+ vec2 uv1 = gl_TexCoord[0].xy;
+ vec2 uv2 = gl_TexCoord[1].xy;
+
+ vec4 cloudColorSun = vary_CloudColorSun;
+ vec4 cloudColorAmbient = vary_CloudColorAmbient;
+ float cloudDensity = vary_CloudDensity;
+ vec2 uv3 = gl_TexCoord[2].xy;
+ vec2 uv4 = gl_TexCoord[3].xy;
+
+ // Offset texture coords
+ uv1 += cloud_pos_density1.xy; //large texture, visible density
+ uv2 += cloud_pos_density1.xy; //large texture, self shadow
+ uv3 += cloud_pos_density2.xy; //small texture, visible density
+ uv4 += cloud_pos_density2.xy; //small texture, self shadow
+
+
+ // Compute alpha1, the main cloud opacity
+ float alpha1 = (texture2D(cloud_noise_texture, uv1).x - 0.5) + (texture2D(cloud_noise_texture, uv3).x - 0.5) * cloud_pos_density2.z;
+ alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10. * cloud_pos_density1.z, 1.);
+
+ // And smooth
+ alpha1 = 1. - alpha1 * alpha1;
+ alpha1 = 1. - alpha1 * alpha1;
+
+
+ // Compute alpha2, for self shadowing effect
+ // (1 - alpha2) will later be used as percentage of incoming sunlight
+ float alpha2 = (texture2D(cloud_noise_texture, uv2).x - 0.5);
+ alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+
+ // And smooth
+ alpha2 = 1. - alpha2;
+ alpha2 = 1. - alpha2 * alpha2;
+
+ // Combine
+ vec4 color;
+ color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
+ color *= 2.;
+
+ /// Gamma correct for WL (soft clip effect).
+ gl_FragData[0] = vec4(scaleSoftClip(color.rgb), alpha1);
+ gl_FragData[1] = vec4(0.0,0.0,0.0,0.0);
+ gl_FragData[2] = vec4(0,0,1,0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
new file mode 100644
index 0000000000..3eac63076c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -0,0 +1,165 @@
+/**
+ * @file WLCloudsV.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+// Output parameters
+varying vec4 vary_CloudColorSun;
+varying vec4 vary_CloudColorAmbient;
+varying float vary_CloudDensity;
+
+// Inputs
+uniform vec3 camPosLocal;
+
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 max_y;
+
+uniform vec4 glow;
+
+uniform vec4 cloud_color;
+
+uniform vec4 cloud_scale;
+
+void main()
+{
+
+ // World / view / projection
+ gl_Position = ftransform();
+
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ // Get relative position
+ vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0);
+
+ // Set altitude
+ if (P.y > 0.)
+ {
+ P *= (max_y.x / 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 = 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 * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+
+ // Calculate relative weights
+ temp1 = blue_density + haze_density.x;
+ blue_weight = blue_density / temp1;
+ haze_weight = haze_density.x / 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 * density_multiplier.x;
+
+ // 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
+
+ // Add "minimum anti-solar illumination"
+ temp2.x += .25;
+
+ // Increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
+
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= (1. - cloud_shadow.x);
+
+ // Haze color below cloud
+ vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+ );
+
+ // CLOUDS
+
+ sunlight = sunlight_color;
+ 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.x - 0.25);
+
+
+ // Texture coords
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_TexCoord[0].xy -= 0.5;
+ gl_TexCoord[0].xy /= cloud_scale.x;
+ gl_TexCoord[0].xy += 0.5;
+
+ gl_TexCoord[1] = gl_TexCoord[0];
+ gl_TexCoord[1].x += lightnorm.x * 0.0125;
+ gl_TexCoord[1].y += lightnorm.z * 0.0125;
+
+ gl_TexCoord[2] = gl_TexCoord[0] * 16.;
+ gl_TexCoord[3] = gl_TexCoord[1] * 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
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 35cfb80c93..43af480c50 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
@@ -20,3 +20,4 @@ void main()
vec3 nvn = normalize(vary_normal);
gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
new file mode 100644
index 0000000000..e7b5dcce7f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -0,0 +1,19 @@
+/**
+ * @file diffuseIndexedF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+varying vec3 vary_normal;
+
+void main()
+{
+ vec3 col = gl_Color.rgb * diffuseLookup(gl_TexCoord[0].xy).rgb;
+
+ gl_FragData[0] = vec4(col, 0.0);
+ gl_FragData[1] = gl_Color.aaaa; // spec
+ //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested
+ vec3 nvn = normalize(vary_normal);
+ gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
index 9a45c03237..2c4caea109 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
varying vec3 vary_normal;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 03d3322cb6..b56d1493c3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -5,16 +5,18 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_normal;
+varying float vary_texture_index;
void main()
{
//transform vertex
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ vary_texture_index = gl_Vertex.w;
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 3429877397..d781e08548 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -5,60 +5,24 @@
* $/LicenseInfo$
*/
-#version 120
-#extension GL_ARB_texture_rectangle : enable
-
-uniform sampler2D diffuseMap;
-uniform sampler2DRect depthMap;
-uniform sampler2D noiseMap;
-uniform vec4 shadow_clip;
-uniform vec2 screen_res;
+#extension GL_ARB_texture_rectangle : enable
vec3 fullbrightAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
-varying vec3 vary_ambient;
-varying vec3 vary_directional;
-varying vec4 vary_position;
-varying vec3 vary_normal;
-varying vec3 vary_fragcoord;
-
-uniform mat4 inv_proj;
-
-vec4 getPosition(vec2 pos_screen)
-{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
- vec2 sc = pos_screen.xy*2.0;
- sc /= screen_res;
- sc -= vec2(1.0,1.0);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
void main()
{
- vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
- frag *= screen_res;
-
- vec3 samp_pos = getPosition(frag).xyz;
-
float shadow = 1.0;
- vec4 pos = vary_position;
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color;
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy)*gl_Color;
color.rgb = fullbrightAtmosTransport(color.rgb);
color.rgb = fullbrightScaleSoftClip(color.rgb);
- //gl_FragColor = gl_Color;
gl_FragColor = color;
- //gl_FragColor = vec4(1,0,1,1);
-
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index 6c38d220e2..2eed044b7c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
@@ -14,30 +14,23 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
-varying vec3 vary_ambient;
-varying vec3 vary_directional;
-varying vec3 vary_normal;
-varying vec3 vary_fragcoord;
-uniform float near_clip;
-varying vec4 vary_position;
+varying float vary_texture_index;
void main()
{
//transform vertex
- gl_Position = ftransform();
+ vec4 vert = vec4(gl_Vertex.xyz, 1.0);
+ vary_texture_index = gl_Vertex.w;
+
+ gl_Position = gl_ModelViewProjectionMatrix*vert;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
- vary_position = pos;
-
+ vec4 pos = (gl_ModelViewMatrix * vert);
+
calcAtmospherics(pos.xyz);
gl_FrontColor = gl_Color;
gl_FogFragCoord = pos.z;
-
- pos = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
-
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
index 75b555e8ae..41c149e774 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
index 8dc1410ea5..e86f2896da 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index e3c15a2ab2..fa811f0d55 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
index 37148b3f1a..723777bd3a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void main()
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
index 78df54d5dc..25e93ae266 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
index 0c820bfc6c..4baf1fc65a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index c5ddf31ac0..3c5c780d94 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -23,8 +23,9 @@ uniform float sun_wash;
uniform int light_count;
-uniform vec4 light[16];
-uniform vec4 light_col[16];
+#define MAX_LIGHT_COUNT 16
+uniform vec4 light[MAX_LIGHT_COUNT];
+uniform vec4 light_col[MAX_LIGHT_COUNT];
varying vec4 vary_fragcoord;
uniform vec2 screen_res;
@@ -35,7 +36,7 @@ uniform mat4 inv_proj;
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
@@ -63,50 +64,56 @@ void main()
float noise = texture2D(noiseMap, frag.xy/128.0).b;
vec3 out_col = vec3(0,0,0);
vec3 npos = normalize(-pos);
-
- for (int i = 0; i < light_count; ++i)
+
+ // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
+ for (int i = 0; i < MAX_LIGHT_COUNT; ++i)
{
+ bool light_contrib = (i < light_count);
+
vec3 lv = light[i].xyz-pos;
float dist2 = dot(lv,lv);
dist2 /= light[i].w;
if (dist2 > 1.0)
{
- continue;
+ light_contrib = false;
}
float da = dot(norm, lv);
if (da < 0.0)
{
- continue;
+ light_contrib = false;
}
-
- lv = normalize(lv);
- da = dot(norm, lv);
-
- float fa = light_col[i].a+1.0;
- float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.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)
+ if (light_contrib)
{
- //vec3 ref = dot(pos+lv, norm);
+ lv = normalize(lv);
+ da = dot(norm, lv);
+
+ float fa = light_col[i].a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ dist_atten *= noise;
+
+ float lit = da * dist_atten;
- float sa = dot(normalize(lv+npos),norm);
+ vec3 col = light_col[i].rgb*lit*diff;
+ //vec3 col = vec3(dist2, light_col[i].a, lit);
- if (sa > 0.0)
+ if (spec.a > 0.0)
{
- sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
- sa *= noise;
- col += da*sa*light_col[i].rgb*spec.rgb;
+ //vec3 ref = dot(pos+lv, norm);
+
+ float sa = dot(normalize(lv+npos),norm);
+
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*light_col[i].rgb*spec.rgb;
+ }
}
+
+ out_col += col;
}
-
- out_col += col;
}
if (dot(out_col, out_col) <= 0.0)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl
new file mode 100644
index 0000000000..6c43679acf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightMSF.glsl
@@ -0,0 +1,137 @@
+/**
+ * @file multiPointLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+
+uniform int light_count;
+
+#define MAX_LIGHT_COUNT 16
+uniform vec4 light[MAX_LIGHT_COUNT];
+uniform vec4 light_col[MAX_LIGHT_COUNT];
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform float far_z;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
+ ivec2 itc = ivec2(frag);
+
+ int wght = 0;
+ vec3 fcol = vec3(0,0,0);
+
+ for (int s = 0; s < samples; ++s)
+ {
+ vec3 pos = getPosition(itc, s).xyz;
+ if (pos.z >= far_z)
+ {
+ vec3 norm = texelFetch(normalMap, itc, s).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+ norm = normalize(norm);
+ vec4 spec = texelFetch(specularRect, itc, s);
+ vec3 diff = texelFetch(diffuseRect, itc, s).rgb;
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ vec3 out_col = vec3(0,0,0);
+ 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 < MAX_LIGHT_COUNT; ++i)
+ {
+ bool light_contrib = (i < light_count);
+
+ vec3 lv = light[i].xyz-pos;
+ float dist2 = dot(lv,lv);
+ dist2 /= light[i].w;
+ if (dist2 > 1.0)
+ {
+ light_contrib = false;
+ }
+
+ float da = dot(norm, lv);
+ if (da < 0.0)
+ {
+ light_contrib = false;
+ }
+
+ if (light_contrib)
+ {
+ lv = normalize(lv);
+ da = dot(norm, lv);
+
+ float fa = light_col[i].a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.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)
+ {
+ //vec3 ref = dot(pos+lv, norm);
+
+ float sa = dot(normalize(lv+npos),norm);
+
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*light_col[i].rgb*spec.rgb;
+ }
+ }
+
+ out_col += col;
+ }
+ }
+
+ fcol += out_col;
+ ++wght;
+ }
+ }
+
+ if (wght <= 0)
+ {
+ discard;
+ }
+
+ gl_FragColor.rgb = fcol/samples;
+ gl_FragColor.a = 0.0;
+
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
index 2e3e84dd15..434fb6f534 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec4 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index a9f03f7615..0d25d7792d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
//class 1 -- no shadows
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl
new file mode 100644
index 0000000000..c80a54346e
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightMSF.glsl
@@ -0,0 +1,232 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+//class 1 -- no shadows
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+
+ float det = min(lod/(proj_lod*0.5), 1.0);
+
+ float d = min(dist.x, dist.y);
+
+ float edge = 0.25*det;
+
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+
+ return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ int wght = 0;
+
+ vec3 fcol = vec3(0,0,0);
+
+ vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
+
+ ivec2 itc = ivec2(frag.xy);
+
+ for (int i = 0; i < samples; ++i)
+ {
+ vec3 pos = getPosition(itc, i).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 <= 1.0)
+ {
+ vec3 norm = texelFetch(normalMap, itc, i).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z >= 0.0)
+ {
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+ if (dist_atten > 0.0)
+ {
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ float amb_da = proj_ambiance;
+
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex;
+ amb_da += (da*0.5)*proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texelFetch(specularRect, itc, i);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.w;
+
+ float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+
+ stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+ }
+ }
+ }
+ }
+
+ fcol += col;
+ ++wght;
+ }
+ }
+ }
+ }
+
+ if (wght <= 0)
+ {
+ discard;
+ }
+
+ gl_FragColor.rgb = fcol/samples;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 22ed9dcd40..5efa3200d4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
- #version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -30,7 +30,7 @@ uniform vec4 viewport;
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
sc /= viewport.zw;
sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl
new file mode 100644
index 0000000000..feaf38115d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightMSF.glsl
@@ -0,0 +1,108 @@
+/**
+ * @file pointLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+uniform vec4 viewport;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = (vec2(pos_screen.xy)-viewport.xy)*2.0;
+ sc /= viewport.zw;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+
+ ivec2 itc = ivec2(frag.xy);
+
+ int wght = 0;
+ vec3 fcol = vec3(0,0,0);
+
+ for (int s = 0; s < samples; ++s)
+ {
+ vec3 pos = getPosition(itc, s).xyz;
+ vec3 lv = vary_light.xyz-pos;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 <= 1.0)
+ {
+ vec3 norm = texelFetch(normalMap, itc, s).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+ float da = dot(norm, lv);
+ if (da >= 0.0)
+ {
+ norm = normalize(norm);
+ lv = normalize(lv);
+ da = dot(norm, lv);
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+
+ vec3 col = texelFetch(diffuseRect, itc, s).rgb;
+ float fa = gl_Color.a+1.0;
+ float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ float lit = da * dist_atten * noise;
+
+ col = gl_Color.rgb*lit*col;
+
+ vec4 spec = texelFetch(specularRect, itc, s);
+ if (spec.a > 0.0)
+ {
+ float sa = dot(normalize(lv-normalize(pos)),norm);
+ if (sa > 0.0)
+ {
+ sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+ sa *= noise;
+ col += da*sa*gl_Color.rgb*spec.rgb;
+ }
+ }
+
+ fcol += col;
+ ++wght;
+ }
+ }
+ }
+
+ if (wght <= 0)
+ {
+ discard;
+ }
+
+ gl_FragColor.rgb = fcol/samples;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index 8e74feb615..c510d8ad77 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -5,19 +5,14 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec4 vary_light;
varying vec4 vary_fragcoord;
-uniform vec2 screen_res;
-uniform float near_clip;
-
void main()
{
//transform vertex
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
-
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
vary_fragcoord = pos;
@@ -25,6 +20,8 @@ void main()
tex.w = 1.0;
vary_light = gl_MultiTexCoord0;
+
+ gl_Position = pos;
gl_FrontColor = gl_Color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 77f1b2224c..f6b0402bb9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -29,7 +29,7 @@ varying vec2 vary_fragcoord;
float getDepth(vec2 pos_screen)
{
- float z = texture2DRect(depthMap, pos_screen.xy).a;
+ float z = texture2DRect(depthMap, pos_screen.xy).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl
new file mode 100644
index 0000000000..62ae5f917a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredMSF.glsl
@@ -0,0 +1,133 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS edgeMap;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D bloomMap;
+
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+uniform float focal_distance;
+uniform float blur_constant;
+uniform float tan_pixel_angle;
+uniform float magnification;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec2 vary_fragcoord;
+
+vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
+{
+ vec4 ret = vec4(0,0,0,0);
+ for (int i = 0; i < samples; ++i)
+ {
+ ret += texelFetch(tex, tc, i);
+ }
+
+ return ret/samples;
+}
+
+float getDepth(ivec2 pos_screen)
+{
+ float z = texture2DMS(depthMap, pos_screen.xy).r;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+float calc_cof(float depth)
+{
+ float sc = abs(depth-focal_distance)/-depth*blur_constant;
+
+ sc /= magnification;
+
+ // tan_pixel_angle = pixel_length/-depth;
+ float pixel_length = tan_pixel_angle*-focal_distance;
+
+ sc = sc/pixel_length;
+ sc *= 1.414;
+
+ return sc;
+}
+
+void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, ivec2 tc)
+{
+ float d = getDepth(tc);
+
+ float sc = calc_cof(d);
+
+ if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius
+ || d < cur_depth) //sampled pixel is further away than current pixel
+ {
+ float wg = 0.25;
+
+ vec4 s = texture2DMS(diffuseRect, tc);
+ // de-weight dull areas to make highlights 'pop'
+ wg += s.r+s.g+s.b;
+
+ diff += wg*s;
+
+ w += wg;
+ }
+}
+
+
+void main()
+{
+ ivec2 itc = ivec2(vary_fragcoord.xy);
+
+ vec3 norm = texture2DMS(normalMap, itc).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+
+ float depth = getDepth(itc);
+
+ vec4 diff = texture2DMS(diffuseRect, itc);
+
+ {
+ float w = 1.0;
+
+ float sc = calc_cof(depth);
+ sc = min(abs(sc), 10.0);
+
+ float fd = depth*0.5f;
+
+ float PI = 3.14159265358979323846264;
+
+ int isc = int(sc);
+
+ // sample quite uniformly spaced points within a circle, for a circular 'bokeh'
+ //if (depth < focal_distance)
+ {
+ for (int x = -isc; x <= isc; x+=2)
+ {
+ for (int y = -isc; y <= isc; y+=2)
+ {
+ ivec2 cur_samp = ivec2(x,y);
+ float cur_sc = length(vec2(cur_samp));
+ if (cur_sc < sc)
+ {
+ dofSample(diff, w, cur_sc, depth, itc+cur_samp);
+ }
+ }
+ }
+ }
+
+ diff /= w;
+ }
+
+ vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+ gl_FragColor = diff + bloom;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
index ab48d08bbb..bf829bfc56 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl
new file mode 100644
index 0000000000..bf35dfe11c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFMSF.glsl
@@ -0,0 +1,37 @@
+/**
+ * @file postDeferredF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2D bloomMap;
+
+uniform vec2 screen_res;
+varying vec2 vary_fragcoord;
+
+vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
+{
+ vec4 ret = vec4(0,0,0,0);
+
+ for (int i = 0; i < samples; ++i)
+ {
+ ret += texelFetch(tex,tc,i);
+ }
+
+ return ret/samples;
+}
+
+void main()
+{
+ vec4 diff = texture2DMS(diffuseRect, ivec2(vary_fragcoord.xy));
+
+ vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
+ gl_FragColor = diff + bloom;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
index 12983baa94..876f65ee3a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
index 63b3c9f205..fa3f04bcc8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
index ae57227fe5..eebe930666 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
index 6674c4a5aa..e0c5406483 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
index db3bddc6be..9271a5115c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec4 post_pos;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
new file mode 100644
index 0000000000..820c82ffd7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -0,0 +1,44 @@
+/**
+ * @file WLSkyF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+/////////////////////////////////////////////////////////////////////////
+// The fragment shader for the sky
+/////////////////////////////////////////////////////////////////////////
+
+varying vec4 vary_HazeColor;
+
+uniform sampler2D cloud_noise_texture;
+uniform vec4 gamma;
+
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light) {
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ // Potential Fill-rate optimization. Add cloud calculation
+ // back in and output alpha of 0 (so that alpha culling kills
+ // the fragment) if the sky wouldn't show up because the clouds
+ // are fully opaque.
+
+ vec4 color;
+ color = vary_HazeColor;
+ color *= 2.;
+
+ /// Gamma correct for WL (soft clip effect).
+ gl_FragData[0] = vec4(scaleSoftClip(color.rgb), 1.0);
+ gl_FragData[1] = vec4(0.0,0.0,0.0,0.0);
+ gl_FragData[2] = vec4(0,0,1,0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
new file mode 100644
index 0000000000..1ea00f723a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -0,0 +1,140 @@
+/**
+ * @file WLSkyV.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+// SKY ////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+// Output parameters
+varying vec4 vary_HazeColor;
+
+// Inputs
+uniform vec3 camPosLocal;
+
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 max_y;
+
+uniform vec4 glow;
+
+uniform vec4 cloud_color;
+
+uniform vec4 cloud_scale;
+
+void main()
+{
+
+ // World / view / projection
+ gl_Position = ftransform();
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ // Get relative position
+ vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0);
+ //vec3 P = gl_Vertex.xyz + vec3(0,50,0);
+
+ // Set altitude
+ if (P.y > 0.)
+ {
+ P *= (max_y.x / 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 = 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 * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+
+ // Calculate relative weights
+ temp1 = blue_density + haze_density.x;
+ blue_weight = blue_density / temp1;
+ haze_weight = haze_density.x / 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 * density_multiplier.x;
+
+ // 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
+
+ // Add "minimum anti-solar illumination"
+ temp2.x += .25;
+
+
+ // Haze color above cloud
+ vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient)
+ + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient)
+ );
+
+
+ // Increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
+
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= (1. - cloud_shadow.x);
+
+ // Haze color below cloud
+ vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+ );
+
+ // Final atmosphere additive
+ vary_HazeColor *= (1. - temp1);
+
+ // Attenuate cloud color by atmosphere
+ temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
+
+ // At horizon, blend high altitude sky color towards the darker color below the clouds
+ vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1));
+
+ // won't compile on mac without this being set
+ //vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 29340c7e9f..60082f40d6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -259,7 +259,7 @@ vec3 scaleSoftClip(vec3 light)
void main()
{
vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).a;
+ float depth = texture2DRect(depthMap, tc.xy).r;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
new file mode 100644
index 0000000000..9dfacfb520
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightMSF.glsl
@@ -0,0 +1,318 @@
+/**
+ * @file softenLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2DMS depthMap;
+uniform sampler2D noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+//uniform mat4 shadow_matrix[3];
+//uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 getPositionEye()
+{
+ return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+ return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+ return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+ return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+ return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+ vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+ vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+ vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+ vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+ vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+ vec3 P = inPositionEye;
+ setPositionEye(P);
+
+ //(TERRAIN) limit altitude
+ if (P.y > max_y.x) P *= (max_y.x / P.y);
+ if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+ vec3 tmpLightnorm = lightnorm.xyz;
+
+ vec3 Pn = normalize(P);
+ float Plen = length(P);
+
+ vec4 temp1 = vec4(0);
+ vec3 temp2 = vec3(0);
+ vec4 blue_weight;
+ vec4 haze_weight;
+ 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 * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ //I had thought blue_density and haze_density should have equal weighting,
+ //but attenuation due to haze_density tends to seem too strong
+
+ temp1 = blue_density + vec4(haze_density.r);
+ blue_weight = blue_density / temp1;
+ haze_weight = vec4(haze_density.r) / temp1;
+
+ //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+ temp2.y = max(0.0, tmpLightnorm.y);
+ temp2.y = 1. / temp2.y;
+ sunlight *= exp( - light_atten * temp2.y);
+
+ // main atmospheric scattering line integral
+ temp2.z = Plen * density_multiplier.x;
+
+ // Transparency (-> temp1)
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // compiler gets confused.
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+ //final atmosphere attenuation factor
+ setAtmosAttenuation(temp1.rgb);
+
+ //compute haze glow
+ //(can use temp2.x as temp because we haven't used it yet)
+ temp2.x = dot(Pn, tmpLightnorm.xyz);
+ temp2.x = 1. - temp2.x;
+ //temp2.x is 0 at the sun and increases away from sun
+ temp2.x = max(temp2.x, .03); //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;
+
+ //increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 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(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+ //haze color
+ setAdditiveColor(
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ + tmpAmbient)));
+
+ //brightness of surface both sunlight and ambient
+ setSunlitColor(vec3(sunlight * .5));
+ setAmblitColor(vec3(tmpAmbient * .25));
+ setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor();
+ return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor() * 2.0;
+ return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+ return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+ return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+ return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+ return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+ return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
+{
+ vec4 ret = vec4(0,0,0,0);
+
+ for (int i = 0; i < samples; ++i)
+ {
+ ret += texelFetch(tex,tc,i);
+ }
+
+ return ret/samples;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ ivec2 itc = ivec2(tc);
+
+ vec3 fcol = vec3(0,0,0);
+
+ for (int i = 0; i < samples; ++i)
+ {
+ float depth = texelFetch(depthMap, itc, i).r;
+ vec3 pos = getPosition_d(tc, depth).xyz;
+ vec3 norm = texelFetch(normalMap, itc, i).xyz;
+
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+ //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
+
+ float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+
+ vec4 diffuse = texelFetch(diffuseRect, itc, i);
+ if (diffuse.a >= 1.0)
+ {
+ fcol += diffuse.rgb;
+ }
+ else
+ {
+ vec4 spec = texelFetch(specularRect, itc, i);
+
+ calcAtmospherics(pos.xyz, 1.0);
+
+ vec3 col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
+
+ col *= diffuse.rgb;
+
+ if (spec.a > 0.0) // specular reflection
+ {
+ // the old infinite-sky shiny reflection
+ //
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(refnormpersp, vary_light.xyz);
+ vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+ // add the two types of shiny together
+ col += dumbshiny * spec.rgb;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+ fcol += col;
+ }
+ }
+
+ gl_FragColor.rgb = fcol.rgb/samples;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
index 8f0bcca76b..745cc01992 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 29fac46bfe..9aaffc15bf 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl
new file mode 100644
index 0000000000..4bb9bad275
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightMSF.glsl
@@ -0,0 +1,234 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+//class 1 -- no shadows
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+
+ float det = min(lod/(proj_lod*0.5), 1.0);
+
+ float d = min(dist.x, dist.y);
+
+ float edge = 0.25*det;
+
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+
+ return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+ ivec2 itc = ivec2(frag.xy);
+
+ vec3 fcol = vec3(0,0,0);
+ int wght = 0;
+
+ for (int i = 0; i < samples; ++i)
+ {
+ vec3 pos = getPosition(itc, i).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 <= 1.0)
+ {
+ vec3 norm = texelFetch(normalMap, itc, i).xyz*2.0-1.0;
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z >= 0.0)
+ {
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+ if (dist_atten > 0.0)
+ {
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ float amb_da = proj_ambiance;
+
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex;
+ amb_da += (da*0.5)*proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texelFetch(specularRect, itc, i);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.w;
+
+ float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+
+ stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
+ }
+ }
+ }
+ }
+
+ fcol += col;
+ ++wght;
+ }
+ }
+ }
+ }
+
+ if (wght <= 0)
+ {
+ discard;
+ }
+
+ gl_FragColor.rgb = fcol/samples;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
new file mode 100644
index 0000000000..2cf7d194cc
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
@@ -0,0 +1,19 @@
+/**
+ * @file starsF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+uniform sampler2D diffuseMap;
+
+void main()
+{
+ vec4 col = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
+
+ gl_FragData[0] = col;
+ gl_FragData[1] = vec4(0,0,0,0);
+ gl_FragData[2] = vec4(0,0,1,0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
new file mode 100644
index 0000000000..c43125dad9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file starsV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+
+void main()
+{
+ //transform vertex
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ gl_FrontColor = gl_Color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
index 00093836a2..f20886565a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
//class 1, no shadow, no SSAO, should never be called
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl
new file mode 100644
index 0000000000..f20886565a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightMSF.glsl
@@ -0,0 +1,17 @@
+/**
+ * @file sunLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+//class 1, no shadow, no SSAO, should never be called
+
+#extension GL_ARB_texture_rectangle : enable
+
+void main()
+{
+ gl_FragColor = vec4(0,0,0,0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index cd91351ad4..665d8126a0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -35,7 +35,7 @@ uniform float shadow_offset;
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl
new file mode 100644
index 0000000000..32d1b2149a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOMSF.glsl
@@ -0,0 +1,123 @@
+/**
+ * @file sunLightSSAOF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+//class 1 -- no shadow, SSAO only
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2D noiseMap;
+
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm, int sample)
+{
+ float ret = 1.0;
+
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+ kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+ kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+ kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+ kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+ kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+ kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+ kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec3 pos_world = pos.xyz;
+ vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+
+ float angle_hidden = 0.0;
+ int points = 0;
+
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ ivec2 samppos_screen = ivec2(pos_screen + scale * reflect(kern[i], noise_reflect));
+ vec3 samppos_world = getPosition(samppos_screen, sample).xyz;
+
+ vec3 diff = pos_world - samppos_world;
+ float dist2 = dot(diff, diff);
+
+ // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+ // --> solid angle shrinking by the square of distance
+ //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+ //(k should vary inversely with # of samples, but this is taken care of later)
+
+ angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+
+ // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
+ points = points + int(diff.z > -1.0);
+ }
+
+ angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+
+ ret = (1.0 - (float(points != 0) * angle_hidden));
+
+ return min(ret, 1.0);
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ ivec2 itc = ivec2(pos_screen);
+
+ float col = 0;
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec4 pos = getPosition(itc, i);
+ vec3 norm = texelFetch(normalMap, itc, i).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+ col += calcAmbientOcclusion(pos,norm,i);
+ }
+
+ col /= samples;
+
+ gl_FragColor[0] = 1.0;
+ gl_FragColor[1] = col;
+ gl_FragColor[2] = 1.0;
+ gl_FragColor[3] = 1.0;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
index 9beb513ad8..814deb3677 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec4 vary_light;
varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 0edae47918..d005f67bf6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D detail_0;
uniform sampler2D detail_1;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
index a6163063be..3038fd2966 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_normal;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index c54d9a1e3e..de7e038402 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
index 29689ecbaf..a9bef4292d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_normal;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index e76f598d09..2710422d32 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
index 649e392630..5397290b11 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
index f2023fa5ea..32f5f5f236 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl
new file mode 100644
index 0000000000..9267a8585d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractMSF.glsl
@@ -0,0 +1,38 @@
+/**
+ * @file glowExtractF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseMap;
+uniform float minLuminance;
+uniform float maxExtractAlpha;
+uniform vec3 lumWeights;
+uniform vec3 warmthWeights;
+uniform float warmthAmount;
+
+void main()
+{
+ ivec2 itc = ivec2(gl_TexCoord[0].xy);
+ vec4 fcol = vec4(0,0,0,0);
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec4 col = texelFetch(diffuseMap, itc, i);
+
+ /// CALCULATING LUMINANCE (Using NTSC lum weights)
+ /// http://en.wikipedia.org/wiki/Luma_%28video%29
+ float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) );
+ float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) );
+
+ fcol += vec4(col.rgb, max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha));
+ }
+
+ gl_FragColor = fcol/samples;
+}
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
index 0ca0608b45..76736fed53 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void main()
{
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl
index 65fc2e9f99..d3225546b3 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
uniform float glowStrength;
diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
index 0bd44cec90..9bb41626ae 100644
--- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec2 glowDelta;
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
index ac00f15b35..cdc2ca3da2 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D detail0;
uniform sampler2D detail1;
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
index 1e19ee7699..8af981915b 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
index 34f78565a5..d94d986581 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
// this class1 shader is just a copy of terrainF
diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
index 0dfac84a6e..06854fcc0a 100644
--- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index 4e9c09b1ea..0f24e3c35a 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec3 scaleSoftClip(vec3 inColor);
vec3 atmosTransport(vec3 inColor);
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index a34cf23790..630459b324 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 applyWaterFog(vec4 color)
{
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
index 161c794c68..831d6a761c 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl
index 6f821f893d..f6c6d945de 100644
--- a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl
index d1c98bf70c..f114f766bf 100644
--- a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void main()
{
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
index 9c59e8c3ad..1796730c92 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
index 1fee99c446..bfe0be9fdf 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
index fb5da21c72..6f1fe91007 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
index 1bdaccf9b8..19072cd052 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
@@ -6,7 +6,7 @@
*/
-#version 120
+
uniform sampler2D diffuseMap;
uniform samplerCube environmentMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
index 2e94d3bbf1..0ae6dc89e2 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
@@ -6,7 +6,7 @@
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
index 714f9a2551..5d4bf2c33e 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l)
{
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
index 65b45f8081..574252af12 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l)
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
index 7f65ea76f7..29f575b7e5 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
index 8f13e6dc04..65da5a6825 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
index 56f31f6a79..d491f1102e 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
index 64d549ff52..ef38ee9699 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
index c5d084c132..286c92326b 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
index 732d246471..772a420e33 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
vec3 atmosAmbient(vec3 light);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
index 73e1a1ec26..da60a3ddf5 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l);
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
index afc3dc89bf..c0b72115dd 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void fullbright_lighting();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl
index 3dc4294f67..391c06edc8 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void fullbright_shiny_lighting();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
index f0baeeeee5..f44a5ce32e 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
index 02367b9439..31e0f0a429 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl
index 5daf66fb31..8ffb252f57 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
void fullbright_shiny_lighting_water();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
index 02ff3cc2a9..e5dafa8c78 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
index 38e07dbd80..3382384c99 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl
index afaac4f69c..220f26614f 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void fullbright_lighting_water();
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
index 2cf7a69baa..d079de5377 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void shiny_lighting();
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
index 4146646058..cd655f3bb5 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
index 6ea83b721d..68a086dbc1 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl
index e3babe2210..4649d1c47c 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void shiny_lighting_water();
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl
index d449d37c0c..b4e4dcfbbf 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl
@@ -5,8 +5,6 @@
* $/LicenseInfo$
*/
-#version 120
-
void default_lighting();
void main()
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
index be38a14d52..900448035c 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
index 0d8e14e2e3..b493f76fcc 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl
index 68bd81e029..4ec5ee43b4 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void default_lighting_water();
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
index f337bde329..3d05850ab3 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec3 atmosLighting(vec3 light)
{
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
index 4b402a7028..f1a0af21af 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec3 atmosAmbient(vec3 light)
{
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
index 20948b1e46..73bbd57315 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void setPositionEye(vec3 v);
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
index 8a2c2a7186..e0eb7b3767 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_PositionEye;
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
index a1dd4ed5fe..a251213ff5 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_PositionEye;
diff --git a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
index 7aed1fd3b5..4958cb2f72 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec4 gamma;
diff --git a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
index 6780dc4d3e..75929bc609 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec3 atmosTransport(vec3 light)
{
diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
index 172c2ca078..3e8b719f93 100644
--- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
+++ b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index 6dfc1b952c..681e52de2a 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -5,11 +5,10 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
-uniform sampler2D diffuseMap;
uniform sampler2DRectShadow shadowMap0;
uniform sampler2DRectShadow shadowMap1;
uniform sampler2DRectShadow shadowMap2;
@@ -105,7 +104,7 @@ void main()
}
}
- vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 diff = diffuseLookup(gl_TexCoord[0].xy);
vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
vec4 color = diff * col;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl
new file mode 100644
index 0000000000..5350359f75
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl
@@ -0,0 +1,125 @@
+/**
+ * @file alphaF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DRect depthMap;
+uniform sampler2D diffuseMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+varying vec3 vary_ambient;
+varying vec3 vary_directional;
+varying vec3 vary_fragcoord;
+varying vec3 vary_position;
+varying vec3 vary_pointlight_col;
+
+uniform float shadow_bias;
+
+uniform mat4 inv_proj;
+
+vec4 getPosition(vec2 pos_screen)
+{
+ float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos.xyz /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
+
+ return shadow/5.0;
+}
+
+
+void main()
+{
+ vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+ frag *= screen_res;
+
+ float shadow = 1.0;
+ vec4 pos = vec4(vary_position, 1.0);
+
+ vec4 spos = pos;
+
+ if (spos.z > -shadow_clip.w)
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 1.5);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 1.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 1.5);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.5);
+ }
+ }
+
+ vec4 diff = texture2D(diffuseMap,gl_TexCoord[0].xy);
+
+ vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a);
+ vec4 color = diff * col;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ color.rgb += diff.rgb * vary_pointlight_col.rgb;
+
+ //gl_FragColor = gl_Color;
+ gl_FragColor = color;
+ //gl_FragColor.r = 0.0;
+ //gl_FragColor = vec4(1,shadow,1,1);
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
index d227346163..948a52da5b 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
@@ -35,19 +35,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
//get distance
float d = length(lv);
- //normalize light vector
- lv *= 1.0/d;
+ float da = 0.0;
+
+ if (d > 0.0 && la > 0.0 && fa > 0.0)
+ {
+ //normalize light vector
+ lv *= 1.0/d;
- //distance attenuation
- float dist2 = d*d/(la*la);
- float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
- //angular attenuation
- da *= calcDirectionalLight(n, lv);
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+ }
return da;
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
index 86f014df35..f616ecc872 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
@@ -22,6 +22,7 @@ varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
varying vec3 vary_pointlight_col;
+varying float vary_texture_index;
uniform float near_clip;
uniform float shadow_offset;
@@ -35,19 +36,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
//get distance
float d = length(lv);
- //normalize light vector
- lv *= 1.0/d;
+ float da = 0.0;
+
+ if (d > 0.0 && la > 0.0 && fa > 0.0)
+ {
+ //normalize light vector
+ lv *= 1.0/d;
- //distance attenuation
- float dist2 = d*d/(la*la);
- float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
- //angular attenuation
- da *= calcDirectionalLight(n, lv);
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+ }
return da;
}
@@ -55,11 +61,13 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
void main()
{
//transform vertex
- gl_Position = ftransform();
+ vec4 vert = vec4(gl_Vertex.xyz, 1.0);
+ vary_texture_index = gl_Vertex.w;
+ gl_Position = gl_ModelViewProjectionMatrix * vert;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
- vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+ vec4 pos = (gl_ModelViewMatrix * vert);
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
@@ -94,7 +102,7 @@ void main()
gl_FogFragCoord = pos.z;
- pos = gl_ModelViewProjectionMatrix * gl_Vertex;
+ pos = gl_ModelViewProjectionMatrix * vert;
vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
index 495e86c8db..01e40afc4f 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();
@@ -37,19 +37,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
//get distance
float d = length(lv);
- //normalize light vector
- lv *= 1.0/d;
+ float da = 0.0;
+
+ if (d > 0.0 && la > 0.0 && fa > 0.0)
+ {
+ //normalize light vector
+ lv *= 1.0/d;
- //distance attenuation
- float dist2 = d*d/(la*la);
- float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
- //angular attenuation
- da *= calcDirectionalLight(n, lv);
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+ }
return da;
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
index 3155f3f929..729e4b5543 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -22,7 +22,7 @@ uniform vec2 screen_res;
float getDepth(vec2 pos_screen)
{
- float z = texture2DRect(depthMap, pos_screen.xy).a;
+ float z = texture2DRect(depthMap, pos_screen.xy).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl
new file mode 100644
index 0000000000..b22bc5b288
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeMSF.glsl
@@ -0,0 +1,74 @@
+/**
+ * @file edgeF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+
+varying vec2 vary_fragcoord;
+
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+float getDepth(ivec2 pos_screen, int sample)
+{
+ float z = texelFetch(depthMap, pos_screen, sample).r;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+void main()
+{
+ float e = 0;
+
+ ivec2 itc = ivec2(vary_fragcoord.xy);
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec3 norm = texelFetch(normalMap, itc, i).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+ float depth = getDepth(itc, i);
+
+ vec2 tc = vary_fragcoord.xy;
+
+ int sc = 1;
+
+ vec2 de;
+ de.x = (depth-getDepth(itc+ivec2(sc, sc),i)) + (depth-getDepth(itc+ivec2(-sc, -sc), i));
+ de.y = (depth-getDepth(itc+ivec2(-sc, sc),i)) + (depth-getDepth(itc+ivec2(sc, -sc), i));
+ de /= depth;
+ de *= de;
+ de = step(depth_cutoff, de);
+
+ vec2 ne;
+ vec3 nexnorm = texelFetch(normalMap, itc+ivec2(-sc,-sc), i).rgb;
+ nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm
+ ne.x = dot(nexnorm, norm);
+ vec3 neynorm = texelFetch(normalMap, itc+ivec2(sc,sc), i).rgb;
+ neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm
+ ne.y = dot(neynorm, norm);
+
+ ne = 1.0-ne;
+
+ ne = step(norm_cutoff, ne);
+
+ e += dot(de,de)+dot(ne,ne);
+ }
+
+ e /= samples;
+
+ gl_FragColor.a = e;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
index b3413c301f..393084a3db 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index d6cd984ebe..f54186ffca 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -91,7 +91,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl
new file mode 100644
index 0000000000..fee32be3e3
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightMSF.glsl
@@ -0,0 +1,244 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+
+ float det = min(lod/(proj_lod*0.5), 1.0);
+
+ float d = min(dist.x, dist.y);
+
+ float edge = 0.25*det;
+
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+
+ return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ int wght = 0;
+
+ vec3 fcol = vec3(0,0,0);
+
+ vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
+
+ ivec2 itc = ivec2(frag.xy);
+
+ float shadow = 1.0;
+
+ if (proj_shadow_idx >= 0)
+ {
+ vec4 shd = texture2DRect(lightMap, frag);
+ float sh[2];
+ sh[0] = shd.b;
+ sh[1] = shd.a;
+ shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+ }
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec3 pos = getPosition(itc, i).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 <= 1.0)
+ {
+ vec3 norm = texelFetch(normalMap, itc, i).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z >= 0.0)
+ {
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+ if (dist_atten > 0.0)
+ {
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ float amb_da = proj_ambiance;
+
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex*shadow;
+ amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texelFetch(specularRect, itc, i);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.w;
+
+ float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+
+ stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+ }
+ }
+ }
+ }
+
+ fcol += col;
+ wght++;
+ }
+ }
+ }
+ }
+
+ if (wght <= 0)
+ {
+ discard;
+ }
+
+ gl_FragColor.rgb = fcol/samples;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 0160e84278..66a1a8515f 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -71,7 +71,7 @@ vec4 getPosition_d(vec2 pos_screen, float depth)
vec4 getPosition(vec2 pos_screen)
{ //get position in screen space (world units) given window coordinate and depth map
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
return getPosition_d(pos_screen, depth);
}
@@ -258,7 +258,7 @@ vec3 scaleSoftClip(vec3 light)
void main()
{
vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).a;
+ float depth = texture2DRect(depthMap, tc.xy).r;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
@@ -288,54 +288,8 @@ void main()
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
- /*
- // screen-space cheap fakey reflection map
- //
- vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
- depth -= 0.5; // unbias depth
- // first figure out where we'll make our 2D guess from
- vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
- // Offset the guess source a little according to a trivial
- // checkerboard dither function and spec.a.
- // This is meant to be similar to sampling a blurred version
- // of the diffuse map. LOD would be better in that regard.
- // The goal of the blur is to soften reflections in surfaces
- // with low shinyness, and also to disguise our lameness.
- float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
- float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
- ref2d += vec2(checkoffset, checkoffset);
- ref2d += tc.xy; // use as offset from destination
- // Get attributes from the 2D guess point.
- // We average two samples of diffuse (not of anything else) per
- // pixel to try to reduce aliasing some more.
- vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
- texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
- float refdepth = texture2DRect(depthMap, ref2d).a;
- vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
- float refshad = texture2DRect(lightMap, ref2d).r;
- vec3 refn = texture2DRect(normalMap, ref2d).rgb;
- refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
- refn = normalize(refn);
- // figure out how appropriate our guess actually was
- float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
- // darken reflections from points which face away from the reflected ray - our guess was a back-face
- //refapprop *= step(dot(refnorm, refn), 0.0);
- refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
- // get appropriate light strength for guess-point
- // reflect light direction to increase the illusion that
- // these are reflections.
- vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
- float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
- // apply sun color to guess-point, dampen according to inappropriateness of guess
- float refmod = min(refapprop, reflit);
- vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
- vec3 ssshiny = (refprod * spec.a);
- ssshiny *= 0.3; // dampen it even more
- */
- vec3 ssshiny = vec3(0,0,0);
-
// add the two types of shiny together
- col += (ssshiny + dumbshiny) * spec.rgb;
+ col += dumbshiny * spec.rgb;
}
col = atmosLighting(col);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
new file mode 100644
index 0000000000..0bae10ca7d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightMSF.glsl
@@ -0,0 +1,307 @@
+/**
+ * @file softenLightMSF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2DMS depthMap;
+uniform sampler2D noiseMap;
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+uniform vec3 gi_quad;
+
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+//uniform vec4 camPosWorld;
+uniform vec4 gamma;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 ambient;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
+uniform vec4 haze_horizon;
+uniform vec4 haze_density;
+uniform vec4 cloud_shadow;
+uniform vec4 density_multiplier;
+uniform vec4 distance_multiplier;
+uniform vec4 max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform vec3 env_mat[3];
+uniform vec4 shadow_clip;
+uniform mat3 ssao_effect_mat;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+varying vec4 vary_light;
+varying vec2 vary_fragcoord;
+
+vec3 vary_PositionEye;
+
+vec3 vary_SunlitColor;
+vec3 vary_AmblitColor;
+vec3 vary_AdditiveColor;
+vec3 vary_AtmosAttenuation;
+
+vec4 getPosition_d(vec2 pos_screen, float depth)
+{
+ vec2 sc = pos_screen.xy*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+vec3 getPositionEye()
+{
+ return vary_PositionEye;
+}
+vec3 getSunlitColor()
+{
+ return vary_SunlitColor;
+}
+vec3 getAmblitColor()
+{
+ return vary_AmblitColor;
+}
+vec3 getAdditiveColor()
+{
+ return vary_AdditiveColor;
+}
+vec3 getAtmosAttenuation()
+{
+ return vary_AtmosAttenuation;
+}
+
+
+void setPositionEye(vec3 v)
+{
+ vary_PositionEye = v;
+}
+
+void setSunlitColor(vec3 v)
+{
+ vary_SunlitColor = v;
+}
+
+void setAmblitColor(vec3 v)
+{
+ vary_AmblitColor = v;
+}
+
+void setAdditiveColor(vec3 v)
+{
+ vary_AdditiveColor = v;
+}
+
+void setAtmosAttenuation(vec3 v)
+{
+ vary_AtmosAttenuation = v;
+}
+
+void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
+
+ vec3 P = inPositionEye;
+ setPositionEye(P);
+
+ //(TERRAIN) limit altitude
+ if (P.y > max_y.x) P *= (max_y.x / P.y);
+ if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+
+ vec3 tmpLightnorm = lightnorm.xyz;
+
+ vec3 Pn = normalize(P);
+ float Plen = length(P);
+
+ vec4 temp1 = vec4(0);
+ vec3 temp2 = vec3(0);
+ vec4 blue_weight;
+ vec4 haze_weight;
+ 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 * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ //I had thought blue_density and haze_density should have equal weighting,
+ //but attenuation due to haze_density tends to seem too strong
+
+ temp1 = blue_density + vec4(haze_density.r);
+ blue_weight = blue_density / temp1;
+ haze_weight = vec4(haze_density.r) / temp1;
+
+ //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+ temp2.y = max(0.0, tmpLightnorm.y);
+ temp2.y = 1. / temp2.y;
+ sunlight *= exp( - light_atten * temp2.y);
+
+ // main atmospheric scattering line integral
+ temp2.z = Plen * density_multiplier.x;
+
+ // Transparency (-> temp1)
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // compiler gets confused.
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+
+ //final atmosphere attenuation factor
+ setAtmosAttenuation(temp1.rgb);
+
+ //compute haze glow
+ //(can use temp2.x as temp because we haven't used it yet)
+ temp2.x = dot(Pn, tmpLightnorm.xyz);
+ temp2.x = 1. - temp2.x;
+ //temp2.x is 0 at the sun and increases away from sun
+ temp2.x = max(temp2.x, .03); //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;
+
+ //increase ambient when there are more clouds
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 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(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+ //haze color
+ setAdditiveColor(
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ + tmpAmbient)));
+
+ //brightness of surface both sunlight and ambient
+ setSunlitColor(vec3(sunlight * .5));
+ setAmblitColor(vec3(tmpAmbient * .25));
+ setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
+}
+
+vec3 atmosLighting(vec3 light)
+{
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor();
+ return (2.0 * light);
+}
+
+vec3 atmosTransport(vec3 light) {
+ light *= getAtmosAttenuation().r;
+ light += getAdditiveColor() * 2.0;
+ return light;
+}
+vec3 atmosGetDiffuseSunlightColor()
+{
+ return getSunlitColor();
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+ return (light / scene_light_strength );
+}
+
+vec3 scaleUpLight(vec3 light)
+{
+ return (light * scene_light_strength);
+}
+
+vec3 atmosAmbient(vec3 light)
+{
+ return getAmblitColor() + light / 2.0;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+ return getSunlitColor() * lightIntensity;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+ //soft clip effect:
+ light = 1. - clamp(light, vec3(0.), vec3(1.));
+ light = 1. - pow(light, gamma.xxx);
+
+ return light;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ ivec2 itc = ivec2(tc);
+
+ vec3 fcol = vec3(0,0,0);
+
+ vec2 scol_ambocc = texture2DRect(lightMap, tc).rg;
+ float ambocc = scol_ambocc.g;
+
+ for (int i = 0; i < samples; ++i)
+ {
+ float depth = texelFetch(depthMap, itc.xy, i).r;
+ vec3 pos = getPosition_d(tc, depth).xyz;
+ vec3 norm = texelFetch(normalMap, itc, i).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+
+ float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
+
+ vec4 diffuse = texelFetch(diffuseRect, itc, i);
+ vec4 spec = texelFetch(specularRect, itc, i);
+
+ float amb = 0;
+
+ float scol = max(scol_ambocc.r, diffuse.a);
+ amb += ambocc;
+
+ calcAtmospherics(pos.xyz, ambocc);
+
+ vec3 col = atmosAmbient(vec3(0));
+ col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+
+ col *= diffuse.rgb;
+
+ if (spec.a > 0.0) // specular reflection
+ {
+ // the old infinite-sky shiny reflection
+ //
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+ float sa = dot(refnormpersp, vary_light.xyz);
+ vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+
+ // add the two types of shiny together
+ col += dumbshiny * spec.rgb;
+ }
+
+ col = atmosLighting(col);
+ col = scaleSoftClip(col);
+
+ fcol += col;
+ }
+
+ gl_FragColor.rgb = fcol/samples;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
index 8f0bcca76b..745cc01992 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 50b9ef276e..cd3828fbd4 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl
new file mode 100644
index 0000000000..ec9b547a47
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightMSF.glsl
@@ -0,0 +1,245 @@
+/**
+ * @file multiSpotLightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+uniform sampler2DMS diffuseRect;
+uniform sampler2DMS specularRect;
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2D projectionMap;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod; //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+varying vec4 vary_light;
+
+varying vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float det = max(1.0-lod/(proj_lod*0.5), 0.0);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+
+ float det = min(lod/(proj_lod*0.5), 1.0);
+
+ float d = min(dist.x, dist.y);
+
+ float edge = 0.25*det;
+
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+ vec2 dist = tc-vec2(0.5);
+
+ float d = dot(dist,dist);
+
+ ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+
+ return ret;
+}
+
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+void main()
+{
+ vec4 frag = vary_fragcoord;
+ frag.xyz /= frag.w;
+ frag.xyz = frag.xyz*0.5+0.5;
+ frag.xy *= screen_res;
+ ivec2 itc = ivec2(frag.xy);
+
+ vec3 fcol = vec3(0,0,0);
+ int wght = 0;
+
+ float shadow = 1.0;
+
+ if (proj_shadow_idx >= 0)
+ {
+ vec4 shd = texture2DRect(lightMap, frag.xy);
+ float sh[2];
+ sh[0] = shd.b;
+ sh[1] = shd.a;
+ shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+ }
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec3 pos = getPosition(itc, i).xyz;
+ vec3 lv = vary_light.xyz-pos.xyz;
+ float dist2 = dot(lv,lv);
+ dist2 /= vary_light.w;
+ if (dist2 <= 1.0)
+ {
+ vec3 norm = texelFetch(normalMap, itc, i).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+
+ norm = normalize(norm);
+ float l_dist = -dot(lv, proj_n);
+
+ vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+ if (proj_tc.z >= 0.0)
+ {
+ proj_tc.xyz /= proj_tc.w;
+
+ float fa = gl_Color.a+1.0;
+ float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
+ if (dist_atten > 0.0)
+ {
+ lv = proj_origin-pos.xyz;
+ lv = normalize(lv);
+ float da = dot(norm, lv);
+
+ vec3 col = vec3(0,0,0);
+
+ vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
+
+ float noise = texture2D(noiseMap, frag.xy/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
+ {
+ float lit = 0.0;
+ float amb_da = proj_ambiance;
+
+ if (da > 0.0)
+ {
+ float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+
+ vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+
+ vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
+
+ lit = da * dist_atten * noise;
+
+ col = lcol*lit*diff_tex*shadow;
+ amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+ amb_da += (da*da*0.5+0.5)*proj_ambiance;
+
+ amb_da *= dist_atten * noise;
+
+ amb_da = min(amb_da, 1.0-lit);
+
+ col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+ }
+
+
+ vec4 spec = texelFetch(specularRect, itc, i);
+ if (spec.a > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), norm);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
+ {
+ stc.xy /= stc.w;
+
+ float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
+
+ stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
+ col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
+ }
+ }
+ }
+ }
+
+ fcol += col;
+ wght++;
+ }
+ }
+ }
+ }
+
+ if (wght <= 0)
+ {
+ discard;
+ }
+
+ gl_FragColor.rgb = fcol/wght;
+ gl_FragColor.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index 4369b3b34f..315139b415 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -45,7 +45,7 @@ uniform float spot_shadow_offset;
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl
new file mode 100644
index 0000000000..63d13c996d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightMSF.glsl
@@ -0,0 +1,202 @@
+/**
+ * @file sunLightMSF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+//class 2, shadows, no SSAO
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen.xy, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias*scl;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += spot_shadow_bias*scl;
+
+ float cs = shadow2D(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ vec2 off = 1.5/proj_shadow_res;
+
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ ivec2 itc = ivec2(pos_screen);
+
+ //try doing an unproject here
+
+ vec4 fcol = vec4(0,0,0,0);
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec4 pos = getPosition(itc, i);
+
+ vec4 nmap4 = texelFetch(normalMap, itc, i);
+ nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
+ float displace = nmap4.w;
+ vec3 norm = nmap4.xyz;
+
+ /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
+ {
+ gl_FragColor = vec4(0.0); // doesn't matter
+ return;
+ }*/
+
+ float shadow = 1.0;
+ float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+
+ vec3 shadow_pos = pos.xyz + displace*norm;
+ vec3 offset = vary_light.xyz * (1.0-dp_directional_light);
+
+ vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
+
+ if (spos.z > -shadow_clip.w)
+ {
+ if (dp_directional_light == 0.0)
+ {
+ // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
+ shadow = 0.0;
+ }
+ else
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 0.25);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 0.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 0.75);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.0);
+ }
+
+ // take the most-shadowed value out of these two:
+ // * the blurred sun shadow in the light (shadow) map
+ // * an unblurred dot product between the sun and this norm
+ // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
+ shadow = min(shadow, dp_directional_light);
+
+ //lpos.xy /= lpos.w*32.0;
+ //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
+ //{
+ // shadow = 0.0;
+ //}
+
+ }
+ }
+ else
+ {
+ // more distant than the shadow map covers
+ shadow = 1.0;
+ }
+
+ fcol[0] += shadow;
+ fcol[1] += 1.0;
+
+ spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
+
+ //spotlight shadow 1
+ vec4 lpos = shadow_matrix[4]*spos;
+ fcol[2] += pcfShadow(shadowMap4, lpos, 0.8);
+
+ //spotlight shadow 2
+ lpos = shadow_matrix[5]*spos;
+ fcol[3] += pcfShadow(shadowMap5, lpos, 0.8);
+ }
+
+ gl_FragColor = fcol/samples;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index 847b36b1ac..d53850b489 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -5,7 +5,7 @@
* $License$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
@@ -45,7 +45,7 @@ uniform float spot_shadow_offset;
vec4 getPosition(vec2 pos_screen)
{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
+ float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
@@ -234,7 +234,7 @@ void main()
gl_FragColor[0] = shadow;
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
- spos.xyz = shadow_pos+offset*spot_shadow_offset;
+ spos.xyz = shadow_pos+norm*spot_shadow_offset;
//spotlight shadow 1
vec4 lpos = shadow_matrix[4]*spos;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl
new file mode 100644
index 0000000000..a2a76eed9f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOMSF.glsl
@@ -0,0 +1,241 @@
+/**
+ * @file sunLightSSAOF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+
+
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_texture_multisample : enable
+
+//class 2 -- shadows and SSAO
+
+uniform sampler2DMS depthMap;
+uniform sampler2DMS normalMap;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+uniform sampler2D noiseMap;
+
+// Inputs
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+varying vec2 vary_fragcoord;
+varying vec4 vary_light;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+
+uniform float shadow_bias;
+uniform float shadow_offset;
+
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+
+vec4 getPosition(ivec2 pos_screen, int sample)
+{
+ float depth = texelFetch(depthMap, pos_screen, sample).r;
+ vec2 sc = vec2(pos_screen.xy)*2.0;
+ sc /= screen_res;
+ sc -= vec2(1.0,1.0);
+ vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+ vec4 pos = inv_proj * ndc;
+ pos /= pos.w;
+ pos.w = 1.0;
+ return pos;
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm, int sample)
+{
+ float ret = 1.0;
+
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+ kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+ kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+ kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+ kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+ kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+ kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+ kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec3 pos_world = pos.xyz;
+ vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+
+ float angle_hidden = 0.0;
+ int points = 0;
+
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ ivec2 samppos_screen = ivec2(pos_screen + scale * reflect(kern[i], noise_reflect));
+ vec3 samppos_world = getPosition(samppos_screen, sample).xyz;
+
+ vec3 diff = pos_world - samppos_world;
+ float dist2 = dot(diff, diff);
+
+ // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+ // --> solid angle shrinking by the square of distance
+ //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+ //(k should vary inversely with # of samples, but this is taken care of later)
+
+ angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+
+ // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
+ points = points + int(diff.z > -1.0);
+ }
+
+ angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+
+ ret = (1.0 - (float(points != 0) * angle_hidden));
+
+ return min(ret, 1.0);
+}
+
+float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += shadow_bias*scl;
+
+ float cs = shadow2DRect(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
+ shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
+{
+ stc.xyz /= stc.w;
+ stc.z += spot_shadow_bias*scl;
+
+ float cs = shadow2D(shadowMap, stc.xyz).x;
+ float shadow = cs;
+
+ vec2 off = 1.5/proj_shadow_res;
+
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
+ shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
+
+
+ return shadow/5.0;
+
+ //return shadow;
+}
+
+void main()
+{
+ vec2 pos_screen = vary_fragcoord.xy;
+ ivec2 itc = ivec2(pos_screen);
+ vec4 fcol = vec4(0,0,0,0);
+
+ for (int i = 0; i < samples; i++)
+ {
+ vec4 pos = getPosition(itc, i);
+
+ vec4 nmap4 = texelFetch(normalMap, itc, i);
+ nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm
+ float displace = nmap4.w;
+ vec3 norm = nmap4.xyz;
+
+ float shadow = 1.0;
+ float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
+
+ vec3 shadow_pos = pos.xyz + displace*norm;
+ vec3 offset = vary_light.xyz * (1.0-dp_directional_light);
+
+ vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
+
+ if (spos.z > -shadow_clip.w)
+ {
+ if (dp_directional_light == 0.0)
+ {
+ // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
+ shadow = 0.0;
+ }
+ else
+ {
+ vec4 lpos;
+
+ if (spos.z < -shadow_clip.z)
+ {
+ lpos = shadow_matrix[3]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap3, lpos, 0.25);
+ shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+ }
+ else if (spos.z < -shadow_clip.y)
+ {
+ lpos = shadow_matrix[2]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap2, lpos, 0.5);
+ }
+ else if (spos.z < -shadow_clip.x)
+ {
+ lpos = shadow_matrix[1]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap1, lpos, 0.75);
+ }
+ else
+ {
+ lpos = shadow_matrix[0]*spos;
+ lpos.xy *= shadow_res;
+ shadow = pcfShadow(shadowMap0, lpos, 1.0);
+ }
+
+ // take the most-shadowed value out of these two:
+ // * the blurred sun shadow in the light (shadow) map
+ // * an unblurred dot product between the sun and this norm
+ // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
+ shadow = min(shadow, dp_directional_light);
+
+ }
+ }
+ else
+ {
+ // more distant than the shadow map covers
+ shadow = 1.0;
+ }
+
+
+ fcol[0] += shadow;
+ fcol[1] += calcAmbientOcclusion(pos, norm, i);
+
+ spos.xyz = shadow_pos+offset*spot_shadow_offset;
+
+ //spotlight shadow 1
+ vec4 lpos = shadow_matrix[4]*spos;
+ fcol[2] += pcfShadow(shadowMap4, lpos, 0.8);
+
+ //spotlight shadow 2
+ lpos = shadow_matrix[5]*spos;
+ fcol[3] += pcfShadow(shadowMap5, lpos, 0.8);
+ }
+
+ gl_FragColor = fcol / samples;
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
index 9beb513ad8..814deb3677 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec4 vary_light;
varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl
index a4ad0bfa15..dff4d4a68f 100644
--- a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect RenderTexture;
uniform float bloomStrength;
diff --git a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl
index d471a6c5e5..de469542f9 100644
--- a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec2 texelSize;
uniform vec2 blurDirection;
diff --git a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl
index 66880b958e..8871bb3fc7 100644
--- a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect RenderTexture;
uniform float brightness;
diff --git a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl
index c35c500d62..9c52b8dd5d 100644
--- a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void main(void)
{
diff --git a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl
index e77baa5bee..713f8021de 100644
--- a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect RenderTexture;
uniform float extractLow;
diff --git a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl
index 8e0eec6f5e..fd94b2e95f 100644
--- a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect RenderTexture;
uniform sampler2D NoiseTexture;
diff --git a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl
index 98a50e22fc..a1a9c9716c 100644
--- a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl
+++ b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect RenderTexture;
diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl
index bbb8951f3a..9527dc469b 100644
--- a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D detail_0;
uniform sampler2D detail_1;
diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl
index 84906c16bf..2658bee88d 100644
--- a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
void calcAtmospherics(vec3 inPositionEye);
diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl
index 7590c542ef..974e227b77 100644
--- a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D detail_0;
uniform sampler2D detail_1;
diff --git a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl
index 900f1a6cb8..702e0881ac 100644
--- a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
index f4f6b6e90f..c4e4bc08c5 100644
--- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec3 scaleSoftClip(vec3 inColor);
vec3 atmosTransport(vec3 inColor);
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl
index 9f3328cbf0..b66b72b401 100644
--- a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec4 lightnorm;
uniform vec4 waterPlane;
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
index 342bc2ab66..4c31602736 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl
@@ -5,16 +5,14 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
vec3 atmosLighting(vec3 light);
vec3 scaleSoftClip(vec3 light);
void default_lighting()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
color.rgb = atmosLighting(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl
index dad18b5883..95bd052b5d 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl
@@ -5,16 +5,14 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
vec3 fullbrightAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
void fullbright_lighting()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
color.rgb = fullbrightAtmosTransport(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl
new file mode 100644
index 0000000000..b1e61e1a33
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl
@@ -0,0 +1,25 @@
+/**
+ * @file lightFullbrightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+vec3 fullbrightAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+uniform sampler2D diffuseMap;
+
+void fullbright_lighting()
+{
+ vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color;
+
+ color.rgb = fullbrightAtmosTransport(color.rgb);
+
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+
+ gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl
index 73ff81e03a..26f0ea84e0 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl
@@ -5,9 +5,8 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
+
uniform samplerCube environmentMap;
vec3 fullbrightShinyAtmosTransport(vec3 light);
@@ -15,7 +14,7 @@ vec3 fullbrightScaleSoftClip(vec3 light);
void fullbright_shiny_lighting()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy);
color.rgb *= gl_Color.rgb;
vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl
new file mode 100644
index 0000000000..953298da0d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl
@@ -0,0 +1,32 @@
+/**
+ * @file lightFullbrightShinyF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+uniform samplerCube environmentMap;
+uniform sampler2D diffuseMap;
+
+vec3 fullbrightShinyAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void fullbright_shiny_lighting()
+{
+ vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ color.rgb *= gl_Color.rgb;
+
+ vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
+ color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+ color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+
+ color.a = max(color.a, gl_Color.a);
+
+ gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl
index 9b4b584369..a6e10a249d 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl
@@ -5,9 +5,9 @@
* $License$
*/
-#version 120
-uniform sampler2D diffuseMap;
+
+
uniform samplerCube environmentMap;
vec3 fullbrightShinyAtmosTransport(vec3 light);
@@ -16,7 +16,7 @@ vec4 applyWaterFog(vec4 color);
void fullbright_shiny_lighting_water()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy);
color.rgb *= gl_Color.rgb;
vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
new file mode 100644
index 0000000000..b4bb665a2b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
@@ -0,0 +1,32 @@
+/**
+ * @file lightFullbrightShinyWaterF.glsl
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+
+
+
+uniform samplerCube environmentMap;
+uniform sampler2D diffuseMap;
+
+vec3 fullbrightShinyAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void fullbright_shiny_lighting_water()
+{
+ vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy);
+ color.rgb *= gl_Color.rgb;
+
+ vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
+ color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+ color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+ color.rgb = fullbrightScaleSoftClip(color.rgb);
+ color.a = max(color.a, gl_Color.a);
+
+ gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl
index 3d46c8d874..887d4130e7 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl
@@ -5,16 +5,16 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
+
+vec4 diffuseLookup(vec2 texcoord);
vec3 fullbrightAtmosTransport(vec3 light);
vec4 applyWaterFog(vec4 color);
void fullbright_lighting_water()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
color.rgb = fullbrightAtmosTransport(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl
new file mode 100644
index 0000000000..1234682ae9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl
@@ -0,0 +1,23 @@
+/**
+ * @file lightFullbrightWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+uniform sampler2D diffuseMap;
+
+vec3 fullbrightAtmosTransport(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void fullbright_lighting_water()
+{
+ vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+
+ color.rgb = fullbrightAtmosTransport(color.rgb);
+
+ gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl
new file mode 100644
index 0000000000..149cf791f5
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl
@@ -0,0 +1,25 @@
+/**
+ * @file lightF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+uniform sampler2D diffuseMap;
+
+vec3 atmosLighting(vec3 light);
+vec3 scaleSoftClip(vec3 light);
+
+void default_lighting()
+{
+ vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+
+ gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl
index ebe21320b4..300fcac092 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl
@@ -5,9 +5,9 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
+
+
uniform samplerCube environmentMap;
vec3 scaleSoftClip(vec3 light);
@@ -16,7 +16,7 @@ vec4 applyWaterFog(vec4 color);
void shiny_lighting()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy);
color.rgb *= gl_Color.rgb;
vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl
new file mode 100644
index 0000000000..e877c0abb1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl
@@ -0,0 +1,32 @@
+/**
+ * @file lightShinyF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+
+uniform samplerCube environmentMap;
+uniform sampler2D diffuseMap;
+
+vec3 scaleSoftClip(vec3 light);
+vec3 atmosLighting(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void shiny_lighting()
+{
+ vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy);
+ color.rgb *= gl_Color.rgb;
+
+ vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
+ color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+ color.rgb = atmosLighting(color.rgb);
+
+ color.rgb = scaleSoftClip(color.rgb);
+ color.a = max(color.a, gl_Color.a);
+ gl_FragColor = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl
index 7f48e2cf1d..07572fa915 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl
@@ -5,10 +5,9 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
+
uniform samplerCube environmentMap;
vec3 atmosLighting(vec3 light);
@@ -16,7 +15,7 @@ vec4 applyWaterFog(vec4 color);
void shiny_lighting_water()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy);
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy);
color.rgb *= gl_Color.rgb;
vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl
new file mode 100644
index 0000000000..3904179427
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl
@@ -0,0 +1,29 @@
+/**
+ * @file lightShinyWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+
+uniform sampler2D diffuseMap;
+uniform samplerCube environmentMap;
+
+vec3 atmosLighting(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void shiny_lighting_water()
+{
+ vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy);
+ color.rgb *= gl_Color.rgb;
+
+ vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb;
+ color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a);
+
+ color.rgb = atmosLighting(color.rgb);
+ color.a = max(color.a, gl_Color.a);
+ gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl
index ad1dc4da77..3384f64d07 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
// All lights, no specular highlights
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl
index a0f6e019ef..10c770fcc2 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
// All lights, no specular highlights
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl
index 97eba92d7b..61341a9f1f 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl
@@ -5,16 +5,14 @@
* $/LicenseInfo$
*/
-#version 120
-uniform sampler2D diffuseMap;
vec3 atmosLighting(vec3 light);
vec4 applyWaterFog(vec4 color);
void default_lighting_water()
{
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color;
+ vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color;
color.rgb = atmosLighting(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl
new file mode 100644
index 0000000000..ba850b61d0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl
@@ -0,0 +1,23 @@
+/**
+ * @file lightWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+uniform sampler2D diffuseMap;
+
+vec3 atmosLighting(vec3 light);
+vec4 applyWaterFog(vec4 color);
+
+void default_lighting_water()
+{
+ vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color;
+
+ color.rgb = atmosLighting(color.rgb);
+
+ gl_FragColor = applyWaterFog(color);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
index fde32ed035..8df2e6f222 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
index 8fe49e3be0..3d43a1813a 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l);
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
new file mode 100644
index 0000000000..f49e74406f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl
@@ -0,0 +1,35 @@
+/**
+ * @file fullbrightShinyV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+void calcAtmospherics(vec3 inPositionEye);
+
+uniform vec4 origin;
+
+varying float vary_texture_index;
+
+void main()
+{
+ //transform vertex
+ vec4 vert = vec4(gl_Vertex.xyz,1.0);
+ vary_texture_index = gl_Vertex.w;
+ gl_Position = gl_ModelViewProjectionMatrix*vert;
+
+ vec4 pos = (gl_ModelViewMatrix * vert);
+ vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+ vec3 ref = reflect(pos.xyz, -norm);
+
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0);
+
+ calcAtmospherics(pos.xyz);
+
+ gl_FrontColor = gl_Color;
+
+ gl_FogFragCoord = pos.z;
+}
diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
new file mode 100644
index 0000000000..3076fa3260
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl
@@ -0,0 +1,29 @@
+/**
+ * @file fullbrightV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+void calcAtmospherics(vec3 inPositionEye);
+
+varying float vary_texture_index;
+
+void main()
+{
+ //transform vertex
+ vec4 vert = vec4(gl_Vertex.xyz,1.0);
+ vary_texture_index = gl_Vertex.w;
+ gl_Position = gl_ModelViewProjectionMatrix*vert;
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+
+ vec4 pos = (gl_ModelViewMatrix * vert);
+
+ calcAtmospherics(pos.xyz);
+
+ gl_FrontColor = gl_Color;
+
+ gl_FogFragCoord = pos.z;
+}
diff --git a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
index 4cebb06df0..49992d3535 100644
--- a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl
@@ -5,20 +5,24 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
+varying float vary_texture_index;
+
uniform vec4 origin;
void main()
{
//transform vertex
- gl_Position = ftransform();
+ vec4 vert = vec4(gl_Vertex.xyz,1.0);
+ vary_texture_index = gl_Vertex.w;
+ gl_Position = gl_ModelViewProjectionMatrix*vert;
- vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
+ vec4 pos = (gl_ModelViewMatrix * vert);
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
vec3 ref = reflect(pos.xyz, -norm);
diff --git a/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
new file mode 100644
index 0000000000..5e02391767
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl
@@ -0,0 +1,33 @@
+/**
+ * @file simpleV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $/LicenseInfo$
+ */
+
+
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+void calcAtmospherics(vec3 inPositionEye);
+
+varying float vary_texture_index;
+
+void main()
+{
+ //transform vertex
+ vec4 vert = vec4(gl_Vertex.xyz,1.0);
+ vary_texture_index = gl_Vertex.w;
+ gl_Position = gl_ModelViewProjectionMatrix*vert;
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+
+ vec4 pos = (gl_ModelViewMatrix * vert);
+
+ vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
+
+ calcAtmospherics(pos.xyz);
+
+ vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
+ gl_FrontColor = color;
+
+ gl_FogFragCoord = pos.z;
+}
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
index 77d15fba9a..21a0812c1b 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
//////////////////////////////////////////////////////////
// The fragment shader for the terrain atmospherics
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
index 8c5b864cbe..ab4cf4806d 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
// Output variables
vec3 getSunlitColor();
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
index 8d365c15ca..b61b0bb396 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
// varying param funcs
void setSunlitColor(vec3 v);
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
index cf9ef30632..3a6585bb33 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_PositionEye;
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
index 398f1556a0..0f6e231ca6 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec3 vary_PositionEye;
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
index 13207997b2..20f907a006 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
/////////////////////////////////////////////////////////////////////////
// The fragment shader for the sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index 267ef36d4d..3eac63076c 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
//////////////////////////////////////////////////////////////////////////
// The vertex shader for creating the atmospheric sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
index a658edd21f..6570dcb608 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec4 gamma;
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
index 77ca4868a6..d14c638130 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
/////////////////////////////////////////////////////////////////////////
// The fragment shader for the sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index 03bca8f27e..1ea00f723a 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
// SKY ////////////////////////////////////////////////////////////////////////
// The vertex shader for creating the atmospheric sky
diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
index 7f1ad4d5b4..28381482c1 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
@@ -5,8 +5,6 @@
* $/LicenseInfo$
*/
-#version 120
-
//////////////////////////////////////////////////////////
// The fragment shader for the terrain atmospherics
//////////////////////////////////////////////////////////
diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
index a003e2a1f1..3d970d252c 100644
--- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
index fc370ef367..498fee7c66 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2DRect giLightMap;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
index ae57227fe5..eebe930666 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
index 951e3e97ae..9896f8dafe 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
index b2f8b2c633..df4c6b3e0a 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
index 19c4e07b8b..7e20d71529 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
index 8dc1410ea5..e86f2896da 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
index 5f3bf68b24..980def6443 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
index a24eda35dc..9afeac6ddf 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
index ab99a88971..6d4c20f68c 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
index 12983baa94..876f65ee3a 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
index f037754708..fc65881680 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
index ae57227fe5..eebe930666 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
varying vec2 vary_fragcoord;
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index ce32f66000..d38d33cc21 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
#extension GL_ARB_texture_rectangle : enable
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
index 8f0bcca76b..745cc01992 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform vec2 screen_res;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
index c54d9a1e3e..de7e038402 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
uniform sampler2D diffuseMap;
diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
index 04533fdce1..92347a5b4a 100644
--- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol);
diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
index 73bc18b866..24bbc0a1a1 100644
--- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
@@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
-#version 120
+
float calcDirectionalLight(vec3 n, vec3 l);
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
diff --git a/indra/newview/app_settings/windlight/days/Colder%20Tones.xml b/indra/newview/app_settings/windlight/days/Colder%20Tones.xml
new file mode 100644
index 0000000000..63d0b099e1
--- /dev/null
+++ b/indra/newview/app_settings/windlight/days/Colder%20Tones.xml
@@ -0,0 +1,28 @@
+<llsd>
+ <array>
+ <array>
+ <real>0</real>
+ <string>Midnight</string>
+ </array>
+ <array>
+ <real>0.24999989569187164</real>
+ <string>Purple</string>
+ </array>
+ <array>
+ <real>0.49999979138374329</real>
+ <string>Blue Midday</string>
+ </array>
+ <array>
+ <real>0.74999970197677612</real>
+ <string>Blizzard</string>
+ </array>
+ <array>
+ <real>0.87499958276748657</real>
+ <string>Ghost</string>
+ </array>
+ <array>
+ <real>0.99999958276748657</real>
+ <string>Midnight</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/days/Dynamic%20Richness.xml b/indra/newview/app_settings/windlight/days/Dynamic%20Richness.xml
new file mode 100644
index 0000000000..f75b52e6ed
--- /dev/null
+++ b/indra/newview/app_settings/windlight/days/Dynamic%20Richness.xml
@@ -0,0 +1,32 @@
+<llsd>
+ <array>
+ <array>
+ <real>0</real>
+ <string>Night</string>
+ </array>
+ <array>
+ <real>0.12499994784593582</real>
+ <string>Blizzard</string>
+ </array>
+ <array>
+ <real>0.24999989569187164</real>
+ <string>Sunrise</string>
+ </array>
+ <array>
+ <real>0.49999979138374329</real>
+ <string>Midday 3</string>
+ </array>
+ <array>
+ <real>0.68749970197677612</real>
+ <string>Pirate</string>
+ </array>
+ <array>
+ <real>0.81249970197677612</real>
+ <string>Coastal Sunset</string>
+ </array>
+ <array>
+ <real>0.99999958276748657</real>
+ <string>Midnight</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/days/Pirate%27s%20Dream.xml b/indra/newview/app_settings/windlight/days/Pirate%27s%20Dream.xml
new file mode 100644
index 0000000000..6dc1ba9f4d
--- /dev/null
+++ b/indra/newview/app_settings/windlight/days/Pirate%27s%20Dream.xml
@@ -0,0 +1,44 @@
+<llsd>
+ <array>
+ <array>
+ <real>0</real>
+ <string>A-12AM</string>
+ </array>
+ <array>
+ <real>0.12499994784593582</real>
+ <string>A-3AM</string>
+ </array>
+ <array>
+ <real>0.22222213447093964</real>
+ <string>Barcelona</string>
+ </array>
+ <array>
+ <real>0.30208322405815125</real>
+ <string>Sunrise</string>
+ </array>
+ <array>
+ <real>0.37499985098838806</real>
+ <string>Sailor&apos;s Delight</string>
+ </array>
+ <array>
+ <real>0.53819423913955688</real>
+ <string>Coastal Afternoon</string>
+ </array>
+ <array>
+ <real>0.63194417953491211</real>
+ <string>Pirate</string>
+ </array>
+ <array>
+ <real>0.7048608660697937</real>
+ <string>Desert Sunset</string>
+ </array>
+ <array>
+ <real>0.74999970197677612</real>
+ <string>Coastal Sunset</string>
+ </array>
+ <array>
+ <real>0.87499958276748657</real>
+ <string>Blizzard</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/days/Psycho%20Strobe%21.xml b/indra/newview/app_settings/windlight/days/Psycho%20Strobe%21.xml
new file mode 100644
index 0000000000..302af5a9ba
--- /dev/null
+++ b/indra/newview/app_settings/windlight/days/Psycho%20Strobe%21.xml
@@ -0,0 +1,72 @@
+<llsd>
+ <array>
+ <array>
+ <real>0</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.062499973922967911</real>
+ <string>A-12AM</string>
+ </array>
+ <array>
+ <real>0.12499994784593582</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.18749992549419403</real>
+ <string>A-3AM</string>
+ </array>
+ <array>
+ <real>0.24999989569187164</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.31249985098838806</real>
+ <string>A-6AM</string>
+ </array>
+ <array>
+ <real>0.37499985098838806</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.43749979138374329</real>
+ <string>A-9AM</string>
+ </array>
+ <array>
+ <real>0.49999979138374329</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.5624997615814209</real>
+ <string>A-12PM</string>
+ </array>
+ <array>
+ <real>0.62499970197677612</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.68749970197677612</real>
+ <string>A-3PM</string>
+ </array>
+ <array>
+ <real>0.74999970197677612</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.81249970197677612</real>
+ <string>A-6PM</string>
+ </array>
+ <array>
+ <real>0.87499958276748657</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.93749958276748657</real>
+ <string>A-9PM</string>
+ </array>
+ <array>
+ <real>0.99999958276748657</real>
+ <string>Sheer Surreality</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/days/Tropicalia.xml b/indra/newview/app_settings/windlight/days/Tropicalia.xml
new file mode 100644
index 0000000000..89a56d4a13
--- /dev/null
+++ b/indra/newview/app_settings/windlight/days/Tropicalia.xml
@@ -0,0 +1,32 @@
+<llsd>
+ <array>
+ <array>
+ <real>0.062499973922967911</real>
+ <string>Purple</string>
+ </array>
+ <array>
+ <real>0.16666659712791443</real>
+ <string>Funky Funky</string>
+ </array>
+ <array>
+ <real>0.31249985098838806</real>
+ <string>Sunrise</string>
+ </array>
+ <array>
+ <real>0.49999979138374329</real>
+ <string>Fine Day</string>
+ </array>
+ <array>
+ <real>0.66666638851165771</real>
+ <string>Desert Sunset</string>
+ </array>
+ <array>
+ <real>0.74999970197677612</real>
+ <string>Sailor&apos;s Delight</string>
+ </array>
+ <array>
+ <real>0.95833295583724976</real>
+ <string>Midnight</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/days/Weird-O.xml b/indra/newview/app_settings/windlight/days/Weird-O.xml
new file mode 100644
index 0000000000..1e312f2464
--- /dev/null
+++ b/indra/newview/app_settings/windlight/days/Weird-O.xml
@@ -0,0 +1,56 @@
+<llsd>
+ <array>
+ <array>
+ <real>0</real>
+ <string>Funky Funky</string>
+ </array>
+ <array>
+ <real>0.13194438815116882</real>
+ <string>Funky Funky Funky</string>
+ </array>
+ <array>
+ <real>0.26041656732559204</real>
+ <string>Gelatto</string>
+ </array>
+ <array>
+ <real>0.40624985098838806</real>
+ <string>Funky Funky Funky</string>
+ </array>
+ <array>
+ <real>0.43749979138374329</real>
+ <string>Ghost</string>
+ </array>
+ <array>
+ <real>0.46874979138374329</real>
+ <string>Gelatto</string>
+ </array>
+ <array>
+ <real>0.5486108660697937</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.6076386570930481</real>
+ <string>Gelatto</string>
+ </array>
+ <array>
+ <real>0.68055528402328491</real>
+ <string>Ghost</string>
+ </array>
+ <array>
+ <real>0.75694411993026733</real>
+ <string>Sheer Surreality</string>
+ </array>
+ <array>
+ <real>0.87847185134887695</real>
+ <string>Gelatto</string>
+ </array>
+ <array>
+ <real>0.91319411993026733</real>
+ <string>Funky Funky Funky</string>
+ </array>
+ <array>
+ <real>0.96527737379074097</real>
+ <string>Funky Funky Funky</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/skies/Midday.xml b/indra/newview/app_settings/windlight/skies/Midday.xml
new file mode 100644
index 0000000000..119b3e1418
--- /dev/null
+++ b/indra/newview/app_settings/windlight/skies/Midday.xml
@@ -0,0 +1,141 @@
+<llsd>
+ <map>
+ <key>ambient</key>
+ <array>
+ <real>1.0499999523162842</real>
+ <real>1.0499999523162842</real>
+ <real>1.0499999523162842</real>
+ <real>0.34999999403953552</real>
+ </array>
+ <key>blue_density</key>
+ <array>
+ <real>0.24475815892219543</real>
+ <real>0.44872328639030457</real>
+ <real>0.75999999046325684</real>
+ <real>0.37999999523162842</real>
+ </array>
+ <key>blue_horizon</key>
+ <array>
+ <real>0.49548381567001343</real>
+ <real>0.49548381567001343</real>
+ <real>0.63999998569488525</real>
+ <real>0.31999999284744263</real>
+ </array>
+ <key>cloud_color</key>
+ <array>
+ <real>0.40999999642372131</real>
+ <real>0.40999999642372131</real>
+ <real>0.40999999642372131</real>
+ <real>0.40999999642372131</real>
+ </array>
+ <key>cloud_pos_density1</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>1</real>
+ <real>1</real>
+ </array>
+ <key>cloud_pos_density2</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.125</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scale</key>
+ <array>
+ <real>0.41999998688697815</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scroll_rate</key>
+ <array>
+ <real>10.199999809265137</real>
+ <real>10.01099967956543</real>
+ </array>
+ <key>cloud_shadow</key>
+ <array>
+ <real>0.26999998092651367</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>density_multiplier</key>
+ <array>
+ <real>0.00017999998817685992</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>distance_multiplier</key>
+ <array>
+ <real>0.80000001192092896</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>east_angle</key>
+ <real>0</real>
+ <key>enable_cloud_scroll</key>
+ <array>
+ <boolean>1</boolean>
+ <boolean>1</boolean>
+ </array>
+ <key>gamma</key>
+ <array>
+ <real>1</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>glow</key>
+ <array>
+ <real>5</real>
+ <real>0.0010000000474974513</real>
+ <real>-0.47999998927116394</real>
+ <real>1</real>
+ </array>
+ <key>haze_density</key>
+ <array>
+ <real>0.69999998807907104</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>haze_horizon</key>
+ <array>
+ <real>0.18999999761581421</real>
+ <real>0.19915600121021271</real>
+ <real>0.19915600121021271</real>
+ <real>1</real>
+ </array>
+ <key>lightnorm</key>
+ <array>
+ <real>0</real>
+ <real>1</real>
+ <real>-4.3711388286737929e-008</real>
+ <real>0</real>
+ </array>
+ <key>max_y</key>
+ <array>
+ <real>1605</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>preset_num</key>
+ <integer>22</integer>
+ <key>star_brightness</key>
+ <real>0</real>
+ <key>sun_angle</key>
+ <real>1.5707963705062866</real>
+ <key>sunlight_color</key>
+ <array>
+ <real>0.7342105507850647</real>
+ <real>0.78157895803451538</real>
+ <real>0.89999997615814209</real>
+ <real>0.29999998211860657</real>
+ </array>
+ </map>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/skies/Midnight.xml b/indra/newview/app_settings/windlight/skies/Midnight.xml
new file mode 100644
index 0000000000..0aba31214a
--- /dev/null
+++ b/indra/newview/app_settings/windlight/skies/Midnight.xml
@@ -0,0 +1,141 @@
+<llsd>
+ <map>
+ <key>ambient</key>
+ <array>
+ <real>0.20405027270317078</real>
+ <real>0.24246673285961151</real>
+ <real>0.32999998331069946</real>
+ <real>0.10999999940395355</real>
+ </array>
+ <key>blue_density</key>
+ <array>
+ <real>0.44999998807907104</real>
+ <real>0.44999998807907104</real>
+ <real>0.44999998807907104</real>
+ <real>1</real>
+ </array>
+ <key>blue_horizon</key>
+ <array>
+ <real>0.23999999463558197</real>
+ <real>0.23999999463558197</real>
+ <real>0.23999999463558197</real>
+ <real>1</real>
+ </array>
+ <key>cloud_color</key>
+ <array>
+ <real>0.22615399956703186</real>
+ <real>0.22615399956703186</real>
+ <real>0.22615399956703186</real>
+ <real>1</real>
+ </array>
+ <key>cloud_pos_density1</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.87999999523162842</real>
+ <real>1</real>
+ </array>
+ <key>cloud_pos_density2</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.125</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scale</key>
+ <array>
+ <real>0.41999998688697815</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scroll_rate</key>
+ <array>
+ <real>10.49940013885498</real>
+ <real>10.01099967956543</real>
+ </array>
+ <key>cloud_shadow</key>
+ <array>
+ <real>0.26999998092651367</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>density_multiplier</key>
+ <array>
+ <real>0.00030000001424923539</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>distance_multiplier</key>
+ <array>
+ <real>0</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>east_angle</key>
+ <real>0</real>
+ <key>enable_cloud_scroll</key>
+ <array>
+ <boolean>1</boolean>
+ <boolean>1</boolean>
+ </array>
+ <key>gamma</key>
+ <array>
+ <real>1</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>glow</key>
+ <array>
+ <real>5</real>
+ <real>0.0010000000474974513</real>
+ <real>-0.47999998927116394</real>
+ <real>1</real>
+ </array>
+ <key>haze_density</key>
+ <array>
+ <real>4</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>haze_horizon</key>
+ <array>
+ <real>0</real>
+ <real>0.19915600121021271</real>
+ <real>0.19915600121021271</real>
+ <real>1</real>
+ </array>
+ <key>lightnorm</key>
+ <array>
+ <real>0</real>
+ <real>1</real>
+ <real>-4.8876205482883961e-007</real>
+ <real>1</real>
+ </array>
+ <key>max_y</key>
+ <array>
+ <real>906.20001220703125</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>preset_num</key>
+ <integer>22</integer>
+ <key>star_brightness</key>
+ <real>2</real>
+ <key>sun_angle</key>
+ <real>4.7123894691467285</real>
+ <key>sunlight_color</key>
+ <array>
+ <real>0.34876692295074463</real>
+ <real>0.35574248433113098</real>
+ <real>0.65999996662139893</real>
+ <real>0.2199999988079071</real>
+ </array>
+ </map>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/skies/Sunrise.xml b/indra/newview/app_settings/windlight/skies/Sunrise.xml
new file mode 100644
index 0000000000..bbc7aeec59
--- /dev/null
+++ b/indra/newview/app_settings/windlight/skies/Sunrise.xml
@@ -0,0 +1,141 @@
+<llsd>
+ <map>
+ <key>ambient</key>
+ <array>
+ <real>0.80999994277954102</real>
+ <real>0.46289783716201782</real>
+ <real>0.62999993562698364</real>
+ <real>0.26999998092651367</real>
+ </array>
+ <key>blue_density</key>
+ <array>
+ <real>0.15793180465698242</real>
+ <real>0.43499568104743958</real>
+ <real>0.87000000476837158</real>
+ <real>0.87000000476837158</real>
+ </array>
+ <key>blue_horizon</key>
+ <array>
+ <real>0.20673196017742157</real>
+ <real>0.40988314151763916</real>
+ <real>0.47999998927116394</real>
+ <real>0.47999998927116394</real>
+ </array>
+ <key>cloud_color</key>
+ <array>
+ <real>0.22616604226328718</real>
+ <real>0.22616604226328718</real>
+ <real>0.22616604226328718</real>
+ <real>0.99997219085526012</real>
+ </array>
+ <key>cloud_pos_density1</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.88000025272481253</real>
+ <real>1</real>
+ </array>
+ <key>cloud_pos_density2</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.125</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scale</key>
+ <array>
+ <real>0.41999998688697815</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scroll_rate</key>
+ <array>
+ <real>10.49940013883861</real>
+ <real>10.010999679576344</real>
+ </array>
+ <key>cloud_shadow</key>
+ <array>
+ <real>0.26999998092651367</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>density_multiplier</key>
+ <array>
+ <real>0.00062000000616535544</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>distance_multiplier</key>
+ <array>
+ <real>2.6999279499073054</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>east_angle</key>
+ <real>0</real>
+ <key>enable_cloud_scroll</key>
+ <array>
+ <boolean>1</boolean>
+ <boolean>1</boolean>
+ </array>
+ <key>gamma</key>
+ <array>
+ <real>1</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>glow</key>
+ <array>
+ <real>5.0009990693069994</real>
+ <real>0.0010000000474963411</real>
+ <real>-0.48000101923815919</real>
+ <real>1</real>
+ </array>
+ <key>haze_density</key>
+ <array>
+ <real>0.53999996185302734</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>haze_horizon</key>
+ <array>
+ <real>0.15999999642372131</real>
+ <real>0.19915600121021271</real>
+ <real>0.19915600121021271</real>
+ <real>1</real>
+ </array>
+ <key>lightnorm</key>
+ <array>
+ <real>0</real>
+ <real>0.094108223915100098</real>
+ <real>0.99556195735931396</real>
+ <real>0</real>
+ </array>
+ <key>max_y</key>
+ <array>
+ <real>563</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>preset_num</key>
+ <integer>22</integer>
+ <key>star_brightness</key>
+ <real>0</real>
+ <key>sun_angle</key>
+ <real>0.094247691333293915</real>
+ <key>sunlight_color</key>
+ <array>
+ <real>2.369999885559082</real>
+ <real>2.369999885559082</real>
+ <real>2.369999885559082</real>
+ <real>0.78999996185302734</real>
+ </array>
+ </map>
+</llsd>
diff --git a/indra/newview/app_settings/windlight/skies/Sunset.xml b/indra/newview/app_settings/windlight/skies/Sunset.xml
new file mode 100644
index 0000000000..ebf08e1a3f
--- /dev/null
+++ b/indra/newview/app_settings/windlight/skies/Sunset.xml
@@ -0,0 +1,142 @@
+<llsd>
+ <map>
+ <key>ambient</key>
+ <array>
+ <real>1.0199999809265137</real>
+ <real>0.80999994277954102</real>
+ <real>0.80999994277954102</real>
+ <real>1.0199999809265137</real>
+ </array>
+ <key>blue_density</key>
+ <array>
+ <real>0.14522500336170197</real>
+ <real>0.39999699592590332</real>
+ <real>0.80000197887420654</real>
+ <real>1</real>
+ </array>
+ <key>blue_horizon</key>
+ <array>
+ <real>0.10767599940299988</real>
+ <real>0.21348699927330017</real>
+ <real>0.25</real>
+ <real>1</real>
+ </array>
+ <key>cloud_color</key>
+ <array>
+ <real>0.22615399956703186</real>
+ <real>0.22615399956703186</real>
+ <real>0.22615399956703186</real>
+ <real>1</real>
+ </array>
+ <key>cloud_pos_density1</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.87999999523162842</real>
+ <real>1</real>
+ </array>
+ <key>cloud_pos_density2</key>
+ <array>
+ <real>1.6884100437164307</real>
+ <real>0.52609699964523315</real>
+ <real>0.125</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scale</key>
+ <array>
+ <real>0.41999998688697815</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>cloud_scroll_rate</key>
+ <array>
+ <real>10.49940013885498</real>
+ <real>10.01099967956543</real>
+ </array>
+ <key>cloud_shadow</key>
+ <array>
+ <real>0.26999998092651367</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>density_multiplier</key>
+ <array>
+ <real>0.00046000001020729542</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>distance_multiplier</key>
+ <array>
+ <real>1</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>east_angle</key>
+ <real>0</real>
+ <key>enable_cloud_scroll</key>
+ <array>
+ <boolean>1</boolean>
+ <boolean>1</boolean>
+ </array>
+ <key>gamma</key>
+ <array>
+ <real>1</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>glow</key>
+ <array>
+ <real>5</real>
+ <real>0.0010000000474974513</real>
+ <real>-0.47999998927116394</real>
+ <real>1</real>
+ </array>
+ <key>haze_density</key>
+ <array>
+ <real>0.69999998807907104</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>haze_horizon</key>
+ <array>
+ <real>0.15999999642372131</real>
+ <real>0.19915600121021271</real>
+ <real>0.19915600121021271</real>
+ <real>1</real>
+ </array>
+ <key>lightnorm</key>
+ <array>
+ <real>0</real>
+ <real>0.07532646507024765</real>
+ <real>-0.99715894460678101</real>
+ <real>0</real>
+ </array>
+ <key>max_y</key>
+ <array>
+ <real>562.5</real>
+ <real>0</real>
+ <real>0</real>
+ <real>1</real>
+ </array>
+ <key>preset_num</key>
+ <integer>22</integer>
+ <key>star_brightness</key>
+ <real>0</real>
+ <key>sun_angle</key>
+ <real>3.0661947727203369</real>
+ <key>sunlight_color</key>
+ <array>
+ <real>2.8385701179504395</real>
+ <real>2.8385701179504395</real>
+ <real>2.8385701179504395</real>
+ <real>1</real>
+ </array>
+ </map>
+</llsd>
+
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index dd8a88e558..22c79a4cbd 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 27
+version 30
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
+RenderVBOMappingDisable 1 1
RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
@@ -59,11 +60,11 @@ Disregard96DefaultDrawDistance 1 1
RenderTextureMemoryMultiple 1 1.0
RenderShaderLightingMaxLevel 1 3
RenderDeferred 1 1
-SkyUseClassicClouds 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
WatchdogDisabled 1 1
RenderUseStreamVBO 1 1
+RenderFSAASamples 1 16
//
// Low Graphics Settings
@@ -91,10 +92,10 @@ RenderVolumeLODFactor 1 0.5
VertexShaderEnable 1 0
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
-SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// Mid Graphics Settings
@@ -124,6 +125,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// High Graphics Settings (purty)
@@ -153,6 +155,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 4
//
// Ultra graphics (REALLY PURTY!)
@@ -181,6 +184,8 @@ WLSkyDetail 1 128
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
+RenderFSAASamples 1 8
+
//
// Class Unknown Hardware (unknown)
@@ -238,6 +243,12 @@ RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
+//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable 1 0
+
//
// "Default" setups for safe, low, medium, high
@@ -284,6 +295,7 @@ RenderDeferred 0 0
list Intel
RenderAnisotropic 1 0
+RenderVBOEnable 1 0
list GeForce2
RenderAnisotropic 1 0
@@ -467,7 +479,6 @@ RenderAvatarCloth 0 0
list ATI
RenderUseStreamVBO 1 0
-RenderAvatarVP 1 0
// Disable vertex buffer objects by default for ATI cards with little video memory
list ATIVramLT256
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 058bdcc730..649f5ebd18 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 23
+version 25
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
+RenderVBOMappingDisable 1 1
RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
@@ -57,11 +58,11 @@ WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
RenderTextureMemoryMultiple 1 1.0
-SkyUseClassicClouds 1 1
RenderShaderLightingMaxLevel 1 3
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
+RenderFSAASamples 1 16
//
// Low Graphics Settings
@@ -89,10 +90,10 @@ RenderVolumeLODFactor 1 0.5
VertexShaderEnable 1 0
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
-SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// Mid Graphics Settings
@@ -122,6 +123,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// High Graphics Settings (purty)
@@ -151,6 +153,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 4
//
// Ultra graphics (REALLY PURTY!)
@@ -180,6 +183,7 @@ WLSkyDetail 1 128
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
+RenderFSAASamples 1 8
//
// Class Unknown Hardware (unknown)
@@ -237,6 +241,13 @@ RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
+//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable 1 0
+
+
// "Default" setups for safe, low, medium, high
//
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index c075c660f3..ee08e78af5 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 23
+version 26
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
+RenderVBOMappingDisable 1 1
RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
@@ -58,12 +59,12 @@ Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
RenderTextureMemoryMultiple 1 0.5
RenderShaderLightingMaxLevel 1 3
-SkyUseClassicClouds 1 1
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
WatchdogDisabled 1 1
RenderUseStreamVBO 1 1
+RenderFSAASamples 1 16
//
// Low Graphics Settings
@@ -91,10 +92,10 @@ RenderVolumeLODFactor 1 0.5
VertexShaderEnable 1 0
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
-SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// Mid Graphics Settings
@@ -124,6 +125,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// High Graphics Settings (purty)
@@ -153,6 +155,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 2
+RenderFSAASamples 1 4
//
// Ultra graphics (REALLY PURTY!)
@@ -182,6 +185,7 @@ WLSkyDetail 1 128
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 2
+RenderFSAASamples 1 8
//
// Class Unknown Hardware (unknown)
@@ -240,6 +244,13 @@ RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable 1 0
+
+
+//
// "Default" setups for safe, low, medium, high
//
list safe
@@ -281,6 +292,9 @@ RenderVBOEnable 1 0
list TexUnit8orLess
RenderDeferredSSAO 0 0
+list ATI
+RenderDeferredSSAO 0 0
+
list Intel
RenderAnisotropic 1 0
RenderLocalLights 1 0
@@ -409,31 +423,6 @@ Disregard128DefaultDrawDistance 1 0
list ATI_Mobility_Radeon_X1xxx
Disregard128DefaultDrawDistance 1 0
-
-
-
-// Avatar hardware skinning causes
-// invisible avatars on HD 2600... so I masked
-// out other possible bad ones till it's fixed
-
-list ATI_Radeon_HD_2300
-RenderAvatarVP 0 0
-RenderAvatarCloth 0 0
-Disregard128DefaultDrawDistance 1 0
-list ATI_Radeon_HD_2400
-RenderAvatarVP 0 0
-RenderAvatarCloth 0 0
-Disregard128DefaultDrawDistance 1 0
-list ATI_Radeon_HD_2600
-RenderAvatarVP 0 0
-RenderAvatarCloth 0 0
-list ATI_Radeon_HD_2900
-RenderAvatarVP 0 0
-RenderAvatarCloth 0 0
-list ATI_Radeon_HD_3800
-RenderAvatarVP 0 0
-RenderAvatarCloth 0 0
-
/// Tweaked NVIDIA
list NVIDIA_GeForce_FX_5100
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index 3339172a1a..ba74f9a6c2 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -1,4 +1,4 @@
-version 27
+version 30
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -48,6 +48,7 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
+RenderVBOMappingDisable 1 1
RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
@@ -58,12 +59,12 @@ Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
RenderTextureMemoryMultiple 1 1.0
RenderShaderLightingMaxLevel 1 3
-SkyUseClassicClouds 1 1
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
WatchdogDisabled 1 1
RenderUseStreamVBO 1 1
+RenderFSAASamples 1 16
//
// Low Graphics Settings
@@ -91,10 +92,10 @@ RenderVolumeLODFactor 1 0.5
VertexShaderEnable 1 0
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
-SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// Mid Graphics Settings
@@ -124,6 +125,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
+RenderFSAASamples 1 0
//
// High Graphics Settings (purty)
@@ -153,6 +155,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 2
+RenderFSAASamples 1 4
//
// Ultra graphics (REALLY PURTY!)
@@ -182,6 +185,7 @@ WLSkyDetail 1 128
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 2
+RenderFSAASamples 1 8
//
// Class Unknown Hardware (unknown)
@@ -240,6 +244,13 @@ RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
//
+// No GL_ARB_map_buffer_range
+//
+list NoMapBufferRange
+RenderVBOMappingDisable 1 0
+
+
+//
// "Default" setups for safe, low, medium, high
//
list safe
@@ -282,6 +293,7 @@ RenderDeferred 0 0
list Intel
RenderAnisotropic 1 0
+RenderVBOEnable 1 0
list GeForce2
RenderAnisotropic 1 0
@@ -466,7 +478,6 @@ RenderAvatarCloth 0 0
list ATI
RenderUseStreamVBO 1 0
-RenderAvatarVP 1 0
// Disable vertex buffer objects by default for ATI cards with little video memory
list ATIVramLT256
diff --git a/indra/newview/groupchatlistener.cpp b/indra/newview/groupchatlistener.cpp
index 3758896b85..ef015a950d 100644
--- a/indra/newview/groupchatlistener.cpp
+++ b/indra/newview/groupchatlistener.cpp
@@ -4,8 +4,25 @@
* @date 2011-04-11
* @brief Implementation for groupchatlistener.
*
- * $LicenseInfo:firstyear=2011&license=internal$
- * Copyright (c) 2011, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/newview/groupchatlistener.h b/indra/newview/groupchatlistener.h
index 719e3e877f..0c76db305e 100644
--- a/indra/newview/groupchatlistener.h
+++ b/indra/newview/groupchatlistener.h
@@ -4,8 +4,25 @@
* @date 2011-04-11
* @brief
*
- * $LicenseInfo:firstyear=2011&license=internal$
- * Copyright (c) 2011, Linden Research, Inc.
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/newview/llaccountingquotamanager.cpp b/indra/newview/llaccountingquotamanager.cpp
new file mode 100644
index 0000000000..a4f5de5632
--- /dev/null
+++ b/indra/newview/llaccountingquotamanager.cpp
@@ -0,0 +1,278 @@
+/**
+ * @file LLAccountingQuotaManager.cpp
+ * @ Handles the setting and accessing for costs associated with mesh
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llaccountingquotamanager.h"
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llparcel.h"
+
+//===============================================================================
+LLAccountingQuotaManager::LLAccountingQuotaManager()
+{
+}
+//===============================================================================
+class LLAccountingQuotaResponder : public LLCurl::Responder
+{
+public:
+ LLAccountingQuotaResponder( const LLSD& objectIDs )
+ : mObjectIDs( objectIDs )
+ {
+ }
+
+ void clearPendingRequests ( void )
+ {
+ for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
+ {
+ LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( iter->asUUID() );
+ }
+ }
+
+ void error( U32 statusNum, const std::string& reason )
+ {
+ llwarns << "Transport error "<<reason<<llendl;
+ //prep#do we really want to remove all because of one failure - verify
+ clearPendingRequests();
+ }
+
+ void result( const LLSD& content )
+ {
+ if ( !content.isMap() || content.has("error") )
+ {
+ llwarns << "Error on fetched data"<< llendl;
+ //prep#do we really want to remove all because of one failure - verify
+ clearPendingRequests();
+ return;
+ }
+
+ //Differentiate what the incoming caps could be from the data
+ bool containsParcel = content.has("parcel");
+ bool containsSelection = content.has("selected");
+
+ //Loop over the stored object ids checking against the incoming data
+ for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
+ {
+ LLUUID objectID = iter->asUUID();
+
+ LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( objectID );
+
+ if ( containsParcel )
+ {
+ //Typically should be one
+ S32 dataCount = content["parcel"].size();
+ for(S32 i = 0; i < dataCount; i++)
+ {
+ //prep#todo verify that this is safe, otherwise just add a bool
+ LLUUID parcelId;
+ //S32 parcelOwner = 0;
+ if ( content["parcel"][i].has("parcel_id") )
+ {
+ parcelId = content["parcel"][i]["parcel_id"].asUUID();
+ }
+
+ //if ( content["parcel"][i].has("parcel_owner") )
+ //{
+ // parcelOwner = content["parcel"][i]["parcel_owner"].asInteger();
+ //}
+
+ F32 ownerRenderCost = 0;
+ F32 ownerPhysicsCost = 0;
+ F32 ownerNetworkCost = 0;
+ F32 ownerSimulationCost = 0;
+
+ F32 groupRenderCost = 0;
+ F32 groupPhysicsCost = 0;
+ F32 groupNetworkCost = 0;
+ F32 groupSimulationCost = 0;
+
+ F32 otherRenderCost = 0;
+ F32 otherPhysicsCost = 0;
+ F32 otherNetworkCost = 0;
+ F32 otherSimulationCost = 0;
+
+ F32 tempRenderCost = 0;
+ F32 tempPhysicsCost = 0;
+ F32 tempNetworkCost = 0;
+ F32 tempSimulationCost = 0;
+
+ F32 selectedRenderCost = 0;
+ F32 selectedPhysicsCost = 0;
+ F32 selectedNetworkCost = 0;
+ F32 selectedSimulationCost = 0;
+
+ F32 parcelCapacity = 0;
+
+ if ( content["parcel"][i].has("capacity") )
+ {
+ parcelCapacity = content["parcel"][i].has("capacity");
+ }
+
+ if ( content["parcel"][i].has("owner") )
+ {
+ ownerRenderCost = content["parcel"][i]["owner"]["rendering"].asReal();
+ ownerPhysicsCost = content["parcel"][i]["owner"]["physics"].asReal();
+ ownerNetworkCost = content["parcel"][i]["owner"]["streaming"].asReal();
+ ownerSimulationCost = content["parcel"][i]["owner"]["simulation"].asReal();
+ }
+
+ if ( content["parcel"][i].has("group") )
+ {
+ groupRenderCost = content["parcel"][i]["group"]["rendering"].asReal();
+ groupPhysicsCost = content["parcel"][i]["group"]["physics"].asReal();
+ groupNetworkCost = content["parcel"][i]["group"]["streaming"].asReal();
+ groupSimulationCost = content["parcel"][i]["group"]["simulation"].asReal();
+
+ }
+ if ( content["parcel"][i].has("other") )
+ {
+ otherRenderCost = content["parcel"][i]["other"]["rendering"].asReal();
+ otherPhysicsCost = content["parcel"][i]["other"]["physics"].asReal();
+ otherNetworkCost = content["parcel"][i]["other"]["streaming"].asReal();
+ otherSimulationCost = content["parcel"][i]["other"]["simulation"].asReal();
+ }
+
+ if ( content["parcel"][i].has("temp") )
+ {
+ tempRenderCost = content["parcel"][i]["total"]["rendering"].asReal();
+ tempPhysicsCost = content["parcel"][i]["total"]["physics"].asReal();
+ tempNetworkCost = content["parcel"][i]["total"]["streaming"].asReal();
+ tempSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
+ }
+
+ if ( content["parcel"][i].has("selected") )
+ {
+ selectedRenderCost = content["parcel"][i]["total"]["rendering"].asReal();
+ selectedPhysicsCost = content["parcel"][i]["total"]["physics"].asReal();
+ selectedNetworkCost = content["parcel"][i]["total"]["streaming"].asReal();
+ selectedSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
+ }
+
+ ParcelQuota parcelQuota( ownerRenderCost, ownerPhysicsCost, ownerNetworkCost, ownerSimulationCost,
+ groupRenderCost, groupPhysicsCost, groupNetworkCost, groupSimulationCost,
+ otherRenderCost, otherPhysicsCost, otherNetworkCost, otherSimulationCost,
+ tempRenderCost, tempPhysicsCost, tempNetworkCost, tempSimulationCost,
+ selectedRenderCost, selectedPhysicsCost, selectedNetworkCost, selectedSimulationCost,
+ parcelCapacity );
+ //Update the Parcel
+ LLParcel* pParcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
+ if ( pParcel )
+ {
+ pParcel->updateQuota( objectID, parcelQuota );
+ }
+ }
+ }
+ else
+ if ( containsSelection )
+ {
+ S32 dataCount = content["selected"].size();
+ for(S32 i = 0; i < dataCount; i++)
+ {
+
+ F32 renderCost = 0;
+ F32 physicsCost = 0;
+ F32 networkCost = 0;
+ F32 simulationCost = 0;
+
+ LLUUID objectId;
+
+ objectId = content["selected"][i]["local_id"].asUUID();
+ renderCost = content["selected"][i]["rendering"].asReal();
+ physicsCost = content["selected"][i]["physics"].asReal();
+ networkCost = content["selected"][i]["streaming"].asReal();
+ simulationCost = content["selected"][i]["simulation"].asReal();
+
+ SelectionQuota selectionQuota( objectId, renderCost, physicsCost, networkCost, simulationCost );
+
+ //Update the objects
+ gObjectList.updateQuota( objectId, selectionQuota );
+
+ }
+ }
+ else
+ {
+ //Nothing in string
+ LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( objectID );
+ }
+ }
+ }
+
+private:
+ //List of posted objects
+ LLSD mObjectIDs;
+};
+//===============================================================================
+void LLAccountingQuotaManager::fetchQuotas( const std::string& url )
+{
+ // Invoking system must have already determined capability availability
+ if ( !url.empty() )
+ {
+ LLSD objectList;
+ U32 objectIndex = 0;
+ IDIt IDIter = mUpdateObjectQuota.begin();
+ IDIt IDIterEnd = mUpdateObjectQuota.end();
+
+ for ( ; IDIter != IDIterEnd; ++IDIter )
+ {
+ // Check to see if a request for this object has already been made.
+ if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() )
+ {
+ mPendingObjectQuota.insert( *IDIter );
+ objectList[objectIndex++] = *IDIter;
+ }
+ }
+
+ mUpdateObjectQuota.clear();
+
+ //Post results
+ if ( objectList.size() > 0 )
+ {
+ LLSD dataToPost = LLSD::emptyMap();
+ dataToPost["object_ids"] = objectList;
+ LLHTTPClient::post( url, dataToPost, new LLAccountingQuotaResponder( objectList ));
+ }
+ }
+ else
+ {
+ //url was empty - warn & continue
+ llwarns<<"Supplied url is empty "<<llendl;
+ mUpdateObjectQuota.clear();
+ mPendingObjectQuota.clear();
+ }
+}
+//===============================================================================
+void LLAccountingQuotaManager::updateObjectCost( const LLUUID& objectID )
+{
+ mUpdateObjectQuota.insert( objectID );
+}
+//===============================================================================
+void LLAccountingQuotaManager::removePendingObjectQuota( const LLUUID& objectID )
+{
+ mPendingObjectQuota.erase( objectID );
+}
+//===============================================================================
diff --git a/indra/newview/llaccountingquotamanager.h b/indra/newview/llaccountingquotamanager.h
new file mode 100644
index 0000000000..9251ef9351
--- /dev/null
+++ b/indra/newview/llaccountingquotamanager.h
@@ -0,0 +1,55 @@
+/**
+ * @file lllAccountingQuotaManager.h
+ * @
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_ACCOUNTINGQUOTAMANAGER_H
+#define LL_ACCOUNTINGQUOTAMANAGER_H
+//===============================================================================
+#include "llaccountingquota.h"
+//===============================================================================
+class LLAccountingQuotaManager : public LLSingleton<LLAccountingQuotaManager>
+{
+public:
+ //Ctor
+ LLAccountingQuotaManager();
+ //Store an object that will be eventually fetched
+ void updateObjectCost( const LLUUID& objectID );
+ //Request quotas for object list
+ void fetchQuotas( const std::string& url );
+ //Delete a specific object from the pending list
+ void removePendingObjectQuota( const LLUUID& objectID );
+
+private:
+ //Set of objects that need to update their cost
+ std::set<LLUUID> mUpdateObjectQuota;
+ //During fetchQuota we move object into a the pending set to signify that
+ //a fetch has been instigated.
+ std::set<LLUUID> mPendingObjectQuota;
+ typedef std::set<LLUUID>::iterator IDIt;
+};
+//===============================================================================
+
+#endif // LLACCOUNTINGQUOTAMANAGER
+
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 08d71fc8fc..8954937f69 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -41,6 +41,7 @@
#include "llcapabilitylistener.h"
#include "llchannelmanager.h"
#include "llconsole.h"
+#include "llenvmanager.h"
#include "llfirstuse.h"
#include "llfloatercamera.h"
#include "llfloaterreg.h"
@@ -84,6 +85,7 @@
#include "llwindow.h"
#include "llworld.h"
#include "llworldmap.h"
+#include "stringize.h"
using namespace LLVOAvatarDefines;
@@ -206,6 +208,7 @@ LLAgent::LLAgent() :
mAutoPilot(FALSE),
mAutoPilotFlyOnStop(FALSE),
+ mAutoPilotAllowFlying(TRUE),
mAutoPilotTargetGlobal(),
mAutoPilotStopDistance(1.f),
mAutoPilotUseRotation(FALSE),
@@ -607,6 +610,8 @@ void LLAgent::standUp()
//-----------------------------------------------------------------------------
void LLAgent::setRegion(LLViewerRegion *regionp)
{
+ bool teleport = true;
+
llassert(regionp);
if (mRegionp != regionp)
{
@@ -644,6 +649,8 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
gSky.mVOGroundp->setRegion(regionp);
}
+ // Notify windlight managers
+ teleport = (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE);
}
else
{
@@ -684,6 +691,15 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
LLSelectMgr::getInstance()->updateSelectionCenter();
LLFloaterMove::sUpdateFlyingStatus();
+
+ if (teleport)
+ {
+ LLEnvManagerNew::instance().onTeleport();
+ }
+ else
+ {
+ LLEnvManagerNew::instance().onRegionCrossing();
+ }
}
@@ -1230,17 +1246,26 @@ void LLAgent::startAutoPilotGlobal(
const LLQuaternion *target_rotation,
void (*finish_callback)(BOOL, void *),
void *callback_data,
- F32 stop_distance, F32 rot_threshold)
+ F32 stop_distance,
+ F32 rot_threshold,
+ BOOL allow_flying)
{
if (!isAgentAvatarValid())
{
return;
}
+ // Are there any pending callbacks from previous auto pilot requests?
+ if (mAutoPilotFinishedCallback)
+ {
+ mAutoPilotFinishedCallback(dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
+ }
+
mAutoPilotFinishedCallback = finish_callback;
mAutoPilotCallbackData = callback_data;
mAutoPilotRotationThreshold = rot_threshold;
mAutoPilotBehaviorName = behavior_name;
+ mAutoPilotAllowFlying = allow_flying;
LLVector3d delta_pos( target_global );
delta_pos -= getPositionGlobal();
@@ -1268,14 +1293,23 @@ void LLAgent::startAutoPilotGlobal(
}
}
- mAutoPilotFlyOnStop = getFlying();
+ if (mAutoPilotAllowFlying)
+ {
+ mAutoPilotFlyOnStop = getFlying();
+ }
+ else
+ {
+ mAutoPilotFlyOnStop = FALSE;
+ }
- if (distance > 30.0)
+ if (distance > 30.0 && mAutoPilotAllowFlying)
{
setFlying(TRUE);
}
- if ( distance > 1.f && heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f))
+ if ( distance > 1.f &&
+ mAutoPilotAllowFlying &&
+ heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f))
{
setFlying(TRUE);
// Do not force flying for "Sit" behavior to prevent flying after pressing "Stand"
@@ -1285,22 +1319,8 @@ void LLAgent::startAutoPilotGlobal(
}
mAutoPilot = TRUE;
- mAutoPilotTargetGlobal = target_global;
-
- // trace ray down to find height of destination from ground
- LLVector3d traceEndPt = target_global;
- traceEndPt.mdV[VZ] -= 20.f;
+ setAutoPilotTargetGlobal(target_global);
- LLVector3d targetOnGround;
- LLVector3 groundNorm;
- LLViewerObject *obj;
-
- LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj);
- F64 target_height = llmax((F64)gAgentAvatarp->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]);
-
- // clamp z value of target to minimum height above ground
- mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height;
- mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal);
if (target_rotation)
{
mAutoPilotUseRotation = TRUE;
@@ -1318,12 +1338,36 @@ void LLAgent::startAutoPilotGlobal(
//-----------------------------------------------------------------------------
-// startFollowPilot()
+// setAutoPilotTargetGlobal
//-----------------------------------------------------------------------------
-void LLAgent::startFollowPilot(const LLUUID &leader_id)
+void LLAgent::setAutoPilotTargetGlobal(const LLVector3d &target_global)
{
- if (!mAutoPilot) return;
+ if (mAutoPilot)
+ {
+ mAutoPilotTargetGlobal = target_global;
+
+ // trace ray down to find height of destination from ground
+ LLVector3d traceEndPt = target_global;
+ traceEndPt.mdV[VZ] -= 20.f;
+
+ LLVector3d targetOnGround;
+ LLVector3 groundNorm;
+ LLViewerObject *obj;
+
+ LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj);
+ F64 target_height = llmax((F64)gAgentAvatarp->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]);
+ // clamp z value of target to minimum height above ground
+ mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height;
+ mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// startFollowPilot()
+//-----------------------------------------------------------------------------
+void LLAgent::startFollowPilot(const LLUUID &leader_id, BOOL allow_flying, F32 stop_distance)
+{
mLeaderID = leader_id;
if ( mLeaderID.isNull() ) return;
@@ -1334,7 +1378,14 @@ void LLAgent::startFollowPilot(const LLUUID &leader_id)
return;
}
- startAutoPilotGlobal(object->getPositionGlobal());
+ startAutoPilotGlobal(object->getPositionGlobal(),
+ std::string(), // behavior_name
+ NULL, // target_rotation
+ NULL, // finish_callback
+ NULL, // callback_data
+ stop_distance,
+ 0.03f, // rotation_threshold
+ allow_flying);
}
@@ -1360,7 +1411,8 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
//NB: auto pilot can terminate for a reason other than reaching the destination
if (mAutoPilotFinishedCallback)
{
- mAutoPilotFinishedCallback(!user_cancel && dist_vec_squared(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < (mAutoPilotStopDistance * mAutoPilotStopDistance), mAutoPilotCallbackData);
+ mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
+ mAutoPilotFinishedCallback = NULL;
}
mLeaderID = LLUUID::null;
@@ -1400,7 +1452,7 @@ void LLAgent::autoPilot(F32 *delta_yaw)
if (!isAgentAvatarValid()) return;
- if (gAgentAvatarp->mInAir)
+ if (gAgentAvatarp->mInAir && mAutoPilotAllowFlying)
{
setFlying(TRUE);
}
@@ -3298,6 +3350,9 @@ bool LLAgent::teleportCore(bool is_local)
// hide land floater too - it'll be out of date
LLFloaterReg::hideInstance("about_land");
+ // hide the Region/Estate floater
+ LLFloaterReg::hideInstance("region_info");
+
// hide the search floater (EXT-8276)
LLFloaterReg::hideInstance("search");
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 54c5649f97..67ed1923c0 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -469,19 +469,29 @@ public:
public:
BOOL getAutoPilot() const { return mAutoPilot; }
LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; }
+ LLUUID getAutoPilotLeaderID() const { return mLeaderID; }
+ F32 getAutoPilotStopDistance() const { return mAutoPilotStopDistance; }
+ F32 getAutoPilotTargetDist() const { return mAutoPilotTargetDist; }
+ BOOL getAutoPilotUseRotation() const { return mAutoPilotUseRotation; }
+ LLVector3 getAutoPilotTargetFacing() const { return mAutoPilotTargetFacing; }
+ F32 getAutoPilotRotationThreshold() const { return mAutoPilotRotationThreshold; }
+ std::string getAutoPilotBehaviorName() const { return mAutoPilotBehaviorName; }
+
void startAutoPilotGlobal(const LLVector3d &pos_global,
const std::string& behavior_name = std::string(),
const LLQuaternion *target_rotation = NULL,
void (*finish_callback)(BOOL, void *) = NULL, void *callback_data = NULL,
- F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f);
- void startFollowPilot(const LLUUID &leader_id);
+ F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f,
+ BOOL allow_flying = TRUE);
+ void startFollowPilot(const LLUUID &leader_id, BOOL allow_flying = TRUE, F32 stop_distance = 0.5f);
void stopAutoPilot(BOOL user_cancel = FALSE);
- void setAutoPilotGlobal(const LLVector3d &pos_global);
+ void setAutoPilotTargetGlobal(const LLVector3d &target_global);
void autoPilot(F32 *delta_yaw); // Autopilot walking action, angles in radians
void renderAutoPilotTarget();
private:
BOOL mAutoPilot;
BOOL mAutoPilotFlyOnStop;
+ BOOL mAutoPilotAllowFlying;
LLVector3d mAutoPilotTargetGlobal;
F32 mAutoPilotStopDistance;
BOOL mAutoPilotUseRotation;
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index c6b5a0113f..c30d3b9aa3 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -392,7 +392,7 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi
}
LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
- LLVector3 object_extents;
+ LLVector3 object_extents = object->getScale();
const LLVector4a* oe4 = object->mDrawable->getSpatialExtents();
object_extents.set( oe4[1][0], oe4[1][1], oe4[1][2] );
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
index 9cea33c7c6..a8d2222c03 100644
--- a/indra/newview/llagentlistener.cpp
+++ b/indra/newview/llagentlistener.cpp
@@ -31,6 +31,7 @@
#include "llagentlistener.h"
#include "llagent.h"
+#include "llvoavatar.h"
#include "llcommandhandler.h"
#include "llslurl.h"
#include "llurldispatcher.h"
@@ -39,93 +40,242 @@
#include "llviewerregion.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
+#include "lltoolgrab.h"
+#include "llhudeffectlookat.h"
+#include "llagentcamera.h"
LLAgentListener::LLAgentListener(LLAgent &agent)
: LLEventAPI("LLAgent",
"LLAgent listener to (e.g.) teleport, sit, stand, etc."),
mAgent(agent)
{
- add("requestTeleport",
+ add("requestTeleport",
"Teleport: [\"regionname\"], [\"x\"], [\"y\"], [\"z\"]\n"
"If [\"skip_confirmation\"] is true, use LLURLDispatcher rather than LLCommandDispatcher.",
&LLAgentListener::requestTeleport);
- add("requestSit",
- "Ask to sit on the object specified in [\"obj_uuid\"]",
+ add("requestSit",
+ "[\"obj_uuid\"]: id of object to sit on, use this or [\"position\"] to indicate the sit target"
+ "[\"position\"]: region position {x, y, z} where to find closest object to sit on",
&LLAgentListener::requestSit);
- add("requestStand",
+ add("requestStand",
"Ask to stand up",
&LLAgentListener::requestStand);
+ add("requestTouch",
+ "[\"obj_uuid\"]: id of object to touch, use this or [\"position\"] to indicate the object to touch"
+ "[\"position\"]: region position {x, y, z} where to find closest object to touch"
+ "[\"face\"]: optional object face number to touch[Default: 0]",
+ &LLAgentListener::requestTouch);
add("resetAxes",
"Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])",
&LLAgentListener::resetAxes);
add("getAxes",
+ "Obsolete - use getPosition instead\n"
"Send information about the agent's orientation on [\"reply\"]:\n"
"[\"euler\"]: map of {roll, pitch, yaw}\n"
"[\"quat\"]: array of [x, y, z, w] quaternion values",
&LLAgentListener::getAxes,
LLSDMap("reply", LLSD()));
- add("getGroups",
- "Send on [\"reply\"], in [\"groups\"], an array describing agent's groups:\n"
- "[\"id\"]: UUID of group\n"
- "[\"name\"]: name of group",
- &LLAgentListener::getGroups,
+ add("getPosition",
+ "Send information about the agent's position and orientation on [\"reply\"]:\n"
+ "[\"region\"]: array of region {x, y, z} position\n"
+ "[\"global\"]: array of global {x, y, z} position\n"
+ "[\"euler\"]: map of {roll, pitch, yaw}\n"
+ "[\"quat\"]: array of [x, y, z, w] quaternion values",
+ &LLAgentListener::getPosition,
LLSDMap("reply", LLSD()));
+ add("startAutoPilot",
+ "Start the autopilot system using the following parameters:\n"
+ "[\"target_global\"]: array of target global {x, y, z} position\n"
+ "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]\n"
+ "[\"target_rotation\"]: array of [x, y, z, w] quaternion values [default: no target]\n"
+ "[\"rotation_threshold\"]: target maximum angle from target facing rotation [default: 0.03 radians]\n"
+ "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]"
+ "[\"allow_flying\"]: allow flying during autopilot [default: True]",
+ //"[\"callback_pump\"]: pump to send success/failure and callback data to [default: none]\n"
+ //"[\"callback_data\"]: data to send back during a callback [default: none]",
+ &LLAgentListener::startAutoPilot);
+ add("getAutoPilot",
+ "Send information about current state of the autopilot system to [\"reply\"]:\n"
+ "[\"enabled\"]: boolean indicating whether or not autopilot is enabled\n"
+ "[\"target_global\"]: array of target global {x, y, z} position\n"
+ "[\"leader_id\"]: uuid of target autopilot is following\n"
+ "[\"stop_distance\"]: target maximum distance from target\n"
+ "[\"target_distance\"]: last known distance from target\n"
+ "[\"use_rotation\"]: boolean indicating if autopilot has a target facing rotation\n"
+ "[\"target_facing\"]: array of {x, y} target direction to face\n"
+ "[\"rotation_threshold\"]: target maximum angle from target facing rotation\n"
+ "[\"behavior_name\"]: name of the autopilot behavior",
+ &LLAgentListener::getAutoPilot,
+ LLSDMap("reply", LLSD()));
+ add("startFollowPilot",
+ "[\"leader_id\"]: uuid of target to follow using the autopilot system (optional with avatar_name)\n"
+ "[\"avatar_name\"]: avatar name to follow using the autopilot system (optional with leader_id)\n"
+ "[\"allow_flying\"]: allow flying during autopilot [default: True]\n"
+ "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]",
+ &LLAgentListener::startFollowPilot);
+ add("setAutoPilotTarget",
+ "Update target for currently running autopilot:\n"
+ "[\"target_global\"]: array of target global {x, y, z} position",
+ &LLAgentListener::setAutoPilotTarget);
+ add("stopAutoPilot",
+ "Stop the autopilot system:\n"
+ "[\"user_cancel\"] indicates whether or not to act as though user canceled autopilot [default: false]",
+ &LLAgentListener::stopAutoPilot);
+ add("lookAt",
+ "[\"type\"]: number to indicate the lookAt type, 0 to clear\n"
+ "[\"obj_uuid\"]: id of object to look at, use this or [\"position\"] to indicate the target\n"
+ "[\"position\"]: region position {x, y, z} where to find closest object or avatar to look at",
+ &LLAgentListener::lookAt);
}
void LLAgentListener::requestTeleport(LLSD const & event_data) const
{
- if(event_data["skip_confirmation"].asBoolean())
+ if(event_data["skip_confirmation"].asBoolean())
+ {
+ LLSD params(LLSD::emptyArray());
+ params.append(event_data["regionname"]);
+ params.append(event_data["x"]);
+ params.append(event_data["y"]);
+ params.append(event_data["z"]);
+ LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, "clicked", true);
+ // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
+ // should we just compose LLCommandHandler and LLDispatchListener?
+ }
+ else
+ {
+ std::string url = LLSLURL(event_data["regionname"],
+ LLVector3(event_data["x"].asReal(),
+ event_data["y"].asReal(),
+ event_data["z"].asReal())).getSLURLString();
+ LLURLDispatcher::dispatch(url, "clicked", NULL, false);
+ }
+}
+
+void LLAgentListener::requestSit(LLSD const & event_data) const
+{
+ //mAgent.getAvatarObject()->sitOnObject();
+ // shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
+ // *TODO - find a permanent place to share this code properly.
+
+ LLViewerObject *object = NULL;
+ if (event_data.has("obj_uuid"))
+ {
+ object = gObjectList.findObject(event_data["obj_uuid"]);
+ }
+ else if (event_data.has("position"))
{
- LLSD params(LLSD::emptyArray());
- params.append(event_data["regionname"]);
- params.append(event_data["x"]);
- params.append(event_data["y"]);
- params.append(event_data["z"]);
- LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, "clicked", true);
- // *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
- // should we just compose LLCommandHandler and LLDispatchListener?
+ LLVector3 target_position = ll_vector3_from_sd(event_data["position"]);
+ object = findObjectClosestTo(target_position);
}
+
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, mAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, mAgent.getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
+ gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
+ gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3(0,0,0));
+
+ object->getRegion()->sendReliableMessage();
+ }
else
{
- std::string url = LLSLURL(event_data["regionname"],
- LLVector3(event_data["x"].asReal(),
- event_data["y"].asReal(),
- event_data["z"].asReal())).getSLURLString();
- LLURLDispatcher::dispatch(url, "clicked", NULL, false);
+ llwarns << "LLAgent requestSit could not find the sit target: "
+ << event_data << llendl;
}
}
-void LLAgentListener::requestSit(LLSD const & event_data) const
+void LLAgentListener::requestStand(LLSD const & event_data) const
+{
+ mAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+}
+
+
+LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & position ) const
{
- //mAgent.getAvatarObject()->sitOnObject();
- // shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
- // *TODO - find a permanent place to share this code properly.
- LLViewerObject *object = gObjectList.findObject(event_data["obj_uuid"]);
+ LLViewerObject *object = NULL;
- if (object && object->getPCode() == LL_PCODE_VOLUME)
+ // Find the object closest to that position
+ F32 min_distance = 10000.0f; // Start big
+ S32 num_objects = gObjectList.getNumObjects();
+ S32 cur_index = 0;
+ while (cur_index < num_objects)
{
- gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, mAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, mAgent.getSessionID());
- gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
- gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
- gMessageSystem->addVector3Fast(_PREHASH_Offset, LLVector3(0,0,0));
-
- object->getRegion()->sendReliableMessage();
+ LLViewerObject * cur_object = gObjectList.getObject(cur_index++);
+ if (cur_object)
+ { // Calculate distance from the target position
+ LLVector3 target_diff = cur_object->getPositionRegion() - position;
+ F32 distance_to_target = target_diff.length();
+ if (distance_to_target < min_distance)
+ { // Found an object closer
+ min_distance = distance_to_target;
+ object = cur_object;
+ }
+ }
}
+
+ return object;
}
-void LLAgentListener::requestStand(LLSD const & event_data) const
+
+void LLAgentListener::requestTouch(LLSD const & event_data) const
{
- mAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
+ LLViewerObject *object = NULL;
+
+ if (event_data.has("obj_uuid"))
+ {
+ object = gObjectList.findObject(event_data["obj_uuid"]);
+ }
+ else if (event_data.has("position"))
+ {
+ LLVector3 target_position = ll_vector3_from_sd(event_data["position"]);
+ object = findObjectClosestTo(target_position);
+ }
+
+ S32 face = 0;
+ if (event_data.has("face"))
+ {
+ face = event_data["face"].asInteger();
+ }
+
+ if (object && object->getPCode() == LL_PCODE_VOLUME)
+ {
+ // Fake enough pick info to get it to (hopefully) work
+ LLPickInfo pick;
+ pick.mObjectFace = face;
+
+ /*
+ These values are sent to the simulator, but face seems to be easiest to use
+
+ pick.mUVCoords "UVCoord"
+ pick.mSTCoords "STCoord"
+ pick.mObjectFace "FaceIndex"
+ pick.mIntersection "Position"
+ pick.mNormal "Normal"
+ pick.mBinormal "Binormal"
+ */
+
+ // A touch is a sketchy message sequence ... send a grab, immediately
+ // followed by un-grabbing, crossing fingers and hoping packets arrive in
+ // the correct order
+ send_ObjectGrab_message(object, pick, LLVector3::zero);
+ send_ObjectDeGrab_message(object, pick);
+ }
+ else
+ {
+ llwarns << "LLAgent requestTouch could not find the touch target "
+ << event_data["obj_uuid"].asUUID() << llendl;
+ }
}
-void LLAgentListener::resetAxes(const LLSD& event) const
+
+void LLAgentListener::resetAxes(const LLSD& event_data) const
{
- if (event.has("lookat"))
+ if (event_data.has("lookat"))
{
- mAgent.resetAxes(ll_vector3_from_sd(event["lookat"]));
+ mAgent.resetAxes(ll_vector3_from_sd(event_data["lookat"]));
}
else
{
@@ -134,17 +284,210 @@ void LLAgentListener::resetAxes(const LLSD& event) const
}
}
-void LLAgentListener::getAxes(const LLSD& event) const
+void LLAgentListener::getAxes(const LLSD& event_data) const
{
LLQuaternion quat(mAgent.getQuat());
F32 roll, pitch, yaw;
quat.getEulerAngles(&roll, &pitch, &yaw);
// The official query API for LLQuaternion's [x, y, z, w] values is its
// public member mQ...
- sendReply(LLSDMap
- ("quat", llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ)))
- ("euler", LLSDMap("roll", roll)("pitch", pitch)("yaw", yaw)),
- event);
+ LLSD reply = LLSD::emptyMap();
+ reply["quat"] = llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ));
+ reply["euler"] = LLSD::emptyMap();
+ reply["euler"]["roll"] = roll;
+ reply["euler"]["pitch"] = pitch;
+ reply["euler"]["yaw"] = yaw;
+ sendReply(reply, event_data);
+}
+
+void LLAgentListener::getPosition(const LLSD& event_data) const
+{
+ F32 roll, pitch, yaw;
+ LLQuaternion quat(mAgent.getQuat());
+ quat.getEulerAngles(&roll, &pitch, &yaw);
+
+ LLSD reply = LLSD::emptyMap();
+ reply["quat"] = llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ));
+ reply["euler"] = LLSD::emptyMap();
+ reply["euler"]["roll"] = roll;
+ reply["euler"]["pitch"] = pitch;
+ reply["euler"]["yaw"] = yaw;
+ reply["region"] = ll_sd_from_vector3(mAgent.getPositionAgent());
+ reply["global"] = ll_sd_from_vector3d(mAgent.getPositionGlobal());
+
+ sendReply(reply, event_data);
+}
+
+
+void LLAgentListener::startAutoPilot(LLSD const & event_data)
+{
+ LLQuaternion target_rotation_value;
+ LLQuaternion* target_rotation = NULL;
+ if (event_data.has("target_rotation"))
+ {
+ target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]);
+ target_rotation = &target_rotation_value;
+ }
+ // *TODO: Use callback_pump and callback_data
+ F32 rotation_threshold = 0.03f;
+ if (event_data.has("rotation_threshold"))
+ {
+ rotation_threshold = event_data["rotation_threshold"].asReal();
+ }
+
+ BOOL allow_flying = TRUE;
+ if (event_data.has("allow_flying"))
+ {
+ allow_flying = (BOOL) event_data["allow_flying"].asBoolean();
+ mAgent.setFlying(allow_flying);
+ }
+
+ F32 stop_distance = 0.f;
+ if (event_data.has("stop_distance"))
+ {
+ stop_distance = event_data["stop_distance"].asReal();
+ }
+
+ // Clear follow target, this is doing a path
+ mFollowTarget.setNull();
+
+ mAgent.startAutoPilotGlobal(ll_vector3d_from_sd(event_data["target_global"]),
+ event_data["behavior_name"],
+ target_rotation,
+ NULL, NULL,
+ stop_distance,
+ rotation_threshold,
+ allow_flying);
+}
+
+void LLAgentListener::getAutoPilot(const LLSD& event_data) const
+{
+ LLSD reply = LLSD::emptyMap();
+
+ LLSD::Boolean enabled = mAgent.getAutoPilot();
+ reply["enabled"] = enabled;
+
+ reply["target_global"] = ll_sd_from_vector3d(mAgent.getAutoPilotTargetGlobal());
+
+ reply["leader_id"] = mAgent.getAutoPilotLeaderID();
+
+ reply["stop_distance"] = mAgent.getAutoPilotStopDistance();
+
+ reply["target_distance"] = mAgent.getAutoPilotTargetDist();
+ if (!enabled &&
+ mFollowTarget.notNull())
+ { // Get an actual distance from the target object we were following
+ LLViewerObject * target = gObjectList.findObject(mFollowTarget);
+ if (target)
+ { // Found the target AV, return the actual distance to them as well as their ID
+ LLVector3 difference = target->getPositionRegion() - mAgent.getPositionAgent();
+ reply["target_distance"] = difference.length();
+ reply["leader_id"] = mFollowTarget;
+ }
+ }
+
+ reply["use_rotation"] = (LLSD::Boolean) mAgent.getAutoPilotUseRotation();
+ reply["target_facing"] = ll_sd_from_vector3(mAgent.getAutoPilotTargetFacing());
+ reply["rotation_threshold"] = mAgent.getAutoPilotRotationThreshold();
+ reply["behavior_name"] = mAgent.getAutoPilotBehaviorName();
+ reply["fly"] = (LLSD::Boolean) mAgent.getFlying();
+
+ sendReply(reply, event_data);
+}
+
+void LLAgentListener::startFollowPilot(LLSD const & event_data)
+{
+ LLUUID target_id;
+
+ BOOL allow_flying = TRUE;
+ if (event_data.has("allow_flying"))
+ {
+ allow_flying = (BOOL) event_data["allow_flying"].asBoolean();
+ }
+
+ if (event_data.has("leader_id"))
+ {
+ target_id = event_data["leader_id"];
+ }
+ else if (event_data.has("avatar_name"))
+ { // Find the avatar with matching name
+ std::string target_name = event_data["avatar_name"].asString();
+
+ if (target_name.length() > 0)
+ {
+ S32 num_objects = gObjectList.getNumObjects();
+ S32 cur_index = 0;
+ while (cur_index < num_objects)
+ {
+ LLViewerObject * cur_object = gObjectList.getObject(cur_index++);
+ if (cur_object &&
+ cur_object->asAvatar() &&
+ cur_object->asAvatar()->getFullname() == target_name)
+ { // Found avatar with matching name, extract id and break out of loop
+ target_id = cur_object->getID();
+ break;
+ }
+ }
+ }
+ }
+
+ F32 stop_distance = 0.f;
+ if (event_data.has("stop_distance"))
+ {
+ stop_distance = event_data["stop_distance"].asReal();
+ }
+
+ if (target_id.notNull())
+ {
+ mAgent.setFlying(allow_flying);
+ mFollowTarget = target_id; // Save follow target so we can report distance later
+
+ mAgent.startFollowPilot(target_id, allow_flying, stop_distance);
+ }
+}
+
+void LLAgentListener::setAutoPilotTarget(LLSD const & event_data) const
+{
+ if (event_data.has("target_global"))
+ {
+ LLVector3d target_global(ll_vector3d_from_sd(event_data["target_global"]));
+ mAgent.setAutoPilotTargetGlobal(target_global);
+ }
+}
+
+void LLAgentListener::stopAutoPilot(LLSD const & event_data) const
+{
+ BOOL user_cancel = FALSE;
+ if (event_data.has("user_cancel"))
+ {
+ user_cancel = event_data["user_cancel"].asBoolean();
+ }
+ mAgent.stopAutoPilot(user_cancel);
+}
+
+void LLAgentListener::lookAt(LLSD const & event_data) const
+{
+ LLViewerObject *object = NULL;
+ if (event_data.has("obj_uuid"))
+ {
+ object = gObjectList.findObject(event_data["obj_uuid"]);
+ }
+ else if (event_data.has("position"))
+ {
+ LLVector3 target_position = ll_vector3_from_sd(event_data["position"]);
+ object = findObjectClosestTo(target_position);
+ }
+
+ S32 look_at_type = (S32) LOOKAT_TARGET_NONE;
+ if (event_data.has("type"))
+ {
+ look_at_type = event_data["type"].asInteger();
+ }
+ if (look_at_type >= (S32) LOOKAT_TARGET_NONE &&
+ look_at_type < (S32) LOOKAT_NUM_TARGETS)
+ {
+ gAgentCamera.setLookAt((ELookAtType) look_at_type, object);
+ }
}
void LLAgentListener::getGroups(const LLSD& event) const
diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h
index 5a89a99f6a..9a9c4073fe 100644
--- a/indra/newview/llagentlistener.h
+++ b/indra/newview/llagentlistener.h
@@ -34,22 +34,35 @@
class LLAgent;
class LLSD;
+class LLViewerObject;
+class LLVector3d;
class LLAgentListener : public LLEventAPI
{
public:
- LLAgentListener(LLAgent &agent);
+ LLAgentListener(LLAgent &agent);
private:
- void requestTeleport(LLSD const & event_data) const;
- void requestSit(LLSD const & event_data) const;
- void requestStand(LLSD const & event_data) const;
- void resetAxes(const LLSD& event) const;
- void getAxes(const LLSD& event) const;
+ void requestTeleport(LLSD const & event_data) const;
+ void requestSit(LLSD const & event_data) const;
+ void requestStand(LLSD const & event_data) const;
+ void requestTouch(LLSD const & event_data) const;
+ void resetAxes(const LLSD& event_data) const;
+ void getAxes(const LLSD& event_data) const;
void getGroups(const LLSD& event) const;
+ void getPosition(const LLSD& event_data) const;
+ void startAutoPilot(const LLSD& event_data);
+ void getAutoPilot(const LLSD& event_data) const;
+ void startFollowPilot(const LLSD& event_data);
+ void setAutoPilotTarget(const LLSD& event_data) const;
+ void stopAutoPilot(const LLSD& event_data) const;
+ void lookAt(LLSD const & event_data) const;
+
+ LLViewerObject * findObjectClosestTo( const LLVector3 & position ) const;
private:
- LLAgent & mAgent;
+ LLAgent & mAgent;
+ LLUUID mFollowTarget;
};
#endif // LL_LLAGENTLISTENER_H
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index d426afb17c..36272f0c7c 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -33,7 +33,6 @@
#include "llagentwearablesfetch.h"
#include "llappearancemgr.h"
#include "llcallbacklist.h"
-#include "llfolderview.h"
#include "llgesturemgr.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
@@ -45,6 +44,7 @@
#include "llsidepanelappearance.h"
#include "llsidetray.h"
#include "lltexlayer.h"
+#include "lltooldraganddrop.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
#include "llwearable.h"
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 75b6c18c57..80ac385e3b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1,4 +1,4 @@
- /**
+/**
* @file llappviewer.cpp
* @brief The LLAppViewer class definitions
*
@@ -56,6 +56,7 @@
#include "llallocator.h"
#include "llares.h"
#include "llcurl.h"
+#include "llcalc.h"
#include "lltexturestats.h"
#include "lltexturestats.h"
#include "llviewerwindow.h"
@@ -695,6 +696,8 @@ bool LLAppViewer::init()
if (!initConfiguration())
return false;
+ LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
+
// write Google Breakpad minidump files to our log directory
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
logdir += gDirUtilp->getDirDelimiter();
@@ -721,6 +724,8 @@ bool LLAppViewer::init()
// *NOTE:Mani - LLCurl::initClass is not thread safe.
// Called before threads are created.
LLCurl::initClass();
+ LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;
+
LLMachineID::init();
{
@@ -739,6 +744,8 @@ bool LLAppViewer::init()
}
initThreads();
+ LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;
+
writeSystemInfo();
// Initialize updater service (now that we have an io pump)
@@ -773,6 +780,7 @@ bool LLAppViewer::init()
gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND);
gCrashSettings.saveToFile(crash_settings_filename, FALSE);
}
+ LL_INFOS("InitInfo") << "Crash settings done." << LL_ENDL ;
/////////////////////////////////////////////////
// OS-specific login dialogs
@@ -821,6 +829,8 @@ bool LLAppViewer::init()
// Let code in llui access the viewer help floater
LLUI::sHelpImpl = LLViewerHelp::getInstance();
+ LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ;
+
// Load translations for tooltips
LLFloater::initClass();
@@ -870,6 +880,7 @@ bool LLAppViewer::init()
// Early out from user choice.
return false;
}
+ LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ;
// Prepare for out-of-memory situations, during which we will crash on
// purpose and save a dump.
@@ -890,7 +901,8 @@ bool LLAppViewer::init()
OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
return 1;
}
-
+ LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
+
// Initialize the repeater service.
LLMainLoopRepeater::instance().start();
@@ -899,6 +911,7 @@ bool LLAppViewer::init()
//
gGLActive = TRUE;
initWindow();
+ LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
// initWindow also initializes the Feature List, so now we can initialize this global.
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
@@ -1036,6 +1049,8 @@ bool LLAppViewer::init()
}
LLViewerMedia::initClass();
+ LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ;
+
LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
//EXT-7013 - On windows for some locale (Japanese) standard
@@ -1179,11 +1194,11 @@ bool LLAppViewer::mainLoop()
// Scan keyboard for movement keys. Command keys and typing
// are handled by windows callbacks. Don't do this until we're
// done initializing. JC
- if (gViewerWindow->mWindow->getVisible()
+ if ((gHeadlessClient || gViewerWindow->mWindow->getVisible())
&& gViewerWindow->getActive()
&& !gViewerWindow->mWindow->getMinimized()
&& LLStartUp::getStartupState() == STATE_STARTED
- && !gViewerWindow->getShowProgress()
+ && (gHeadlessClient || !gViewerWindow->getShowProgress())
&& !gFocusMgr.focusLocked())
{
LLMemType mjk(LLMemType::MTYPE_JOY_KEY);
@@ -1529,7 +1544,9 @@ bool LLAppViewer::cleanup()
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
LLWorldMap::getInstance()->reset(); // release any images
-
+
+ LLCalc::cleanUp();
+
llinfos << "Global stuff deleted" << llendflush;
if (gAudiop)
@@ -1626,9 +1643,7 @@ bool LLAppViewer::cleanup()
llinfos << "Cleaning up Objects" << llendflush;
LLViewerObject::cleanupVOClasses();
-
- LLWaterParamManager::cleanupClass();
- LLWLParamManager::cleanupClass();
+
LLPostProcess::cleanupClass();
LLTracker::cleanupInstance();
@@ -2502,7 +2517,8 @@ bool LLAppViewer::initConfiguration()
// it relies on checking a marker file which will not work when running
// out of different directories
- if (LLStartUp::getStartSLURL().isValid())
+ if (LLStartUp::getStartSLURL().isValid() &&
+ (gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
{
if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
{
@@ -2812,6 +2828,8 @@ bool LLAppViewer::initWindow()
gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
gSavedSettings.getBOOL("WindowFullScreen"), ignorePixelDepth);
+ LL_INFOS("AppInit") << "gViewerwindow created." << LL_ENDL;
+
// Need to load feature table before cheking to start watchdog.
const S32 NEVER_SUBMIT_REPORT = 2;
bool use_watchdog = false;
@@ -2831,6 +2849,7 @@ bool LLAppViewer::initWindow()
{
LLWatchdog::getInstance()->init(watchdog_killer_callback);
}
+ LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL;
LLNotificationsUI::LLNotificationManager::getInstance();
@@ -2853,7 +2872,8 @@ bool LLAppViewer::initWindow()
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
gPipeline.init();
-
+ LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL;
+
stop_glerror();
gViewerWindow->initGLDefaults();
@@ -2892,7 +2912,7 @@ bool LLAppViewer::initWindow()
// show viewer window
//gViewerWindow->mWindow->show();
-
+ LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL;
return true;
}
@@ -3478,7 +3498,7 @@ void LLAppViewer::migrateCacheDirectory()
// Migrate inventory cache to avoid pain to inventory database after mass update
S32 file_count = 0;
std::string file_name;
- std::string mask = delimiter + "*.*";
+ std::string mask = "*.*";
LLDirIterator iter(old_cache_dir, mask);
while (iter.next(file_name))
@@ -3634,11 +3654,25 @@ bool LLAppViewer::initCache()
// Init the texture cache
// Allocate 80% of the cache size for textures
- const S32 MB = 1024*1024;
+ const S32 MB = 1024 * 1024;
+ const S64 MIN_CACHE_SIZE = 64 * MB;
+ const S64 MAX_CACHE_SIZE = 9984ll * MB;
+ const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
+
S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
- const S64 MAX_CACHE_SIZE = 1024*MB;
- cache_size = llmin(cache_size, MAX_CACHE_SIZE);
- S64 texture_cache_size = ((cache_size * 8)/10);
+ cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
+
+ S64 texture_cache_size = ((cache_size * 8) / 10);
+ S64 vfs_size = cache_size - texture_cache_size;
+
+ if (vfs_size > MAX_VFS_SIZE)
+ {
+ // Give the texture cache more space, since the VFS can't be bigger than 1GB.
+ // This happens when the user's CacheSize setting is greater than 5GB.
+ vfs_size = MAX_VFS_SIZE;
+ texture_cache_size = cache_size - MAX_VFS_SIZE;
+ }
+
S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
texture_cache_size -= extra;
@@ -3647,21 +3681,19 @@ bool LLAppViewer::initCache()
LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS"));
// Init the VFS
- S64 vfs_size = cache_size - texture_cache_size;
- const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
- vfs_size = llmin(vfs_size, MAX_VFS_SIZE);
+ vfs_size = llmin(vfs_size + extra, MAX_VFS_SIZE);
vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned
U32 vfs_size_u32 = (U32)vfs_size;
U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
bool resize_vfs = (vfs_size_u32 != old_vfs_size);
if (resize_vfs)
{
- gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB);
+ gSavedSettings.setU32("VFSOldSize", vfs_size_u32 / MB);
}
- LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << LL_ENDL;
+ LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size / (1024*1024) << " MB" << LL_ENDL;
// This has to happen BEFORE starting the vfs
- //time_t ltime;
+ // time_t ltime;
srand(time(NULL)); // Flawfinder: ignore
U32 old_salt = gSavedSettings.getU32("VFSSalt");
U32 new_salt;
@@ -3682,10 +3714,10 @@ bool LLAppViewer::initCache()
do
{
new_salt = rand();
- } while( new_salt == old_salt );
+ } while(new_salt == old_salt);
}
- old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",old_salt);
+ old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u", old_salt);
// make sure this file exists
llstat s;
@@ -3694,12 +3726,11 @@ bool LLAppViewer::initCache()
{
// doesn't exist, look for a data file
std::string mask;
- mask = gDirUtilp->getDirDelimiter();
- mask += VFS_DATA_FILE_BASE;
+ mask = VFS_DATA_FILE_BASE;
mask += "*";
std::string dir;
- dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
+ dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
std::string found_file;
LLDirIterator iter(dir, mask);
@@ -3716,7 +3747,7 @@ bool LLAppViewer::initCache()
}
}
- old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE) + llformat("%u",old_salt);
+ old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u", old_salt);
stat_result = LLFile::stat(old_vfs_index_file, &s);
if (stat_result)
@@ -3729,27 +3760,25 @@ bool LLAppViewer::initCache()
// Just in case, nuke any other old cache files in the directory.
std::string dir;
- dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
+ dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
std::string mask;
- mask = gDirUtilp->getDirDelimiter();
- mask += VFS_DATA_FILE_BASE;
+ mask = VFS_DATA_FILE_BASE;
mask += "*";
gDirUtilp->deleteFilesInDir(dir, mask);
- mask = gDirUtilp->getDirDelimiter();
- mask += VFS_INDEX_FILE_BASE;
+ mask = VFS_INDEX_FILE_BASE;
mask += "*";
gDirUtilp->deleteFilesInDir(dir, mask);
}
- new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",new_salt);
- new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",new_salt);
+ new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u", new_salt);
+ new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u", new_salt);
- static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2");
- static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2");
+ static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_data.db2");
+ static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_index.db2");
if (resize_vfs)
{
@@ -3772,19 +3801,19 @@ bool LLAppViewer::initCache()
// Don't remove VFS after viewer crashes. If user has corrupt data, they can reinstall. JC
gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
- if( !gVFS )
+ if (!gVFS)
{
return false;
}
gStaticVFS = LLVFS::createLLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
- if( !gStaticVFS )
+ if (!gStaticVFS)
{
return false;
}
BOOL success = gVFS->isValid() && gStaticVFS->isValid();
- if( !success )
+ if (!success)
{
return false;
}
@@ -3805,11 +3834,11 @@ bool LLAppViewer::initCache()
void LLAppViewer::purgeCache()
{
- LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl;
+ LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
- std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
- gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
+ std::string mask = "*.*";
+ gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
}
std::string LLAppViewer::getSecondLifeTitle() const
@@ -4313,7 +4342,6 @@ void LLAppViewer::idle()
//
// Update weather effects
//
- LLWorld::getInstance()->updateClouds(gFrameDTClamped);
gSky.propagateHeavenlyBodies(gFrameDTClamped); // moves sun, moon, and planets
// Update wind vector
@@ -4329,9 +4357,6 @@ void LLAppViewer::idle()
// Compute average wind and use to drive motion of water
average_wind = regionp->mWind.getAverage();
- F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
-
- gSky.setCloudDensityAtAgent(cloud_density);
gSky.setWind(average_wind);
//LLVOWater::setWind(average_wind);
}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 6396ca91ff..445bd208ef 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -295,23 +295,44 @@ void create_console()
// redirect unbuffered STDOUT to the console
l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
- fp = _fdopen( h_con_handle, "w" );
- *stdout = *fp;
- setvbuf( stdout, NULL, _IONBF, 0 );
+ if (h_con_handle == -1)
+ {
+ llwarns << "create_console() failed to open stdout handle" << llendl;
+ }
+ else
+ {
+ fp = _fdopen( h_con_handle, "w" );
+ *stdout = *fp;
+ setvbuf( stdout, NULL, _IONBF, 0 );
+ }
// redirect unbuffered STDIN to the console
l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE);
h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
- fp = _fdopen( h_con_handle, "r" );
- *stdin = *fp;
- setvbuf( stdin, NULL, _IONBF, 0 );
+ if (h_con_handle == -1)
+ {
+ llwarns << "create_console() failed to open stdin handle" << llendl;
+ }
+ else
+ {
+ fp = _fdopen( h_con_handle, "r" );
+ *stdin = *fp;
+ setvbuf( stdin, NULL, _IONBF, 0 );
+ }
// redirect unbuffered STDERR to the console
l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE);
h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
- fp = _fdopen( h_con_handle, "w" );
- *stderr = *fp;
- setvbuf( stderr, NULL, _IONBF, 0 );
+ if (h_con_handle == -1)
+ {
+ llwarns << "create_console() failed to open stderr handle" << llendl;
+ }
+ else
+ {
+ fp = _fdopen( h_con_handle, "w" );
+ *stderr = *fp;
+ setvbuf( stderr, NULL, _IONBF, 0 );
+ }
}
LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) :
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index c08771c5e7..5b9a449be1 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -384,18 +384,18 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
// Continuing the horrible hack above, we need to extract the originally requested permissions data, if any,
// and use them for each next file to be uploaded. Note the requested perms are not the same as the
U32 everyone_perms =
- content.has("everyone_mask") ?
- content["everyone_mask"].asInteger() :
+ content.has("new_everyone_mask") ?
+ content["new_everyone_mask"].asInteger() :
PERM_NONE;
U32 group_perms =
- content.has("group_mask") ?
- content["group_mask"].asInteger() :
+ content.has("new_group_mask") ?
+ content["new_group_mask"].asInteger() :
PERM_NONE;
U32 next_owner_perms =
- content.has("next_owner_mask") ?
- content["next_owner_mask"].asInteger() :
+ content.has("new_next_owner_mask") ?
+ content["new_next_owner_mask"].asInteger() :
PERM_NONE;
std::string display_name = LLStringUtil::null;
@@ -449,7 +449,7 @@ void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
std::string result = content["state"];
LLUUID new_id = content["new_asset"];
- llinfos << "result: " << result << "new_id:" << new_id << llendl;
+ llinfos << "result: " << result << " new_id: " << new_id << llendl;
if (result == "complete"
&& mBakedUploadData != NULL)
{ // Invoke
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index 70871b62e2..381b919c4a 100644
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -112,6 +112,7 @@ private:
struct LLBakedUploadData;
class LLSendTexLayerResponder : public LLAssetUploadResponder
{
+ LOG_CLASS(LLSendTexLayerResponder);
public:
LLSendTexLayerResponder(const LLSD& post_data,
const LLUUID& vfile_id,
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index cbbdcb2983..8344b08bfb 100644..100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -49,6 +49,7 @@
#include "llfloaterpay.h"
#include "llfloaterwebcontent.h"
#include "llfloaterworldmap.h"
+#include "llfolderview.h"
#include "llgiveinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
@@ -69,6 +70,7 @@
#include "lltrans.h"
#include "llcallingcard.h"
#include "llslurl.h" // IDEVO
+#include "llsidepanelinventory.h"
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@@ -312,7 +314,9 @@ static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarNa
std::string url = getProfileURL(username);
// PROFILES: open in webkit window
- LLWeb::loadWebURLInternal(url, "", agent_id.asString());
+ const bool show_chrome = false;
+ static LLCachedControl<LLRect> profile_rect(gSavedSettings, "WebProfileRect");
+ LLFloaterWebContent::create(url, "", agent_id.asString(), show_chrome, profile_rect);
}
// static
@@ -444,8 +448,6 @@ void LLAvatarActions::share(const LLUUID& id)
namespace action_give_inventory
{
- typedef std::set<LLUUID> uuid_set_t;
-
/**
* Returns a pointer to 'Add More' inventory panel of Edit Outfit SP.
*/
@@ -475,18 +477,16 @@ namespace action_give_inventory
/**
* Checks My Inventory visibility.
*/
+
static bool is_give_inventory_acceptable()
{
- LLInventoryPanel* active_panel = get_active_inventory_panel();
- if (!active_panel) return false;
-
// check selection in the panel
- const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool acceptable = false;
- uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
- const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+ std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+ const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
@@ -529,12 +529,12 @@ namespace action_give_inventory
}
}
- static void build_items_string(const uuid_set_t& inventory_selected_uuids , std::string& items_string)
+ static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
{
llassert(inventory_selected_uuids.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
- for (uuid_set_t::const_iterator it = inventory_selected_uuids.begin(); ; )
+ for (std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); ; )
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
@@ -570,10 +570,7 @@ namespace action_give_inventory
return;
}
- LLInventoryPanel* active_panel = get_active_inventory_panel();
- if (!active_panel) return;
-
- const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
@@ -590,8 +587,8 @@ namespace action_give_inventory
// We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710
const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid);
- uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
- const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+ std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+ const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
const std::string& separator = LLTrans::getString("words_separator");
std::string noncopy_item_names;
@@ -654,10 +651,7 @@ namespace action_give_inventory
{
llassert(avatar_names.size() == avatar_uuids.size());
- LLInventoryPanel* active_panel = get_active_inventory_panel();
- if (!active_panel) return;
-
- const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
@@ -678,6 +672,33 @@ namespace action_give_inventory
}
}
+
+
+//static
+std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
+{
+ std::set<LLUUID> inventory_selected_uuids;
+
+ LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
+ if (active_panel)
+ {
+ inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ }
+
+ if (inventory_selected_uuids.empty())
+ {
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+ LLInventoryPanel * inbox = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ inventory_selected_uuids = inbox->getRootFolder()->getSelectionList();
+ }
+
+ }
+
+ return inventory_selected_uuids;
+}
+
//static
void LLAvatarActions::shareWithAvatars()
{
@@ -705,12 +726,12 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL
// check selection in the panel
LLFolderView* root_folder = inv_panel->getRootFolder();
- const uuid_set_t inventory_selected_uuids = root_folder->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList();
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool can_share = true;
- uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
- const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+ std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+ const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
@@ -773,6 +794,10 @@ bool LLAvatarActions::canOfferTeleport(const LLUUID& id)
// static
bool LLAvatarActions::canOfferTeleport(const uuid_vec_t& ids)
{
+ // We can't send more than 250 lures in a single message, so disable this
+ // button when there are too many id's selected.
+ if(ids.size() > 250) return false;
+
bool result = true;
for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
{
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 956fed7461..fbfd815f41 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -36,6 +36,7 @@
class LLInventoryPanel;
+
/**
* Friend-related actions (add, remove, offer teleport, etc)
*/
@@ -196,6 +197,8 @@ public:
*/
static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
+ static std::set<LLUUID> getInventorySelectedUUIDs();
+
private:
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static bool handleRemove(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index f51552aae5..79e6c7b66b 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -46,6 +46,7 @@
#include "llhints.h"
#include "llimfloater.h" // for LLIMFloater
#include "llnearbychatbar.h"
+#include "llnearbychatbarlistener.h"
#include "llsidetray.h"
#include "llspeakbutton.h"
#include "llsplitbutton.h"
@@ -385,6 +386,7 @@ void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, b
{
bool voice_status = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
getChild<LLButton>("speak_flyout_btn")->setEnabled(voice_status);
+ gMenuBarView->getChild<LLView>("Nearby Voice")->setEnabled(voice_status);
if (voice_status)
{
LLFirstUse::speak(true);
@@ -537,6 +539,8 @@ BOOL LLBottomTray::postBuild()
mNearbyChatBar = findChild<LLNearbyChatBar>("chat_bar");
LLHints::registerHintTarget("chat_bar", mNearbyChatBar->LLView::getHandle());
+ mListener.reset(new LLNearbyChatBarListener(*mNearbyChatBar));
+
mChatBarContainer = getChild<LLLayoutPanel>("chat_bar_layout_panel");
mNearbyCharResizeHandlePanel = getChild<LLPanel>("chat_bar_resize_handle_panel");
@@ -567,7 +571,7 @@ BOOL LLBottomTray::postBuild()
// it takes some time between logging in to world and connecting to voice channel.
getChild<LLButton>("speak_btn")->setEnabled(false);
getChild<LLButton>("speak_flyout_btn")->setEnabled(false);
-
+ gMenuBarView->getChild<LLView>("Nearby Voice")->setEnabled(false);
// Registering Chat Bar to receive Voice client status change notifications.
LLVoiceClient::getInstance()->addObserver(this);
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index d9c95d82e5..62718531ef 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -39,6 +39,7 @@ class LLIMChiclet;
class LLBottomTrayLite;
class LLLayoutPanel;
class LLMenuGL;
+class LLNearbyChatBarListener;
// Build time optimization, generate once in .cpp file
#ifndef LLBOTTOMTRAY_CPP
@@ -555,6 +556,9 @@ protected:
* Image used to show position where dragged button will be dropped.
*/
LLUIImage* mImageDragIndication;
+
+ // We want only one LLNearbyChatBarListener object, so it's tied to this singleton
+ boost::shared_ptr<LLNearbyChatBarListener> mListener;
};
#endif // LL_LLBOTTOMPANEL_H
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 6e58be8174..cf0374075a 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -671,6 +671,9 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl)
}
}
+
+/* Cruft - global gChatHandler declared below has been commented out,
+ so this class is never used. See similar code in llnearbychatbar.cpp
class LLChatHandler : public LLCommandHandler
{
public:
@@ -691,7 +694,7 @@ public:
{
S32 channel = tokens[0].asInteger();
// VWR-19499 Restrict function to chat channels greater than 0.
- if ((channel > 0) && (channel < 2147483647))
+ if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG))
{
retval = true;
// Say mesg on channel
@@ -710,3 +713,4 @@ public:
// Creating the object registers with the dispatcher.
//LLChatHandler gChatHandler;
+cruft */
diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp
deleted file mode 100644
index cda0f6e4a2..0000000000
--- a/indra/newview/llcloud.cpp
+++ /dev/null
@@ -1,538 +0,0 @@
-/**
- * @file llcloud.cpp
- * @brief Implementation of viewer LLCloudLayer class
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llmath.h"
-//#include "vmath.h"
-#include "v3math.h"
-#include "v4math.h"
-#include "llquaternion.h"
-#include "llrand.h"
-#include "v4color.h"
-
-#include "llwind.h"
-#include "llcloud.h"
-#include "llgl.h"
-#include "llviewerobjectlist.h"
-#include "llvoclouds.h"
-#include "llvosky.h"
-#include "llsky.h"
-#include "llviewerregion.h"
-#include "patch_dct.h"
-#include "patch_code.h"
-#include "llglheaders.h"
-#include "pipeline.h"
-#include "lldrawpool.h"
-#include "llworld.h"
-
-extern LLPipeline gPipeline;
-
-const F32 CLOUD_UPDATE_RATE = 1.0f; // Global time dilation for clouds
-const F32 CLOUD_GROW_RATE = 0.05f;
-const F32 CLOUD_DECAY_RATE = -0.05f;
-const F32 CLOUD_VELOCITY_SCALE = 0.01f;
-const F32 CLOUD_DENSITY = 25.f;
-const S32 CLOUD_COUNT_MAX = 20;
-const F32 CLOUD_HEIGHT_RANGE = 48.f;
-const F32 CLOUD_HEIGHT_MEAN = 192.f;
-
-enum
-{
- LL_PUFF_GROWING = 0,
- LL_PUFF_DYING = 1
-};
-
-// Used for patch decoder
-S32 gBuffer[16*16];
-
-
-//static
-S32 LLCloudPuff::sPuffCount = 0;
-
-LLCloudPuff::LLCloudPuff() :
- mAlpha(0.01f),
- mRate(CLOUD_GROW_RATE*CLOUD_UPDATE_RATE),
- mLifeState(LL_PUFF_GROWING)
-{
-}
-
-LLCloudGroup::LLCloudGroup() :
- mCloudLayerp(NULL),
- mDensity(0.f),
- mTargetPuffCount(0),
- mVOCloudsp(NULL)
-{
-}
-
-void LLCloudGroup::cleanup()
-{
- if (mVOCloudsp)
- {
- if (!mVOCloudsp->isDead())
- {
- gObjectList.killObject(mVOCloudsp);
- }
- mVOCloudsp = NULL;
- }
-}
-
-void LLCloudGroup::setCenterRegion(const LLVector3 &center)
-{
- mCenterRegion = center;
-}
-
-void LLCloudGroup::updatePuffs(const F32 dt)
-{
- mDensity = mCloudLayerp->getDensityRegion(mCenterRegion);
-
- if (!mVOCloudsp)
- {
- mVOCloudsp = (LLVOClouds *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_CLOUDS, mCloudLayerp->getRegion());
- mVOCloudsp->setCloudGroup(this);
- mVOCloudsp->setPositionRegion(mCenterRegion);
- mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
- 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH,
- CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f);
- gPipeline.createObject(mVOCloudsp);
- }
-
- LLVector3 velocity;
- LLVector3d vel_d;
- // Update the positions of all of the clouds
- for (U32 i = 0; i < mCloudPuffs.size(); i++)
- {
- LLCloudPuff &puff = mCloudPuffs[i];
- velocity = mCloudLayerp->getRegion()->mWind.getCloudVelocity(mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.mPositionGlobal));
- velocity *= CLOUD_VELOCITY_SCALE*CLOUD_UPDATE_RATE;
- vel_d.setVec(velocity);
- mCloudPuffs[i].mPositionGlobal += vel_d;
- mCloudPuffs[i].mAlpha += mCloudPuffs[i].mRate * dt;
- mCloudPuffs[i].mAlpha = llmin(1.f, mCloudPuffs[i].mAlpha);
- mCloudPuffs[i].mAlpha = llmax(0.f, mCloudPuffs[i].mAlpha);
- }
-}
-
-void LLCloudGroup::updatePuffOwnership()
-{
- U32 i = 0;
- while (i < mCloudPuffs.size())
- {
- if (mCloudPuffs[i].getLifeState() == LL_PUFF_DYING)
- {
- i++;
- continue;
- }
- if (inGroup(mCloudPuffs[i]))
- {
- i++;
- continue;
- }
-
- //llinfos << "Cloud moving to new group" << llendl;
- LLCloudGroup *new_cgp = LLWorld::getInstance()->findCloudGroup(mCloudPuffs[i]);
- if (!new_cgp)
- {
- //llinfos << "Killing puff not in group" << llendl;
- mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
- mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
- i++;
- continue;
- }
- //llinfos << "Puff handed off!" << llendl;
- LLCloudPuff puff;
- puff.mPositionGlobal = mCloudPuffs[i].mPositionGlobal;
- puff.mAlpha = mCloudPuffs[i].mAlpha;
- mCloudPuffs.erase(mCloudPuffs.begin() + i);
- new_cgp->mCloudPuffs.push_back(puff);
- }
-
- //llinfos << "Puff count: " << LLCloudPuff::sPuffCount << llendl;
-}
-
-void LLCloudGroup::updatePuffCount()
-{
- if (!mVOCloudsp)
- {
- return;
- }
- S32 i;
- S32 target_puff_count = llround(CLOUD_DENSITY * mDensity);
- target_puff_count = llmax(0, target_puff_count);
- target_puff_count = llmin(CLOUD_COUNT_MAX, target_puff_count);
- S32 current_puff_count = (S32) mCloudPuffs.size();
- // Create a new cloud if we need one
- if (current_puff_count < target_puff_count)
- {
- LLVector3d puff_pos_global;
- mCloudPuffs.resize(target_puff_count);
- for (i = current_puff_count; i < target_puff_count; i++)
- {
- puff_pos_global = mVOCloudsp->getPositionGlobal();
- F32 x = ll_frand(256.f/CLOUD_GROUPS_PER_EDGE) - 128.f/CLOUD_GROUPS_PER_EDGE;
- F32 y = ll_frand(256.f/CLOUD_GROUPS_PER_EDGE) - 128.f/CLOUD_GROUPS_PER_EDGE;
- F32 z = ll_frand(CLOUD_HEIGHT_RANGE) - 0.5f*CLOUD_HEIGHT_RANGE;
- puff_pos_global += LLVector3d(x, y, z);
- mCloudPuffs[i].mPositionGlobal = puff_pos_global;
- mCloudPuffs[i].mAlpha = 0.01f;
- LLCloudPuff::sPuffCount++;
- }
- }
-
- // Count the number of live puffs
- S32 live_puff_count = 0;
- for (i = 0; i < (S32) mCloudPuffs.size(); i++)
- {
- if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
- {
- live_puff_count++;
- }
- }
-
-
- // Start killing enough puffs so the live puff count == target puff count
- S32 new_dying_count = llmax(0, live_puff_count - target_puff_count);
- i = 0;
- while (new_dying_count > 0)
- {
- if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING)
- {
- //llinfos << "Killing extra live cloud" << llendl;
- mCloudPuffs[i].setLifeState(LL_PUFF_DYING);
- mCloudPuffs[i].mRate = CLOUD_DECAY_RATE*CLOUD_UPDATE_RATE;
- new_dying_count--;
- }
- i++;
- }
-
- // Remove fully dead puffs
- i = 0;
- while (i < (S32) mCloudPuffs.size())
- {
- if (mCloudPuffs[i].isDead())
- {
- //llinfos << "Removing dead puff!" << llendl;
- mCloudPuffs.erase(mCloudPuffs.begin() + i);
- LLCloudPuff::sPuffCount--;
- }
- else
- {
- i++;
- }
- }
-}
-
-BOOL LLCloudGroup::inGroup(const LLCloudPuff &puff) const
-{
- // Do min/max check on center of the cloud puff
- F32 min_x, min_y, max_x, max_y;
- F32 delta = 128.f/CLOUD_GROUPS_PER_EDGE;
- min_x = mCenterRegion.mV[VX] - delta;
- min_y = mCenterRegion.mV[VY] - delta;
- max_x = mCenterRegion.mV[VX] + delta;
- max_y = mCenterRegion.mV[VY] + delta;
-
- LLVector3 pos_region = mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.getPositionGlobal());
-
- if ((pos_region.mV[VX] < min_x)
- || (pos_region.mV[VY] < min_y)
- || (pos_region.mV[VX] > max_x)
- || (pos_region.mV[VY] > max_y))
- {
- return FALSE;
- }
- return TRUE;
-}
-
-LLCloudLayer::LLCloudLayer()
-: mOriginGlobal(0.0f, 0.0f, 0.0f),
- mMetersPerEdge(1.0f),
- mMetersPerGrid(1.0f),
- mWindp(NULL),
- mDensityp(NULL)
-{
- S32 i, j;
- for (i = 0; i < 4; i++)
- {
- mNeighbors[i] = NULL;
- }
-
- F32 x, y;
- for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
- {
- y = (0.5f + i)*(256.f/CLOUD_GROUPS_PER_EDGE);
- for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
- {
- x = (0.5f + j)*(256.f/CLOUD_GROUPS_PER_EDGE);
-
- mCloudGroups[i][j].setCloudLayerp(this);
- mCloudGroups[i][j].setCenterRegion(LLVector3(x, y, CLOUD_HEIGHT_MEAN));
- }
- }
-}
-
-
-
-LLCloudLayer::~LLCloudLayer()
-{
- destroy();
-}
-
-
-void LLCloudLayer::create(LLViewerRegion *regionp)
-{
- llassert(regionp);
-
- mRegionp = regionp;
- mDensityp = new F32 [CLOUD_GRIDS_PER_EDGE * CLOUD_GRIDS_PER_EDGE];
-
- U32 i;
- for (i = 0; i < CLOUD_GRIDS_PER_EDGE*CLOUD_GRIDS_PER_EDGE; i++)
- {
- mDensityp[i] = 0.f;
- }
-}
-
-void LLCloudLayer::setRegion(LLViewerRegion *regionp)
-{
- mRegionp = regionp;
-}
-
-void LLCloudLayer::destroy()
-{
- reset();
-
- delete [] mDensityp;
- mDensityp = NULL;
- mWindp = NULL;
-}
-
-
-void LLCloudLayer::reset()
-{
- // Kill all of the existing puffs
- S32 i, j;
-
- for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
- {
- for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
- {
- mCloudGroups[i][j].cleanup();
- }
- }
-}
-
-void LLCloudLayer::setWindPointer(LLWind *windp)
-{
- if (mWindp)
- {
- mWindp->setCloudDensityPointer(NULL);
- }
- mWindp = windp;
- if (mWindp)
- {
- mWindp->setCloudDensityPointer(mDensityp);
- }
-}
-
-
-void LLCloudLayer::setWidth(F32 width)
-{
- mMetersPerEdge = width;
- mMetersPerGrid = width / CLOUD_GRIDS_PER_EDGE;
-}
-
-
-F32 LLCloudLayer::getDensityRegion(const LLVector3 &pos_region)
-{
- // "position" is region-local
- S32 i, j, ii, jj;
-
- i = lltrunc(pos_region.mV[VX] / mMetersPerGrid);
- j = lltrunc(pos_region.mV[VY] / mMetersPerGrid);
- ii = i + 1;
- jj = j + 1;
-
-
- // clamp
- if (i >= (S32)CLOUD_GRIDS_PER_EDGE)
- {
- i = CLOUD_GRIDS_PER_EDGE - 1;
- ii = i;
- }
- else if (i < 0)
- {
- i = 0;
- ii = i;
- }
- else if (ii >= (S32)CLOUD_GRIDS_PER_EDGE || ii < 0)
- {
- ii = i;
- }
-
- if (j >= (S32)CLOUD_GRIDS_PER_EDGE)
- {
- j = CLOUD_GRIDS_PER_EDGE - 1;
- jj = j;
- }
- else if (j < 0)
- {
- j = 0;
- jj = j;
- }
- else if (jj >= (S32)CLOUD_GRIDS_PER_EDGE || jj < 0)
- {
- jj = j;
- }
-
- F32 dx = (pos_region.mV[VX] - (F32) i * mMetersPerGrid) / mMetersPerGrid;
- F32 dy = (pos_region.mV[VY] - (F32) j * mMetersPerGrid) / mMetersPerGrid;
- F32 omdx = 1.0f - dx;
- F32 omdy = 1.0f - dy;
-
- F32 density = dx * dy * *(mDensityp + ii + jj * CLOUD_GRIDS_PER_EDGE) +
- dx * omdy * *(mDensityp + i + jj * CLOUD_GRIDS_PER_EDGE) +
- omdx * dy * *(mDensityp + ii + j * CLOUD_GRIDS_PER_EDGE) +
- omdx * omdy * *(mDensityp + i + j * CLOUD_GRIDS_PER_EDGE);
-
- return density;
-}
-
-void LLCloudLayer::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp)
-{
- LLPatchHeader patch_header;
-
- init_patch_decompressor(group_headerp->patch_size);
-
- // Don't use the packed group_header stride because the strides used on
- // simulator and viewer are not equal.
- group_headerp->stride = group_headerp->patch_size; // offset required to step up one row
- set_group_of_patch_header(group_headerp);
-
- decode_patch_header(bitpack, &patch_header);
- decode_patch(bitpack, gBuffer);
- decompress_patch(mDensityp, gBuffer, &patch_header);
-}
-
-void LLCloudLayer::updatePuffs(const F32 dt)
-{
- // We want to iterate through all of the cloud groups
- // and update their density targets
-
- S32 i, j;
-
- for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
- {
- for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
- {
- mCloudGroups[i][j].updatePuffs(dt);
- }
- }
-}
-
-void LLCloudLayer::updatePuffOwnership()
-{
- S32 i, j;
-
- for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
- {
- for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
- {
- mCloudGroups[i][j].updatePuffOwnership();
- }
- }
-}
-
-void LLCloudLayer::updatePuffCount()
-{
- S32 i, j;
-
- for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
- {
- for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
- {
- mCloudGroups[i][j].updatePuffCount();
- }
- }
-}
-
-LLCloudGroup *LLCloudLayer::findCloudGroup(const LLCloudPuff &puff)
-{
- S32 i, j;
-
- for (i = 0; i < CLOUD_GROUPS_PER_EDGE; i++)
- {
- for (j = 0; j < CLOUD_GROUPS_PER_EDGE; j++)
- {
- if (mCloudGroups[i][j].inGroup(puff))
- {
- return &(mCloudGroups[i][j]);
- }
- }
- }
- return NULL;
-}
-
-
-
-void LLCloudLayer::connectNeighbor(LLCloudLayer *cloudp, U32 direction)
-{
- if (direction >= 4)
- {
- // Only care about cardinal 4 directions.
- return;
- }
-
- mNeighbors[direction] = cloudp;
- if (cloudp)
- mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = this;
-}
-
-
-void LLCloudLayer::disconnectNeighbor(U32 direction)
-{
- if (direction >= 4)
- {
- // Only care about cardinal 4 directions.
- return;
- }
-
- if (mNeighbors[direction])
- {
- mNeighbors[direction]->mNeighbors[gDirOpposite[direction]] = NULL;
- mNeighbors[direction] = NULL;
- }
-}
-
-
-void LLCloudLayer::disconnectAllNeighbors()
-{
- S32 i;
- for (i = 0; i < 4; i++)
- {
- disconnectNeighbor(i);
- }
-}
diff --git a/indra/newview/llcloud.h b/indra/newview/llcloud.h
deleted file mode 100644
index 0435ba1ece..0000000000
--- a/indra/newview/llcloud.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * @file llcloud.h
- * @brief Description of viewer LLCloudLayer class
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCLOUD_H
-#define LL_LLCLOUD_H
-
-// Some ideas on how clouds should work
-//
-// Each region has a cloud layer
-// Each cloud layer has pre-allocated space for N clouds
-// The LLSky class knows the max number of clouds to render M.
-// All clouds use the same texture, but the tex-coords can take on 8 configurations
-// (four rotations, front and back)
-//
-// The sky's part
-// --------------
-// The sky knows that A clouds have been assigned to regions and there are B left over.
-// Divide B by number of active regions to get C.
-// Ask each region to add C more clouds and return total number D.
-// Add up all the D's to get a new A.
-//
-// The cloud layer's part
-// ----------------------
-// The cloud layer is a grid of possibility. Each grid's value represents the probablility
-// (0.0 to 1.0) that a cloud placement query will succeed.
-//
-// The sky asks the region to add C more clouds.
-// The cloud layer tries a total of E times to place clouds and returns total cloud count.
-//
-// Clouds move according to local wind velocity.
-// If a cloud moves out of region then it's location is sent to neighbor region
-// or it is allowed to drift and decay.
-//
-// The clouds in non-visible regions do not propagate every frame.
-// Each frame one non-visible region is allowed to propagate it's clouds
-// (might have to check to see if incoming cloud was already visible or not).
-//
-//
-
-#include "llmath.h"
-//#include "vmath.h"
-#include "v3math.h"
-#include "v3dmath.h"
-#include "v4math.h"
-#include "v4color.h"
-#include "llpointer.h"
-#include "lldarray.h"
-
-#include "llframetimer.h"
-
-const U32 CLOUD_GRIDS_PER_EDGE = 16;
-
-const F32 CLOUD_PUFF_WIDTH = 64.f;
-const F32 CLOUD_PUFF_HEIGHT = 48.f;
-
-class LLWind;
-class LLVOClouds;
-class LLViewerRegion;
-class LLCloudLayer;
-class LLBitPack;
-class LLGroupHeader;
-
-const S32 CLOUD_GROUPS_PER_EDGE = 4;
-
-class LLCloudPuff
-{
-public:
- LLCloudPuff();
-
- const LLVector3d &getPositionGlobal() const { return mPositionGlobal; }
- friend class LLCloudGroup;
-
- void updatePuffs(const F32 dt);
- void updatePuffOwnership();
-
- F32 getAlpha() const { return mAlpha; }
- U32 getLifeState() const { return mLifeState; }
- void setLifeState(const U32 state) { mLifeState = state; }
- BOOL isDead() const { return mAlpha <= 0.f; }
-
-
- static S32 sPuffCount;
-protected:
- F32 mAlpha;
- F32 mRate;
- LLVector3d mPositionGlobal;
-
- BOOL mLifeState;
-};
-
-class LLCloudGroup
-{
-public:
- LLCloudGroup();
-
- void cleanup();
-
- void setCloudLayerp(LLCloudLayer *clp) { mCloudLayerp = clp; }
- void setCenterRegion(const LLVector3 &center);
-
- void updatePuffs(const F32 dt);
- void updatePuffOwnership();
- void updatePuffCount();
-
- BOOL inGroup(const LLCloudPuff &puff) const;
-
- F32 getDensity() const { return mDensity; }
- S32 getNumPuffs() const { return (S32) mCloudPuffs.size(); }
- const LLCloudPuff &getPuff(const S32 i) { return mCloudPuffs[i]; }
-protected:
- LLCloudLayer *mCloudLayerp;
- LLVector3 mCenterRegion;
- F32 mDensity;
- S32 mTargetPuffCount;
-
- std::vector<LLCloudPuff> mCloudPuffs;
- LLPointer<LLVOClouds> mVOCloudsp;
-};
-
-
-class LLCloudLayer
-{
-public:
- LLCloudLayer();
- ~LLCloudLayer();
-
- void create(LLViewerRegion *regionp);
- void destroy();
-
- void reset(); // Clears all active cloud puffs
-
-
- void updatePuffs(const F32 dt);
- void updatePuffOwnership();
- void updatePuffCount();
-
- LLCloudGroup *findCloudGroup(const LLCloudPuff &puff);
-
- void setRegion(LLViewerRegion *regionp);
- LLViewerRegion* getRegion() const { return mRegionp; }
- void setWindPointer(LLWind *windp);
- void setOriginGlobal(const LLVector3d &origin_global) { mOriginGlobal = origin_global; }
- void setWidth(F32 width);
-
- void setBrightness(F32 brightness);
- void setSunColor(const LLColor4 &color);
-
- F32 getDensityRegion(const LLVector3 &pos_region); // "position" is in local coordinates
-
- void decompress(LLBitPack &bitpack, LLGroupHeader *group_header);
-
- LLCloudLayer* getNeighbor(const S32 n) const { return mNeighbors[n]; }
-
- void connectNeighbor(LLCloudLayer *cloudp, U32 direction);
- void disconnectNeighbor(U32 direction);
- void disconnectAllNeighbors();
-
-public:
- LLVector3d mOriginGlobal;
- F32 mMetersPerEdge;
- F32 mMetersPerGrid;
-
-
- F32 mMaxAlpha; // The max cloud puff _render_ alpha
-
-protected:
- LLCloudLayer *mNeighbors[4];
- LLWind *mWindp;
- LLViewerRegion *mRegionp;
- F32 *mDensityp; // the probability density grid
-
- LLCloudGroup mCloudGroups[CLOUD_GROUPS_PER_EDGE][CLOUD_GROUPS_PER_EDGE];
-};
-
-
-#endif
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index 84c560639e..254c0adef1 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -317,7 +317,6 @@ BOOL LLCOFWearables::postBuild()
mAttachments->setComparator(&WEARABLE_NAME_COMPARATOR);
mBodyParts->setComparator(&WEARABLE_NAME_COMPARATOR);
-
mClothingTab = getChild<LLAccordionCtrlTab>("tab_clothing");
mClothingTab->setDropDownStateChangedCallback(boost::bind(&LLCOFWearables::onAccordionTabStateChanged, this, _1, _2));
@@ -499,6 +498,10 @@ void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel
mAttachments->sort();
mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false)
}
+ else
+ {
+ mAttachments->setNoItemsCommentText(LLTrans::getString("no_attachments"));
+ }
if (mBodyParts->size())
{
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 19dba3f917..19dba3f917 100644..100755
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
diff --git a/indra/newview/lldaycyclemanager.cpp b/indra/newview/lldaycyclemanager.cpp
new file mode 100644
index 0000000000..347a467a8b
--- /dev/null
+++ b/indra/newview/lldaycyclemanager.cpp
@@ -0,0 +1,230 @@
+/**
+ * @file lldaycyclemanager.cpp
+ * @brief Implementation for the LLDayCycleManager class.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldaycyclemanager.h"
+
+#include "lldiriterator.h"
+
+void LLDayCycleManager::getPresetNames(preset_name_list_t& names) const
+{
+ names.clear();
+
+ for (dc_map_t::const_iterator it = mDayCycleMap.begin(); it != mDayCycleMap.end(); ++it)
+ {
+ names.push_back(it->first);
+ }
+}
+
+void LLDayCycleManager::getPresetNames(preset_name_list_t& user, preset_name_list_t& sys) const
+{
+ user.clear();
+ sys.clear();
+
+ for (dc_map_t::const_iterator it = mDayCycleMap.begin(); it != mDayCycleMap.end(); ++it)
+ {
+ const std::string& name = it->first;
+
+ if (isSystemPreset(name))
+ {
+ sys.push_back(name);
+ }
+ else
+ {
+ user.push_back(name);
+ }
+ }
+}
+
+void LLDayCycleManager::getUserPresetNames(preset_name_list_t& user) const
+{
+ preset_name_list_t sys; // unused
+ getPresetNames(user, sys);
+}
+
+bool LLDayCycleManager::getPreset(const std::string name, LLWLDayCycle& day_cycle) const
+{
+ dc_map_t::const_iterator it = mDayCycleMap.find(name);
+ if (it == mDayCycleMap.end())
+ {
+ return false;
+ }
+
+ day_cycle = it->second;
+ return true;
+}
+
+bool LLDayCycleManager::getPreset(const std::string name, LLSD& day_cycle) const
+{
+ LLWLDayCycle dc;
+ if (!getPreset(name, dc))
+ {
+ return false;
+ }
+
+ day_cycle = dc.asLLSD();
+ return true;
+}
+
+bool LLDayCycleManager::presetExists(const std::string name) const
+{
+ LLWLDayCycle dummy;
+ return getPreset(name, dummy);
+}
+
+bool LLDayCycleManager::isSystemPreset(const std::string& name) const
+{
+ return gDirUtilp->fileExists(getSysDir() + LLURI::escape(name) + ".xml");
+}
+
+bool LLDayCycleManager::savePreset(const std::string& name, const LLSD& data)
+{
+ // Save given preset.
+ LLWLDayCycle day;
+ day.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
+ day.save(getUserDir() + LLURI::escape(name) + ".xml");
+
+ // Add it to our map.
+ addPreset(name, data);
+ mModifySignal();
+ return true;
+}
+
+bool LLDayCycleManager::deletePreset(const std::string& name)
+{
+ // Remove it from the map.
+ dc_map_t::iterator it = mDayCycleMap.find(name);
+ if (it == mDayCycleMap.end())
+ {
+ LL_WARNS("Windlight") << "No day cycle named " << name << LL_ENDL;
+ return false;
+ }
+ mDayCycleMap.erase(it);
+
+ // Remove from the filesystem.
+ std::string filename = LLURI::escape(name) + ".xml";
+ if (gDirUtilp->fileExists(getUserDir() + filename))
+ {
+ gDirUtilp->deleteFilesInDir(getUserDir(), filename);
+ }
+
+ // Signal interested parties.
+ mModifySignal();
+ return true;
+}
+
+bool LLDayCycleManager::isSkyPresetReferenced(const std::string& preset_name) const
+{
+ // We're traversing local day cycles, they can only reference local skies.
+ LLWLParamKey key(preset_name, LLEnvKey::SCOPE_LOCAL);
+
+ for (dc_map_t::const_iterator it = mDayCycleMap.begin(); it != mDayCycleMap.end(); ++it)
+ {
+ if (it->second.hasReferencesTo(key))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+boost::signals2::connection LLDayCycleManager::setModifyCallback(const modify_signal_t::slot_type& cb)
+{
+ return mModifySignal.connect(cb);
+}
+
+// virtual
+void LLDayCycleManager::initSingleton()
+{
+ LL_DEBUGS("Windlight") << "Loading all day cycles" << LL_ENDL;
+ loadAllPresets();
+}
+
+void LLDayCycleManager::loadAllPresets()
+{
+ mDayCycleMap.clear();
+
+ // First, load system (coming out of the box) day cycles.
+ loadPresets(getSysDir());
+
+ // Then load user presets. Note that user day cycles will modify any system ones already loaded.
+ loadPresets(getUserDir());
+}
+
+void LLDayCycleManager::loadPresets(const std::string& dir)
+{
+ LLDirIterator dir_iter(dir, "*.xml");
+
+ while (1)
+ {
+ std::string file;
+ if (!dir_iter.next(file)) break; // no more files
+ loadPreset(dir + file);
+ }
+}
+
+bool LLDayCycleManager::loadPreset(const std::string& path)
+{
+ LLSD data = LLWLDayCycle::loadDayCycleFromPath(path);
+ if (data.isUndefined())
+ {
+ llwarns << "Error loading day cycle from " << path << llendl;
+ return false;
+ }
+
+ std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
+ addPreset(name, data);
+
+ return true;
+}
+
+bool LLDayCycleManager::addPreset(const std::string& name, const LLSD& data)
+{
+ if (name.empty())
+ {
+ llassert(name.empty());
+ return false;
+ }
+
+ LLWLDayCycle day;
+ day.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
+ mDayCycleMap[name] = day;
+ return true;
+}
+
+// static
+std::string LLDayCycleManager::getSysDir()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/days", "");
+}
+
+// static
+std::string LLDayCycleManager::getUserDir()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/days", "");
+}
diff --git a/indra/newview/lldaycyclemanager.h b/indra/newview/lldaycyclemanager.h
new file mode 100644
index 0000000000..3d2144960d
--- /dev/null
+++ b/indra/newview/lldaycyclemanager.h
@@ -0,0 +1,84 @@
+/**
+ * @file lldaycyclemanager.h
+ * @brief Implementation for the LLDayCycleManager class.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDAYCYCLEMANAGER_H
+#define LL_LLDAYCYCLEMANAGER_H
+
+#include <map>
+#include <string>
+
+#include "llwldaycycle.h"
+#include "llwlparammanager.h"
+
+/**
+ * WindLight day cycles manager class
+ *
+ * Provides interface for accessing, loading and saving day cycles.
+ */
+class LLDayCycleManager : public LLSingleton<LLDayCycleManager>
+{
+ LOG_CLASS(LLDayCycleManager);
+
+public:
+ typedef std::list<std::string> preset_name_list_t;
+
+ typedef std::map<std::string, LLWLDayCycle> dc_map_t;
+ typedef boost::signals2::signal<void()> modify_signal_t;
+
+ void getPresetNames(preset_name_list_t& names) const;
+ void getPresetNames(preset_name_list_t& user, preset_name_list_t& sys) const;
+ void getUserPresetNames(preset_name_list_t& user) const;
+
+ bool getPreset(const std::string name, LLWLDayCycle& day_cycle) const;
+ bool getPreset(const std::string name, LLSD& day_cycle) const;
+ bool presetExists(const std::string name) const;
+ bool isSystemPreset(const std::string& name) const;
+ bool savePreset(const std::string& name, const LLSD& data);
+ bool deletePreset(const std::string& name);
+
+ /// @return true if there is a day cycle that refers to the sky preset.
+ bool isSkyPresetReferenced(const std::string& preset_name) const;
+
+ /// Emitted when a preset gets added or deleted.
+ boost::signals2::connection setModifyCallback(const modify_signal_t::slot_type& cb);
+
+private:
+ friend class LLSingleton<LLDayCycleManager>;
+ /*virtual*/ void initSingleton();
+
+ void loadAllPresets();
+ void loadPresets(const std::string& dir);
+ bool loadPreset(const std::string& path);
+ bool addPreset(const std::string& name, const LLSD& data);
+
+ static std::string getSysDir();
+ static std::string getUserDir();
+
+ dc_map_t mDayCycleMap;
+ modify_signal_t mModifySignal;
+};
+
+#endif // LL_LLDAYCYCLEMANAGER_H
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index b6d67899f8..216cc66ef8 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -62,7 +62,8 @@ void LLDebugView::init()
LLRect r;
LLRect rect = getLocalRect();
- r.set(10, rect.getHeight() - 100, rect.getWidth()/2, 100);
+ // Rectangle to draw debug data in (full height, 3/4 width)
+ r.set(10, rect.getHeight() - 100, ((rect.getWidth()*3)/4), 100);
LLConsole::Params cp;
cp.name("debug console");
cp.max_lines(20);
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index bdc12ec0e3..debac9dcbf 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -94,7 +94,9 @@ void LLDrawable::init()
mRenderType = 0;
mCurrentScale = LLVector3(1,1,1);
mDistanceWRTCamera = 0.0f;
-
+ mPositionGroup.clear();
+ mExtents[0].clear();
+ mExtents[1].clear();
mQuietCount = 0;
mState = 0;
@@ -385,7 +387,6 @@ void LLDrawable::makeActive()
pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||
pcode == LLViewerObject::LL_VO_PART_GROUP ||
pcode == LLViewerObject::LL_VO_HUD_PART_GROUP ||
- pcode == LLViewerObject::LL_VO_CLOUDS ||
pcode == LLViewerObject::LL_VO_GROUND ||
pcode == LLViewerObject::LL_VO_SKY)
{
@@ -587,7 +588,10 @@ void LLDrawable::setRadius(F32 radius)
void LLDrawable::moveUpdatePipeline(BOOL moved)
{
- makeActive();
+ if (moved)
+ {
+ makeActive();
+ }
// Update the face centers.
for (S32 i = 0; i < getNumFaces(); i++)
@@ -695,7 +699,8 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
{
if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
{
- llerrs << "WTF?" << llendl;
+ llwarns << "Attempted to update distance for non-world camera." << llendl;
+ return;
}
//switch LOD with the spatial group to avoid artifacts
@@ -1513,10 +1518,6 @@ BOOL LLDrawable::isAnimating() const
{
return TRUE;
}
- if (mVObjp->getPCode() == LLViewerObject::LL_VO_CLOUDS)
- {
- return TRUE;
- }
if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero())
{
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 9ebe1a45b4..e268640a21 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -276,6 +276,7 @@ public:
REBUILD_SHADOW = 0x02000000,
HAS_ALPHA = 0x04000000,
RIGGED = 0x08000000,
+ PARTITION_MOVE = 0x10000000,
} EDrawableFlags;
private: //aligned members
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 25e4bc847c..fa7d6e2a40 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -35,7 +35,6 @@
#include "lldrawpoolalpha.h"
#include "lldrawpoolavatar.h"
#include "lldrawpoolbump.h"
-#include "lldrawpoolclouds.h"
#include "lldrawpoolground.h"
#include "lldrawpoolsimple.h"
#include "lldrawpoolsky.h"
@@ -191,6 +190,16 @@ void LLDrawPool::renderPostDeferred(S32 pass)
//virtual
void LLDrawPool::endRenderPass( S32 pass )
{
+ for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
+ { //dummy cleanup of any currently bound textures
+ if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
+ {
+ gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
+ gGL.getTexUnit(i)->disable();
+ }
+ }
+
+ gGL.getTexUnit(0)->activate();
}
//virtual
@@ -430,14 +439,14 @@ void LLRenderPass::renderTexture(U32 type, U32 mask)
pushBatches(type, mask, TRUE);
}
-void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture)
+void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
{
for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
{
LLDrawInfo* pparams = *i;
if (pparams)
{
- pushBatch(*pparams, mask, texture);
+ pushBatch(*pparams, mask, texture, batch_textures);
}
}
}
@@ -456,26 +465,43 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params)
}
}
-void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
applyModelMatrix(params);
+ bool tex_setup = false;
+
if (texture)
{
- if (params.mTexture.notNull())
+ if (batch_textures && params.mTextureList.size() > 1)
{
- params.mTexture->addTextureStats(params.mVSize);
- gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
- if (params.mTextureMatrix)
+ for (U32 i = 0; i < params.mTextureList.size(); ++i)
{
- glMatrixMode(GL_TEXTURE);
- glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
+ if (params.mTextureList[i].notNull())
+ {
+ gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
+ }
}
}
else
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ { //not batching textures or batch has only 1 texture -- might need a texture matrix
+ if (params.mTexture.notNull())
+ {
+ params.mTexture->addTextureStats(params.mVSize);
+ gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
+ if (params.mTextureMatrix)
+ {
+ tex_setup = true;
+ gGL.getTexUnit(0)->activate();
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ }
+ }
+ else
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
}
}
@@ -490,7 +516,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
}
- if (params.mTextureMatrix && texture && params.mTexture.notNull())
+ if (tex_setup)
{
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index d3fd9ead0d..c7acbb42c6 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -146,8 +146,8 @@ public:
void resetDrawOrders() { }
static void applyModelMatrix(LLDrawInfo& params);
- virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE);
- virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture);
+ virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
+ virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE);
virtual void renderTexture(U32 type, U32 mask);
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 8b5a2ce781..ad7e3ad593 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -124,7 +124,10 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
if (pass == 0)
{
simple_shader = &gDeferredAlphaProgram;
- fullbright_shader = &gDeferredFullbrightProgram;
+ fullbright_shader = &gObjectFullbrightProgram;
+
+ //prime simple shader (loads shadow relevant uniforms)
+ gPipeline.bindDeferredShader(*simple_shader);
}
else
{
@@ -228,13 +231,13 @@ void LLDrawPoolAlpha::render(S32 pass)
if (!LLPipeline::sRenderDeferred)
{
simple_shader->bind();
- pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask());
+ pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
}
if (fullbright_shader)
{
fullbright_shader->bind();
}
- pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask());
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
LLGLSLShader::bindNoShader();
}
else
@@ -273,7 +276,14 @@ void LLDrawPoolAlpha::render(S32 pass)
}
}
- renderAlpha(getVertexDataMask());
+ if (mVertexShaderLevel > 0)
+ {
+ renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX);
+ }
+ else
+ {
+ renderAlpha(getVertexDataMask());
+ }
gGL.setColorMask(true, false);
@@ -283,23 +293,26 @@ void LLDrawPoolAlpha::render(S32 pass)
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
- if (deferred_render && current_shader != NULL)
- {
- gPipeline.unbindDeferredShader(*current_shader);
- }
-
if (sShowDebugAlpha)
{
- if(gPipeline.canUseWindLightShaders())
+ BOOL shaders = gPipeline.canUseVertexShaders();
+ if(shaders)
{
- LLGLSLShader::bindNoShader();
+ gObjectFullbrightNonIndexedProgram.bind();
+ }
+ else
+ {
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
}
- gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
glColor4f(1,0,0,1);
LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ;
renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD0);
+ if(shaders)
+ {
+ gObjectFullbrightNonIndexedProgram.unbind();
+ }
}
}
@@ -339,12 +352,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
{
BOOL initialized_lighting = FALSE;
BOOL light_enabled = TRUE;
- S32 diffuse_channel = 0;
-
- BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders())
- || gPipeline.canUseWindLightShadersOnObjects();
-
+ BOOL use_shaders = gPipeline.canUseVertexShaders();
+
for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
{
LLSpatialGroup* group = *i;
@@ -357,7 +367,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow.
// All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress.
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
- group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_CLOUD &&
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
@@ -368,92 +377,89 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
LLRenderPass::applyModelMatrix(params);
+
+ if (params.mFullbright)
{
- if (params.mFullbright)
- {
- // Turn off lighting if it hasn't already been so.
- if (light_enabled || !initialized_lighting)
- {
- initialized_lighting = TRUE;
- if (use_shaders)
- {
- target_shader = fullbright_shader;
- }
- else
- {
- gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
- }
- light_enabled = FALSE;
- }
- }
- // Turn on lighting if it isn't already.
- else if (!light_enabled || !initialized_lighting)
+ // Turn off lighting if it hasn't already been so.
+ if (light_enabled || !initialized_lighting)
{
initialized_lighting = TRUE;
if (use_shaders)
{
- target_shader = simple_shader;
+ target_shader = fullbright_shader;
}
else
{
- gPipeline.enableLightsDynamic();
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
}
- light_enabled = TRUE;
+ light_enabled = FALSE;
}
-
- // If we need shaders, and we're not ALREADY using the proper shader, then bind it
- // (this way we won't rebind shaders unnecessarily).
- if(use_shaders && (current_shader != target_shader))
+ }
+ // Turn on lighting if it isn't already.
+ else if (!light_enabled || !initialized_lighting)
+ {
+ initialized_lighting = TRUE;
+ if (use_shaders)
{
- llassert(target_shader != NULL);
- if (deferred_render && current_shader != NULL)
- {
- gPipeline.unbindDeferredShader(*current_shader);
- diffuse_channel = 0;
- }
- current_shader = target_shader;
- if (deferred_render)
- {
- gPipeline.bindDeferredShader(*current_shader);
- diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- }
- else
- {
- current_shader->bind();
- }
+ target_shader = simple_shader;
}
- else if (!use_shaders && current_shader != NULL)
+ else
{
- if (deferred_render)
- {
- gPipeline.unbindDeferredShader(*current_shader);
- diffuse_channel = 0;
- }
- LLGLSLShader::bindNoShader();
- current_shader = NULL;
+ gPipeline.enableLightsDynamic();
}
+ light_enabled = TRUE;
+ }
- if (params.mGroup)
- {
- params.mGroup->rebuildMesh();
- }
+ // If we need shaders, and we're not ALREADY using the proper shader, then bind it
+ // (this way we won't rebind shaders unnecessarily).
+ if(use_shaders && (current_shader != target_shader))
+ {
+ llassert(target_shader != NULL);
+ current_shader = target_shader;
+ current_shader->bind();
+ }
+ else if (!use_shaders && current_shader != NULL)
+ {
+ LLGLSLShader::bindNoShader();
+ current_shader = NULL;
+ }
-
- if (params.mTexture.notNull())
+ if (params.mGroup)
+ {
+ params.mGroup->rebuildMesh();
+ }
+
+ bool tex_setup = false;
+
+ if (use_shaders && params.mTextureList.size() > 1)
+ {
+ for (U32 i = 0; i < params.mTextureList.size(); ++i)
{
- gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
- if(params.mTexture.notNull())
+ if (params.mTextureList[i].notNull())
{
- params.mTexture->addTextureStats(params.mVSize);
+ gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
}
+ }
+ }
+ else
+ { //not batching textures or batch has only 1 texture -- might need a texture matrix
+ if (params.mTexture.notNull())
+ {
+ params.mTexture->addTextureStats(params.mVSize);
+ gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
if (params.mTextureMatrix)
{
+ tex_setup = true;
gGL.getTexUnit(0)->activate();
glMatrixMode(GL_TEXTURE);
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
gPipeline.mTextureMatrixOps++;
}
}
+ else
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
}
params.mVertexBuffer->setBuffer(mask);
@@ -480,7 +486,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
}
- if (params.mTextureMatrix && params.mTexture.notNull())
+ if (tex_setup)
{
gGL.getTexUnit(0)->activate();
glLoadIdentity();
@@ -490,15 +496,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
}
- if (deferred_render && current_shader != NULL)
- {
- gPipeline.unbindDeferredShader(*current_shader);
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
- }
-
+ LLVertexBuffer::unbind();
+
if (!light_enabled)
{
gPipeline.enableLightsDynamic();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 645c7ebcae..9f790d03fe 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -459,14 +459,6 @@ S32 LLDrawPoolAvatar::getNumPasses()
{
return 10;
}
- if (LLPipeline::sImpostorRender)
- {
- return 1;
- }
- else
- {
- return 3;
- }
}
@@ -613,11 +605,11 @@ void LLDrawPoolAvatar::beginRigid()
{
if (LLPipeline::sUnderWaterRender)
{
- sVertexProgram = &gObjectSimpleWaterProgram;
+ sVertexProgram = &gObjectSimpleNonIndexedWaterProgram;
}
else
{
- sVertexProgram = &gObjectSimpleProgram;
+ sVertexProgram = &gObjectSimpleNonIndexedProgram;
}
if (sVertexProgram != NULL)
@@ -669,7 +661,7 @@ void LLDrawPoolAvatar::endDeferredImpostor()
void LLDrawPoolAvatar::beginDeferredRigid()
{
- sVertexProgram = &gDeferredDiffuseProgram;
+ sVertexProgram = &gDeferredNonIndexedDiffuseProgram;
sVertexProgram->bind();
}
@@ -700,11 +692,11 @@ void LLDrawPoolAvatar::beginSkinned()
{
if (LLPipeline::sUnderWaterRender)
{
- sVertexProgram = &gObjectSimpleWaterProgram;
+ sVertexProgram = &gObjectSimpleNonIndexedWaterProgram;
}
else
{
- sVertexProgram = &gObjectSimpleProgram;
+ sVertexProgram = &gObjectSimpleNonIndexedProgram;
}
}
@@ -789,11 +781,11 @@ void LLDrawPoolAvatar::beginRiggedSimple()
{
if (LLPipeline::sUnderWaterRender)
{
- sVertexProgram = &gObjectSimpleWaterProgram;
+ sVertexProgram = &gObjectSimpleNonIndexedWaterProgram;
}
else
{
- sVertexProgram = &gObjectSimpleProgram;
+ sVertexProgram = &gObjectSimpleNonIndexedProgram;
}
}
@@ -864,11 +856,11 @@ void LLDrawPoolAvatar::beginRiggedFullbright()
{
if (LLPipeline::sUnderWaterRender)
{
- sVertexProgram = &gObjectFullbrightWaterProgram;
+ sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram;
}
else
{
- sVertexProgram = &gObjectFullbrightProgram;
+ sVertexProgram = &gObjectFullbrightNonIndexedProgram;
}
}
@@ -908,11 +900,11 @@ void LLDrawPoolAvatar::beginRiggedShinySimple()
{
if (LLPipeline::sUnderWaterRender)
{
- sVertexProgram = &gObjectShinyWaterProgram;
+ sVertexProgram = &gObjectShinyNonIndexedWaterProgram;
}
else
{
- sVertexProgram = &gObjectShinyProgram;
+ sVertexProgram = &gObjectShinyNonIndexedProgram;
}
}
@@ -953,11 +945,11 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny()
{
if (LLPipeline::sUnderWaterRender)
{
- sVertexProgram = &gObjectFullbrightShinyWaterProgram;
+ sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram;
}
else
{
- sVertexProgram = &gObjectFullbrightShinyProgram;
+ sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram;
}
}
@@ -1419,7 +1411,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
- if (avatar->isSelf() && !gAgent.needsRenderAvatar())
+ if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled())
{
return;
}
@@ -1456,7 +1448,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
continue;
}
- const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id);
+ const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj);
if (!skin)
{
continue;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 29b50761d8..813b3820ee 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -94,6 +94,13 @@ void LLStandardBumpmap::restoreGL()
// static
void LLStandardBumpmap::addstandard()
{
+ if(!gTextureList.isInitialized())
+ {
+ //Note: loading pre-configuration sometimes triggers this call.
+ //But it is safe to return here because bump images will be reloaded during initialization later.
+ return ;
+ }
+
// can't assert; we destroyGL and restoreGL a lot during *first* startup, which populates this list already, THEN we explicitly init the list as part of *normal* startup. Sigh. So clear the list every time before we (re-)add the standard bumpmaps.
//llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 );
clear();
@@ -309,6 +316,9 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
llassert(0);
break;
}
+
+ //to cleanup texture channels
+ LLRenderPass::endRenderPass(pass);
}
//static
@@ -347,6 +357,11 @@ void LLDrawPoolBump::beginShiny(bool invisible)
}
bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
+
+ if (mVertexShaderLevel > 1)
+ { //indexed texture rendering, channel 0 is always diffuse
+ diffuse_channel = 0;
+ }
}
//static
@@ -414,16 +429,16 @@ void LLDrawPoolBump::renderShiny(bool invisible)
LLGLEnable blend_enable(GL_BLEND);
if (!invisible && mVertexShaderLevel > 1)
{
- LLRenderPass::renderTexture(LLRenderPass::PASS_SHINY, sVertexMask);
+ LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
}
else if (!invisible)
{
renderGroups(LLRenderPass::PASS_SHINY, sVertexMask);
}
- else // invisible
- {
- renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
- }
+ //else // invisible (deprecated)
+ //{
+ //renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
+ //}
}
}
@@ -522,6 +537,12 @@ void LLDrawPoolBump::beginFullbrightShiny()
gGL.getTexUnit(cube_channel)->bind(cube_map);
gGL.getTexUnit(0)->activate();
}
+
+ if (mVertexShaderLevel > 1)
+ { //indexed texture rendering, channel 0 is always diffuse
+ diffuse_channel = 0;
+ }
+
mShiny = TRUE;
}
@@ -536,7 +557,15 @@ void LLDrawPoolBump::renderFullbrightShiny()
if( gSky.mVOSkyp->getCubeMap() )
{
LLGLEnable blend_enable(GL_BLEND);
- LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+
+ if (mVertexShaderLevel > 1)
+ {
+ LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+ }
}
}
@@ -836,6 +865,9 @@ void LLDrawPoolBump::endPostDeferredPass(S32 pass)
endBump(LLRenderPass::PASS_POST_BUMP);
break;
}
+
+ //to disable texture channels
+ LLRenderPass::endRenderPass(pass);
}
void LLDrawPoolBump::renderPostDeferred(S32 pass)
@@ -889,9 +921,10 @@ void LLBumpImageList::destroyGL()
void LLBumpImageList::restoreGL()
{
- if(!gTextureList.isInitialized())
- {
- return ;
+ if(!gTextureList.isInitialized())
+ {
+ //safe to return here because bump images will be reloaded during initialization later.
+ return ;
}
LLStandardBumpmap::restoreGL();
@@ -1292,43 +1325,60 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
}
}
-void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
applyModelMatrix(params);
- if (params.mTextureMatrix)
+ bool tex_setup = false;
+
+ if (batch_textures && params.mTextureList.size() > 1)
{
- if (mShiny)
+ for (U32 i = 0; i < params.mTextureList.size(); ++i)
{
- gGL.getTexUnit(0)->activate();
- glMatrixMode(GL_TEXTURE);
+ if (params.mTextureList[i].notNull())
+ {
+ gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
+ }
}
- else
+ }
+ else
+ { //not batching textures or batch has only 1 texture -- might need a texture matrix
+ if (params.mTextureMatrix)
{
- gGL.getTexUnit(1)->activate();
- glMatrixMode(GL_TEXTURE);
+ if (mShiny)
+ {
+ gGL.getTexUnit(0)->activate();
+ glMatrixMode(GL_TEXTURE);
+ }
+ else
+ {
+ gGL.getTexUnit(1)->activate();
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
+ gPipeline.mTextureMatrixOps++;
+ gGL.getTexUnit(0)->activate();
+ }
+
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
gPipeline.mTextureMatrixOps++;
- gGL.getTexUnit(0)->activate();
- }
- glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
- gPipeline.mTextureMatrixOps++;
- }
-
- if (mShiny && mVertexShaderLevel > 1 && texture)
- {
- if (params.mTexture.notNull())
- {
- gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
- params.mTexture->addTextureStats(params.mVSize);
+ tex_setup = true;
}
- else
+
+ if (mShiny && mVertexShaderLevel > 1 && texture)
{
- gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
+ if (params.mTexture.notNull())
+ {
+ gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ;
+ params.mTexture->addTextureStats(params.mVSize);
+ }
+ else
+ {
+ gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
+ }
}
}
-
+
if (params.mGroup)
{
params.mGroup->rebuildMesh();
@@ -1336,7 +1386,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
params.mVertexBuffer->setBuffer(mask);
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
- if (params.mTextureMatrix)
+ if (tex_setup)
{
if (mShiny)
{
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index f4702bf61d..476b1d41b7 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -55,7 +55,7 @@ public:
virtual void endRenderPass( S32 pass );
virtual S32 getNumPasses();
/*virtual*/ void prerender();
- /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture);
+ /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
void renderBump(U32 type, U32 mask);
void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture);
diff --git a/indra/newview/lldrawpoolclouds.cpp b/indra/newview/lldrawpoolclouds.cpp
deleted file mode 100644
index 5db1d8cfed..0000000000
--- a/indra/newview/lldrawpoolclouds.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * @file lldrawpoolclouds.cpp
- * @brief LLDrawPoolClouds class implementation
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "lldrawpoolclouds.h"
-
-#include "llface.h"
-#include "llsky.h"
-#include "llviewercamera.h"
-#include "llvoclouds.h"
-#include "pipeline.h"
-
-LLDrawPoolClouds::LLDrawPoolClouds() :
- LLDrawPool(POOL_CLOUDS)
-{
-}
-
-LLDrawPool *LLDrawPoolClouds::instancePool()
-{
- return new LLDrawPoolClouds();
-}
-
-BOOL LLDrawPoolClouds::addFace(LLFace* face)
-{
- llerrs << "WTF?" << llendl;
- return FALSE;
-}
-
-void LLDrawPoolClouds::enqueue(LLFace *facep)
-{
- mDrawFace.push_back(facep);
- facep->mDistance = (facep->mCenterAgent - gCamera->getOrigin()) * gCamera->getAtAxis();
-}
-
-void LLDrawPoolClouds::beginRenderPass(S32 pass)
-{
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_NORMAL_ARRAY);
-}
-
-void LLDrawPoolClouds::prerender()
-{
- mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT);
-}
-
-void LLDrawPoolClouds::render(S32 pass)
-{
- LLFastTimer ftm(LLFastTimer::FTM_RENDER_CLOUDS);
- if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
- {
- return;
- }
-
- if (mDrawFace.empty())
- {
- return;
- }
-
- LLGLSPipelineAlpha gls_pipeline_alpha;
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- glAlphaFunc(GL_GREATER,0.01f);
-
- gPipeline.enableLightsFullbright(LLColor4(1.f,1.f,1.f));
-
- mDrawFace[0]->bindTexture();
-
- std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
-
- drawLoop();
-}
-
-
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 2e83167851..5dbb27cabb 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -44,6 +44,36 @@ static LLGLSLShader* fullbright_shader = NULL;
static LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple");
static LLFastTimer::DeclareTimer FTM_RENDER_GRASS_DEFERRED("Deferred Grass");
+void LLDrawPoolGlow::beginPostDeferredPass(S32 pass)
+{
+ gDeferredFullbrightProgram.bind();
+}
+
+void LLDrawPoolGlow::renderPostDeferred(S32 pass)
+{
+ LLFastTimer t(FTM_RENDER_GLOW);
+ LLGLEnable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.flush();
+ /// Get rid of z-fighting with non-glow pass.
+ LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.0f, -1.0f);
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ gGL.setColorMask(false, true);
+ pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+
+ gGL.setColorMask(true, false);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+}
+
+void LLDrawPoolGlow::endPostDeferredPass(S32 pass)
+{
+ gDeferredFullbrightProgram.unbind();
+ LLRenderPass::endRenderPass(pass);
+}
+
void LLDrawPoolGlow::render(S32 pass)
{
LLFastTimer t(FTM_RENDER_GLOW);
@@ -68,7 +98,15 @@ void LLDrawPoolGlow::render(S32 pass)
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
gGL.setColorMask(false, true);
- renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
+
+ if (shader_level > 1)
+ {
+ pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask());
+ }
gGL.setColorMask(true, false);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -79,10 +117,10 @@ void LLDrawPoolGlow::render(S32 pass)
}
}
-void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
+void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
{
glColor4ubv(params.mGlowColor.mV);
- LLRenderPass::pushBatch(params, mask, texture);
+ LLRenderPass::pushBatch(params, mask, texture, batch_textures);
}
@@ -126,10 +164,11 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
void LLDrawPoolSimple::endRenderPass(S32 pass)
{
LLFastTimer t(FTM_RENDER_SIMPLE);
+ stop_glerror();
LLRenderPass::endRenderPass(pass);
-
- if (mVertexShaderLevel > 0){
-
+ stop_glerror();
+ if (mVertexShaderLevel > 0)
+ {
simple_shader->unbind();
}
}
@@ -142,13 +181,24 @@ void LLDrawPoolSimple::render(S32 pass)
{ //render simple
LLFastTimer t(FTM_RENDER_SIMPLE);
gPipeline.enableLightsDynamic();
- renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
- if (LLPipeline::sRenderDeferred)
- { //if deferred rendering is enabled, bump faces aren't registered as simple
- //render bump faces here as simple so bump faces will appear under water
- renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask());
+ if (mVertexShaderLevel > 0)
+ {
+ U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
+
+ pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE);
+
+ if (LLPipeline::sRenderDeferred)
+ { //if deferred rendering is enabled, bump faces aren't registered as simple
+ //render bump faces here as simple so bump faces will appear under water
+ pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE);
+ }
+ }
+ else
+ {
+ renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
}
+
}
}
@@ -177,7 +227,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass)
{ //render simple
LLFastTimer t(FTM_RENDER_SIMPLE_DEFERRED);
- renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
+ pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
}
}
@@ -200,11 +250,11 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
if (LLPipeline::sUnderWaterRender)
{
- simple_shader = &gObjectSimpleWaterProgram;
+ simple_shader = &gObjectSimpleNonIndexedWaterProgram;
}
else
{
- simple_shader = &gObjectSimpleProgram;
+ simple_shader = &gObjectSimpleNonIndexedProgram;
}
if (mVertexShaderLevel > 0)
@@ -285,6 +335,26 @@ void LLDrawPoolFullbright::prerender()
mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}
+void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
+{
+ gDeferredFullbrightProgram.bind();
+}
+
+void LLDrawPoolFullbright::renderPostDeferred(S32 pass)
+{
+ LLFastTimer t(FTM_RENDER_FULLBRIGHT);
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
+}
+
+void LLDrawPoolFullbright::endPostDeferredPass(S32 pass)
+{
+ gDeferredFullbrightProgram.unbind();
+ LLRenderPass::endRenderPass(pass);
+}
+
void LLDrawPoolFullbright::beginRenderPass(S32 pass)
{
LLFastTimer t(FTM_RENDER_FULLBRIGHT);
@@ -313,25 +383,21 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass)
void LLDrawPoolFullbright::render(S32 pass)
{ //render fullbright
LLFastTimer t(FTM_RENDER_FULLBRIGHT);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
if (mVertexShaderLevel > 0)
{
fullbright_shader->bind();
fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
+ U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
}
else
{
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
+ renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
}
-
- //gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f);
-
- //LLGLEnable test(GL_ALPHA_TEST);
- //LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
- renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
-
- //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
S32 LLDrawPoolFullbright::getNumPasses()
diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h
index 5f3bbebbda..3811b3d398 100644
--- a/indra/newview/lldrawpoolsimple.h
+++ b/indra/newview/lldrawpoolsimple.h
@@ -98,9 +98,9 @@ public:
LLDrawPoolFullbright();
/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
- /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
- /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
- /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+ /*virtual*/ void beginPostDeferredPass(S32 pass);
+ /*virtual*/ void endPostDeferredPass(S32 pass);
+ /*virtual*/ void renderPostDeferred(S32 pass);
/*virtual*/ void beginRenderPass(S32 pass);
/*virtual*/ void endRenderPass(S32 pass);
@@ -126,12 +126,12 @@ public:
virtual void prerender() { }
/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
- /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
- /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
- /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+ /*virtual*/ void beginPostDeferredPass(S32 pass);
+ /*virtual*/ void endPostDeferredPass(S32 pass);
+ /*virtual*/ void renderPostDeferred(S32 pass);
void render(S32 pass = 0);
- void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE);
+ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
};
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 84eeace9c6..3daa0f8261 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -143,7 +143,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass )
void LLDrawPoolTerrain::endRenderPass( S32 pass )
{
LLFastTimer t(FTM_RENDER_TERRAIN);
- LLFacePool::endRenderPass(pass);
+ //LLFacePool::endRenderPass(pass);
if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) {
sShader->unbind();
@@ -215,8 +215,10 @@ void LLDrawPoolTerrain::render(S32 pass)
{ //use fullbright shader for highlighting
LLGLSLShader* old_shader = sShader;
sShader->unbind();
- sShader = &gObjectFullbrightProgram;
+ sShader = &gObjectFullbrightNonIndexedProgram;
sShader->bind();
+ LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.0f, -1.0f);
renderOwnership();
sShader = old_shader;
sShader->bind();
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 195ee60a2e..81c796b146 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -66,11 +66,11 @@ void LLDrawPoolTree::beginRenderPass(S32 pass)
if (LLPipeline::sUnderWaterRender)
{
- shader = &gObjectSimpleWaterProgram;
+ shader = &gObjectSimpleNonIndexedWaterProgram;
}
else
{
- shader = &gObjectSimpleProgram;
+ shader = &gObjectSimpleNonIndexedProgram;
}
if (gPipeline.canUseWindLightShadersOnObjects())
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index dc94924da4..31c14361b5 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -108,7 +108,7 @@ void LLDrawPoolWater::prerender()
// got rid of modulation by light color since it got a little too
// green at sunset and sl-57047 (underwater turns black at 8:00)
- sWaterFogColor = LLWaterParamManager::instance()->getFogColor();
+ sWaterFogColor = LLWaterParamManager::instance().getFogColor();
sWaterFogColor.mV[3] = 0;
}
@@ -527,7 +527,7 @@ void LLDrawPoolWater::shade()
//bind normal map
S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
- LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
+ LLWaterParamManager * param_mgr = &LLWaterParamManager::instance();
// change mWaterNormp if needed
if (mWaterNormp->getID() != param_mgr->getNormalMapID())
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 696c2d1abd..bf79c2100c 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -34,6 +34,8 @@
#include "llviewercamera.h"
#include "llimage.h"
#include "llwlparammanager.h"
+#include "llviewershadermgr.h"
+#include "llglslshader.h"
#include "llsky.h"
#include "llvowlsky.h"
#include "llviewerregion.h"
@@ -44,6 +46,8 @@ LLPointer<LLViewerTexture> LLDrawPoolWLSky::sCloudNoiseTexture = NULL;
LLPointer<LLImageRaw> LLDrawPoolWLSky::sCloudNoiseRawImage = NULL;
+static LLGLSLShader* cloud_shader = NULL;
+static LLGLSLShader* sky_shader = NULL;
LLDrawPoolWLSky::LLDrawPoolWLSky(void) :
@@ -66,7 +70,7 @@ LLDrawPoolWLSky::LLDrawPoolWLSky(void) :
sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
- LLWLParamManager::instance()->propagateParameters();
+ LLWLParamManager::getInstance()->propagateParameters();
}
LLDrawPoolWLSky::~LLDrawPoolWLSky()
@@ -83,12 +87,32 @@ LLViewerTexture *LLDrawPoolWLSky::getDebugTexture()
void LLDrawPoolWLSky::beginRenderPass( S32 pass )
{
+ sky_shader =
+ LLPipeline::sUnderWaterRender ?
+ &gObjectSimpleWaterProgram :
+ &gWLSkyProgram;
+
+ cloud_shader =
+ LLPipeline::sUnderWaterRender ?
+ &gObjectSimpleWaterProgram :
+ &gWLCloudProgram;
}
void LLDrawPoolWLSky::endRenderPass( S32 pass )
{
}
+void LLDrawPoolWLSky::beginDeferredPass(S32 pass)
+{
+ sky_shader = &gDeferredWLSkyProgram;
+ cloud_shader = &gDeferredWLCloudProgram;
+}
+
+void LLDrawPoolWLSky::endDeferredPass(S32 pass)
+{
+
+}
+
void LLDrawPoolWLSky::renderDome(F32 camHeightLocal, LLGLSLShader * shader) const
{
LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
@@ -128,19 +152,14 @@ void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const
{
if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
{
- LLGLSLShader* shader =
- LLPipeline::sUnderWaterRender ?
- &gObjectSimpleWaterProgram :
- &gWLSkyProgram;
-
LLGLDisable blend(GL_BLEND);
- shader->bind();
+ sky_shader->bind();
/// Render the skydome
- renderDome(camHeightLocal, shader);
+ renderDome(camHeightLocal, sky_shader);
- shader->unbind();
+ sky_shader->unbind();
}
}
@@ -161,7 +180,7 @@ void LLDrawPoolWLSky::renderStars(void) const
// clamping and allow the star_alpha param to brighten the stars.
bool error;
LLColor4 star_alpha(LLColor4::black);
- star_alpha.mV[3] = LLWLParamManager::instance()->mCurParams.getFloat("star_brightness", error) / 2.f;
+ star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f;
llassert_always(!error);
gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex());
@@ -186,23 +205,18 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const
{
if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS))
{
- LLGLSLShader* shader =
- LLPipeline::sUnderWaterRender ?
- &gObjectSimpleWaterProgram :
- &gWLCloudProgram;
-
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.getTexUnit(0)->bind(sCloudNoiseTexture);
- shader->bind();
+ cloud_shader->bind();
/// Render the skydome
- renderDome(camHeightLocal, shader);
+ renderDome(camHeightLocal, cloud_shader);
- shader->unbind();
+ cloud_shader->unbind();
}
}
@@ -246,6 +260,53 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
}
}
+void LLDrawPoolWLSky::renderDeferred(S32 pass)
+{
+ if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
+ {
+ return;
+ }
+ LLFastTimer ftm(FTM_RENDER_WL_SKY);
+
+ const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius();
+
+ LLGLSNoFog disableFog;
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ LLGLDisable clip(GL_CLIP_PLANE0);
+
+ gGL.setColorMask(true, false);
+
+ LLGLSquashToFarClip far_clip(glh_get_current_projection());
+
+ renderSkyHaze(camHeightLocal);
+
+ LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+ glPushMatrix();
+
+
+ glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]);
+
+ gDeferredStarProgram.bind();
+ // *NOTE: have to bind a texture here since register combiners blending in
+ // renderStars() requires something to be bound and we might as well only
+ // bind the moon's texture once.
+ gGL.getTexUnit(0)->bind(gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture());
+
+ renderHeavenlyBodies();
+
+ renderStars();
+
+ gDeferredStarProgram.unbind();
+
+ glPopMatrix();
+
+ renderSkyClouds(camHeightLocal);
+
+ gGL.setColorMask(true, true);
+ //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+}
+
void LLDrawPoolWLSky::render(S32 pass)
{
if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
@@ -254,7 +315,7 @@ void LLDrawPoolWLSky::render(S32 pass)
}
LLFastTimer ftm(FTM_RENDER_WL_SKY);
- const F32 camHeightLocal = LLWLParamManager::instance()->getDomeOffset() * LLWLParamManager::instance()->getDomeRadius();
+ const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius();
LLGLSNoFog disableFog;
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index 8ca1ebb942..cd15c991ee 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -44,10 +44,10 @@ public:
/*virtual*/ BOOL isDead() { return FALSE; }
- /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); }
- /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
- /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
- /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
+ /*virtual*/ S32 getNumDeferredPasses() { return 1; }
+ /*virtual*/ void beginDeferredPass(S32 pass);
+ /*virtual*/ void endDeferredPass(S32 pass);
+ /*virtual*/ void renderDeferred(S32 pass);
/*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ void beginRenderPass( S32 pass );
diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp
new file mode 100644
index 0000000000..c2720eaf28
--- /dev/null
+++ b/indra/newview/llenvmanager.cpp
@@ -0,0 +1,684 @@
+/**
+ * @file llenvmanager.cpp
+ * @brief Implementation of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llenvmanager.h"
+
+#include "llagent.h"
+#include "lldaycyclemanager.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewerregion.h"
+#include "llwaterparammanager.h"
+#include "llwlhandlers.h"
+#include "llwlparammanager.h"
+
+std::string LLEnvPrefs::getWaterPresetName() const
+{
+ if (mWaterPresetName.empty())
+ {
+ llwarns << "Water preset name is empty" << llendl;
+ }
+
+ return mWaterPresetName;
+}
+
+std::string LLEnvPrefs::getSkyPresetName() const
+{
+ if (mSkyPresetName.empty())
+ {
+ llwarns << "Sky preset name is empty" << llendl;
+ }
+
+ return mSkyPresetName;
+}
+
+std::string LLEnvPrefs::getDayCycleName() const
+{
+ if (mDayCycleName.empty())
+ {
+ llwarns << "Day cycle name is empty" << llendl;
+ }
+
+ return mDayCycleName;
+}
+
+void LLEnvPrefs::setUseRegionSettings(bool val)
+{
+ mUseRegionSettings = val;
+}
+
+void LLEnvPrefs::setUseWaterPreset(const std::string& name)
+{
+ mUseRegionSettings = false;
+ mWaterPresetName = name;
+}
+
+void LLEnvPrefs::setUseSkyPreset(const std::string& name)
+{
+ mUseRegionSettings = false;
+ mUseDayCycle = false;
+ mSkyPresetName = name;
+}
+
+void LLEnvPrefs::setUseDayCycle(const std::string& name)
+{
+ mUseRegionSettings = false;
+ mUseDayCycle = true;
+ mDayCycleName = name;
+}
+
+//=============================================================================
+LLEnvManagerNew::LLEnvManagerNew()
+{
+ mInterpNextChangeMessage = true;
+
+ // Set default environment settings.
+ mUserPrefs.mUseRegionSettings = true;
+ mUserPrefs.mUseDayCycle = true;
+ mUserPrefs.mWaterPresetName = "Default";
+ mUserPrefs.mSkyPresetName = "Default";
+ mUserPrefs.mDayCycleName = "Default";
+}
+
+bool LLEnvManagerNew::getUseRegionSettings() const
+{
+ return mUserPrefs.getUseRegionSettings();
+}
+
+bool LLEnvManagerNew::getUseDayCycle() const
+{
+ return mUserPrefs.getUseDayCycle();
+}
+
+bool LLEnvManagerNew::getUseFixedSky() const
+{
+ return mUserPrefs.getUseFixedSky();
+}
+
+std::string LLEnvManagerNew::getWaterPresetName() const
+{
+ return mUserPrefs.getWaterPresetName();
+}
+
+std::string LLEnvManagerNew::getSkyPresetName() const
+{
+ return mUserPrefs.getSkyPresetName();
+}
+
+std::string LLEnvManagerNew::getDayCycleName() const
+{
+ return mUserPrefs.getDayCycleName();
+}
+
+const LLEnvironmentSettings& LLEnvManagerNew::getRegionSettings() const
+{
+ return !mNewRegionPrefs.isEmpty() ? mNewRegionPrefs : mCachedRegionPrefs;
+}
+
+void LLEnvManagerNew::setRegionSettings(const LLEnvironmentSettings& new_settings)
+{
+ // Set region settings override that will be used locally
+ // until user either uploads the changes or goes to another region.
+ mNewRegionPrefs = new_settings;
+}
+
+bool LLEnvManagerNew::usePrefs()
+{
+ LL_DEBUGS("Windlight") << "Displaying preferred environment" << LL_ENDL;
+ updateManagersFromPrefs(false);
+ return true;
+}
+
+bool LLEnvManagerNew::useDefaults()
+{
+ bool rslt;
+
+ rslt = useDefaultWater();
+ rslt &= useDefaultSky();
+
+ return rslt;
+}
+
+bool LLEnvManagerNew::useRegionSettings()
+{
+ bool rslt;
+
+ rslt = useRegionSky();
+ rslt &= useRegionWater();
+
+ return rslt;
+}
+
+bool LLEnvManagerNew::useWaterPreset(const std::string& name)
+{
+ LL_DEBUGS("Windlight") << "Displaying water preset " << name << LL_ENDL;
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+ bool rslt = water_mgr.getParamSet(name, water_mgr.mCurParams);
+ llassert(rslt == true);
+ return rslt;
+}
+
+bool LLEnvManagerNew::useWaterParams(const LLSD& params)
+{
+ LL_DEBUGS("Windlight") << "Displaying water params" << LL_ENDL;
+ LLWaterParamManager::instance().mCurParams.setAll(params);
+ return true;
+}
+
+bool LLEnvManagerNew::useSkyPreset(const std::string& name)
+{
+ LLWLParamManager& sky_mgr = LLWLParamManager::instance();
+ LLWLParamSet param_set;
+
+ if (!sky_mgr.getParamSet(LLWLParamKey(name, LLEnvKey::SCOPE_LOCAL), param_set))
+ {
+ llwarns << "No sky preset named " << name << llendl;
+ return false;
+ }
+
+ LL_DEBUGS("Windlight") << "Displaying sky preset " << name << LL_ENDL;
+ sky_mgr.applySkyParams(param_set.getAll());
+ return true;
+}
+
+bool LLEnvManagerNew::useSkyParams(const LLSD& params)
+{
+ LL_DEBUGS("Windlight") << "Displaying sky params" << LL_ENDL;
+ LLWLParamManager::instance().applySkyParams(params);
+ return true;
+}
+
+bool LLEnvManagerNew::useDayCycle(const std::string& name, LLEnvKey::EScope scope)
+{
+ LLSD params;
+
+ if (scope == LLEnvKey::SCOPE_REGION)
+ {
+ LL_DEBUGS("Windlight") << "Displaying region day cycle " << name << LL_ENDL;
+ params = getRegionSettings().getWLDayCycle();
+ }
+ else
+ {
+ LL_DEBUGS("Windlight") << "Displaying local day cycle " << name << LL_ENDL;
+
+ if (!LLDayCycleManager::instance().getPreset(name, params))
+ {
+ llwarns << "No day cycle named " << name << llendl;
+ return false;
+ }
+ }
+
+ bool rslt = LLWLParamManager::instance().applyDayCycleParams(params, scope);
+ llassert(rslt == true);
+ return rslt;
+}
+
+bool LLEnvManagerNew::useDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time /* = 0.5*/)
+{
+ LL_DEBUGS("Windlight") << "Displaying day cycle params" << LL_ENDL;
+ return LLWLParamManager::instance().applyDayCycleParams(params, scope);
+}
+
+void LLEnvManagerNew::setUseRegionSettings(bool val)
+{
+ mUserPrefs.setUseRegionSettings(val);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::setUseWaterPreset(const std::string& name)
+{
+ // *TODO: make sure the preset exists.
+ if (name.empty())
+ {
+ llwarns << "Empty water preset name passed" << llendl;
+ return;
+ }
+
+ mUserPrefs.setUseWaterPreset(name);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::setUseSkyPreset(const std::string& name)
+{
+ // *TODO: make sure the preset exists.
+ if (name.empty())
+ {
+ llwarns << "Empty sky preset name passed" << llendl;
+ return;
+ }
+
+ mUserPrefs.setUseSkyPreset(name);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::setUseDayCycle(const std::string& name)
+{
+ if (!LLDayCycleManager::instance().presetExists(name))
+ {
+ llwarns << "Invalid day cycle name passed" << llendl;
+ return;
+ }
+
+ mUserPrefs.setUseDayCycle(name);
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::loadUserPrefs()
+{
+ // operate on members directly to avoid side effects
+ mUserPrefs.mWaterPresetName = gSavedSettings.getString("WaterPresetName");
+ mUserPrefs.mSkyPresetName = gSavedSettings.getString("SkyPresetName");
+ mUserPrefs.mDayCycleName = gSavedSettings.getString("DayCycleName");
+
+ mUserPrefs.mUseRegionSettings = gSavedSettings.getBOOL("UseEnvironmentFromRegion");
+ mUserPrefs.mUseDayCycle = gSavedSettings.getBOOL("UseDayCycle");
+}
+
+void LLEnvManagerNew::saveUserPrefs()
+{
+ gSavedSettings.setString("WaterPresetName", getWaterPresetName());
+ gSavedSettings.setString("SkyPresetName", getSkyPresetName());
+ gSavedSettings.setString("DayCycleName", getDayCycleName());
+
+ gSavedSettings.setBOOL("UseEnvironmentFromRegion", getUseRegionSettings());
+ gSavedSettings.setBOOL("UseDayCycle", getUseDayCycle());
+
+ mUsePrefsChangeSignal();
+}
+
+void LLEnvManagerNew::setUserPrefs(
+ const std::string& water_preset,
+ const std::string& sky_preset,
+ const std::string& day_cycle_preset,
+ bool use_fixed_sky,
+ bool use_region_settings)
+{
+ // operate on members directly to avoid side effects
+ mUserPrefs.mWaterPresetName = water_preset;
+ mUserPrefs.mSkyPresetName = sky_preset;
+ mUserPrefs.mDayCycleName = day_cycle_preset;
+
+ mUserPrefs.mUseRegionSettings = use_region_settings;
+ mUserPrefs.mUseDayCycle = !use_fixed_sky;
+
+ saveUserPrefs();
+ updateManagersFromPrefs(false);
+}
+
+void LLEnvManagerNew::dumpUserPrefs()
+{
+ LL_DEBUGS("Windlight") << "WaterPresetName: " << gSavedSettings.getString("WaterPresetName") << LL_ENDL;
+ LL_DEBUGS("Windlight") << "SkyPresetName: " << gSavedSettings.getString("SkyPresetName") << LL_ENDL;
+ LL_DEBUGS("Windlight") << "DayCycleName: " << gSavedSettings.getString("DayCycleName") << LL_ENDL;
+
+ LL_DEBUGS("Windlight") << "UseEnvironmentFromRegion: " << gSavedSettings.getBOOL("UseEnvironmentFromRegion") << LL_ENDL;
+ LL_DEBUGS("Windlight") << "UseDayCycle: " << gSavedSettings.getBOOL("UseDayCycle") << LL_ENDL;
+}
+
+void LLEnvManagerNew::dumpPresets()
+{
+ const LLEnvironmentSettings& region_settings = getRegionSettings();
+ std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : "Unknown region";
+
+ // Dump water presets.
+ LL_DEBUGS("Windlight") << "Waters:" << LL_ENDL;
+ if (region_settings.getWaterParams().size() != 0)
+ {
+ LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
+ }
+ LLWaterParamManager::preset_name_list_t water_presets;
+ LLWaterParamManager::instance().getPresetNames(water_presets);
+ for (LLWaterParamManager::preset_name_list_t::const_iterator it = water_presets.begin(); it != water_presets.end(); ++it)
+ {
+ LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
+ }
+
+ // Dump sky presets.
+ LL_DEBUGS("Windlight") << "Skies:" << LL_ENDL;
+ LLWLParamManager::preset_key_list_t sky_preset_keys;
+ LLWLParamManager::instance().getPresetKeys(sky_preset_keys);
+ for (LLWLParamManager::preset_key_list_t::const_iterator it = sky_preset_keys.begin(); it != sky_preset_keys.end(); ++it)
+ {
+ std::string preset_name = it->name;
+ std::string item_title;
+
+ if (it->scope == LLEnvKey::SCOPE_LOCAL) // local preset
+ {
+ item_title = preset_name;
+ }
+ else // region preset
+ {
+ item_title = preset_name + " (" + region_name + ")";
+ }
+ LL_DEBUGS("Windlight") << " - " << item_title << LL_ENDL;
+ }
+
+ // Dump day cycles.
+ LL_DEBUGS("Windlight") << "Days:" << LL_ENDL;
+ const LLSD& cur_region_dc = region_settings.getWLDayCycle();
+ if (cur_region_dc.size() != 0)
+ {
+ LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
+ }
+ LLDayCycleManager::preset_name_list_t days;
+ LLDayCycleManager::instance().getPresetNames(days);
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = days.begin(); it != days.end(); ++it)
+ {
+ LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
+ }
+}
+
+void LLEnvManagerNew::requestRegionSettings()
+{
+ LLEnvironmentRequest::initiate();
+}
+
+bool LLEnvManagerNew::sendRegionSettings(const LLEnvironmentSettings& new_settings)
+{
+ LLSD metadata;
+
+ metadata["regionID"] = gAgent.getRegion()->getRegionID();
+ // add last received update ID to outbound message so simulator can handle concurrent updates
+ metadata["messageID"] = mLastReceivedID;
+
+ return LLEnvironmentApply::initiateRequest(new_settings.makePacket(metadata));
+}
+
+boost::signals2::connection LLEnvManagerNew::setPreferencesChangeCallback(const prefs_change_signal_t::slot_type& cb)
+{
+ return mUsePrefsChangeSignal.connect(cb);
+}
+
+boost::signals2::connection LLEnvManagerNew::setRegionSettingsChangeCallback(const region_settings_change_signal_t::slot_type& cb)
+{
+ return mRegionSettingsChangeSignal.connect(cb);
+}
+
+boost::signals2::connection LLEnvManagerNew::setRegionChangeCallback(const region_change_signal_t::slot_type& cb)
+{
+ return mRegionChangeSignal.connect(cb);
+}
+
+boost::signals2::connection LLEnvManagerNew::setRegionSettingsAppliedCallback(const region_settings_applied_signal_t::slot_type& cb)
+{
+ return mRegionSettingsAppliedSignal.connect(cb);
+}
+
+// static
+bool LLEnvManagerNew::canEditRegionSettings()
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ BOOL owner_or_god = gAgent.isGodlike() || (region && region->getOwner() == gAgent.getID());
+ BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
+
+ LL_DEBUGS("Windlight") << "Can edit region settings: " << (bool) owner_or_god_or_manager << LL_ENDL;
+ return owner_or_god_or_manager;
+}
+
+// static
+const std::string LLEnvManagerNew::getScopeString(LLEnvKey::EScope scope)
+{
+ switch(scope)
+ {
+ case LLEnvKey::SCOPE_LOCAL:
+ return LLTrans::getString("LocalSettings");
+ case LLEnvKey::SCOPE_REGION:
+ return LLTrans::getString("RegionSettings");
+ default:
+ return " (?)";
+ }
+}
+
+void LLEnvManagerNew::onRegionCrossing()
+{
+ LL_DEBUGS("Windlight") << "Crossed region" << LL_ENDL;
+ onRegionChange(true);
+}
+
+void LLEnvManagerNew::onTeleport()
+{
+ LL_DEBUGS("Windlight") << "Teleported" << LL_ENDL;
+ onRegionChange(false);
+}
+
+void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content)
+{
+ // If the message was valid, grab the UUID from it and save it for next outbound update message.
+ mLastReceivedID = content[0]["messageID"].asUUID();
+
+ // Refresh cached region settings.
+ LL_DEBUGS("Windlight") << "Caching region environment settings: " << content << LL_ENDL;
+ F32 sun_hour = 0; // *TODO
+ LLEnvironmentSettings new_settings(content[1], content[2], content[3], sun_hour);
+ mCachedRegionPrefs = new_settings;
+
+ // Load region sky presets.
+ LLWLParamManager::instance().refreshRegionPresets();
+
+ // If using server settings, update managers.
+ if (getUseRegionSettings())
+ {
+ updateManagersFromPrefs(mInterpNextChangeMessage);
+ }
+
+ // Let interested parties know about the region settings update.
+ mRegionSettingsChangeSignal();
+
+ // reset
+ mInterpNextChangeMessage = false;
+}
+
+void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok)
+{
+ LL_DEBUGS("Windlight") << "Applying region settings " << (ok ? "succeeded" : "failed") << LL_ENDL;
+
+ // Clear locally modified region settings because they have just been uploaded.
+ mNewRegionPrefs.clear();
+
+ mRegionSettingsAppliedSignal(ok);
+}
+
+//-- private methods ----------------------------------------------------------
+
+// virtual
+void LLEnvManagerNew::initSingleton()
+{
+ LL_DEBUGS("Windlight") << "Initializing LLEnvManagerNew" << LL_ENDL;
+
+ loadUserPrefs();
+}
+
+void LLEnvManagerNew::updateSkyFromPrefs()
+{
+ bool success = true;
+
+ // Sync sky with user prefs.
+ if (getUseRegionSettings()) // apply region-wide settings
+ {
+ success = useRegionSky();
+ }
+ else // apply user-specified settings
+ {
+ if (getUseDayCycle())
+ {
+ success = useDayCycle(getDayCycleName(), LLEnvKey::SCOPE_LOCAL);
+ }
+ else
+ {
+ success = useSkyPreset(getSkyPresetName());
+ }
+ }
+
+ // If something went wrong, fall back to defaults.
+ if (!success)
+ {
+ // *TODO: fix user prefs
+ useDefaultSky();
+ }
+}
+
+void LLEnvManagerNew::updateWaterFromPrefs(bool interpolate)
+{
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+ LLSD target_water_params;
+
+ // Determine new water settings based on user prefs.
+
+ {
+ // Fall back to default water.
+ LLWaterParamSet default_water;
+ water_mgr.getParamSet("Default", default_water);
+ target_water_params = default_water.getAll();
+ }
+
+ if (getUseRegionSettings())
+ {
+ // *TODO: make sure whether region settings belong to the current region?
+ const LLSD& region_water_params = getRegionSettings().getWaterParams();
+ if (region_water_params.size() != 0) // region has no water settings
+ {
+ LL_DEBUGS("Windlight") << "Applying region water" << LL_ENDL;
+ target_water_params = region_water_params;
+ }
+ else
+ {
+ LL_DEBUGS("Windlight") << "Applying default water" << LL_ENDL;
+ }
+ }
+ else
+ {
+ std::string water = getWaterPresetName();
+ LL_DEBUGS("Windlight") << "Applying water preset [" << water << "]" << LL_ENDL;
+ LLWaterParamSet params;
+ if (!water_mgr.getParamSet(water, params))
+ {
+ llwarns << "No water preset named " << water << ", falling back to defaults" << llendl;
+ water_mgr.getParamSet("Default", params);
+
+ // *TODO: Fix user preferences accordingly.
+ }
+ target_water_params = params.getAll();
+ }
+
+ // Sync water with user prefs.
+ water_mgr.applyParams(target_water_params, interpolate);
+}
+
+void LLEnvManagerNew::updateManagersFromPrefs(bool interpolate)
+{
+ // Apply water settings.
+ updateWaterFromPrefs(interpolate);
+
+ // Apply sky settings.
+ updateSkyFromPrefs();
+}
+
+bool LLEnvManagerNew::useRegionSky()
+{
+ const LLEnvironmentSettings& region_settings = getRegionSettings();
+
+ // If region is set to defaults,
+ if (region_settings.getSkyMap().size() == 0)
+ {
+ // well... apply the default sky settings.
+ useDefaultSky();
+ return true;
+ }
+
+ // *TODO: Support fixed sky from region.
+
+ // Otherwise apply region day cycle.
+ LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
+ return useDayCycleParams(
+ region_settings.getWLDayCycle(),
+ LLEnvKey::SCOPE_REGION,
+ region_settings.getDayTime());
+}
+
+bool LLEnvManagerNew::useRegionWater()
+{
+ const LLEnvironmentSettings& region_settings = getRegionSettings();
+ const LLSD& region_water = region_settings.getWaterParams();
+
+ // If region is set to defaults,
+ if (region_water.size() == 0)
+ {
+ // well... apply the default water settings.
+ return useDefaultWater();
+ }
+
+ // Otherwise apply region water.
+ LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
+ return useWaterParams(region_water);
+}
+
+bool LLEnvManagerNew::useDefaultSky()
+{
+ return useDayCycle("Default", LLEnvKey::SCOPE_LOCAL);
+}
+
+bool LLEnvManagerNew::useDefaultWater()
+{
+ return useWaterPreset("Default");
+}
+
+
+void LLEnvManagerNew::onRegionChange(bool interpolate)
+{
+ // Avoid duplicating region setting requests
+ // by checking whether the region is actually changing.
+ LLViewerRegion* regionp = gAgent.getRegion();
+ LLUUID region_uuid = regionp ? regionp->getRegionID() : LLUUID::null;
+ if (region_uuid == mCurRegionUUID)
+ {
+ return;
+ }
+
+ // Clear locally modified region settings.
+ mNewRegionPrefs.clear();
+
+ // *TODO: clear environment settings of the previous region?
+
+ // Request environment settings of the new region.
+ LL_DEBUGS("Windlight") << "New viewer region: " << region_uuid << LL_ENDL;
+ mCurRegionUUID = region_uuid;
+ mInterpNextChangeMessage = interpolate;
+ requestRegionSettings();
+
+ // Let interested parties know agent region has been changed.
+ mRegionChangeSignal();
+}
diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h
new file mode 100644
index 0000000000..96af102c1a
--- /dev/null
+++ b/indra/newview/llenvmanager.h
@@ -0,0 +1,283 @@
+/**
+ * @file llenvmanager.h
+ * @brief Declaration of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLENVMANAGER_H
+#define LL_LLENVMANAGER_H
+
+#include "llmemory.h"
+#include "llsd.h"
+
+class LLWLParamManager;
+class LLWaterParamManager;
+class LLWLAnimator;
+
+// generic key
+struct LLEnvKey
+{
+public:
+ // Note: enum ordering is important; for example, a region-level floater (1) will see local and region (all values that are <=)
+ typedef enum e_scope
+ {
+ SCOPE_LOCAL, // 0
+ SCOPE_REGION//, // 1
+ // SCOPE_ESTATE, // 2
+ // etc.
+ } EScope;
+};
+
+class LLEnvironmentSettings
+{
+public:
+ LLEnvironmentSettings() :
+ mWLDayCycle(LLSD::emptyMap()),
+ mSkyMap(LLSD::emptyMap()),
+ mWaterParams(LLSD::emptyMap()),
+ mDayTime(0.f)
+ {}
+ LLEnvironmentSettings(const LLSD& dayCycle, const LLSD& skyMap, const LLSD& waterParams, F64 dayTime) :
+ mWLDayCycle(dayCycle),
+ mSkyMap(skyMap),
+ mWaterParams(waterParams),
+ mDayTime(dayTime)
+ {}
+ ~LLEnvironmentSettings() {}
+
+ void saveParams(const LLSD& dayCycle, const LLSD& skyMap, const LLSD& waterParams, F64 dayTime)
+ {
+ mWLDayCycle = dayCycle;
+ mSkyMap = skyMap;
+ mWaterParams = waterParams;
+ mDayTime = dayTime;
+ }
+
+ const LLSD& getWLDayCycle() const
+ {
+ return mWLDayCycle;
+ }
+
+ const LLSD& getWaterParams() const
+ {
+ return mWaterParams;
+ }
+
+ const LLSD& getSkyMap() const
+ {
+ return mSkyMap;
+ }
+
+ F64 getDayTime() const
+ {
+ return mDayTime;
+ }
+
+ bool isEmpty() const
+ {
+ return mWLDayCycle.size() == 0;
+ }
+
+ void clear()
+ {
+ *this = LLEnvironmentSettings();
+ }
+
+ LLSD makePacket(const LLSD& metadata) const
+ {
+ LLSD full_packet = LLSD::emptyArray();
+
+ // 0: metadata
+ full_packet.append(metadata);
+
+ // 1: day cycle
+ full_packet.append(mWLDayCycle);
+
+ // 2: map of sky setting names to sky settings (as LLSD)
+ full_packet.append(mSkyMap);
+
+ // 3: water params
+ full_packet.append(mWaterParams);
+
+ return full_packet;
+ }
+
+private:
+ LLSD mWLDayCycle, mWaterParams, mSkyMap;
+ F64 mDayTime;
+};
+
+/**
+ * User environment preferences.
+ */
+class LLEnvPrefs
+{
+public:
+ LLEnvPrefs() : mUseRegionSettings(true), mUseDayCycle(true) {}
+
+ bool getUseRegionSettings() const { return mUseRegionSettings; }
+ bool getUseDayCycle() const { return mUseDayCycle; }
+ bool getUseFixedSky() const { return !getUseDayCycle(); }
+
+ std::string getWaterPresetName() const;
+ std::string getSkyPresetName() const;
+ std::string getDayCycleName() const;
+
+ void setUseRegionSettings(bool val);
+ void setUseWaterPreset(const std::string& name);
+ void setUseSkyPreset(const std::string& name);
+ void setUseDayCycle(const std::string& name);
+
+ bool mUseRegionSettings;
+ bool mUseDayCycle;
+ std::string mWaterPresetName;
+ std::string mSkyPresetName;
+ std::string mDayCycleName;
+};
+
+/**
+ * Setting:
+ * 1. Use region settings.
+ * 2. Use my setting: <water preset> + <fixed_sky>|<day_cycle>
+ */
+class LLEnvManagerNew : public LLSingleton<LLEnvManagerNew>
+{
+ LOG_CLASS(LLEnvManagerNew);
+public:
+ typedef boost::signals2::signal<void()> prefs_change_signal_t;
+ typedef boost::signals2::signal<void()> region_settings_change_signal_t;
+ typedef boost::signals2::signal<void()> region_change_signal_t;
+ typedef boost::signals2::signal<void(bool)> region_settings_applied_signal_t;
+
+ LLEnvManagerNew();
+
+ // getters to access user env. preferences
+ bool getUseRegionSettings() const;
+ bool getUseDayCycle() const;
+ bool getUseFixedSky() const;
+ std::string getWaterPresetName() const;
+ std::string getSkyPresetName() const;
+ std::string getDayCycleName() const;
+
+ /// @return cached env. settings of the current region.
+ const LLEnvironmentSettings& getRegionSettings() const;
+
+ /**
+ * Set new region settings without uploading them to the region.
+ *
+ * The override will be reset when the changes are applied to the region (=uploaded)
+ * or user teleports to another region.
+ */
+ void setRegionSettings(const LLEnvironmentSettings& new_settings);
+
+ // Change environment w/o changing user preferences.
+ bool usePrefs();
+ bool useDefaults();
+ bool useRegionSettings();
+ bool useWaterPreset(const std::string& name);
+ bool useWaterParams(const LLSD& params);
+ bool useSkyPreset(const std::string& name);
+ bool useSkyParams(const LLSD& params);
+ bool useDayCycle(const std::string& name, LLEnvKey::EScope scope);
+ bool useDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time = 0.5);
+
+ // setters for user env. preferences
+ void setUseRegionSettings(bool val);
+ void setUseWaterPreset(const std::string& name);
+ void setUseSkyPreset(const std::string& name);
+ void setUseDayCycle(const std::string& name);
+ void setUserPrefs(
+ const std::string& water_preset,
+ const std::string& sky_preset,
+ const std::string& day_cycle_preset,
+ bool use_fixed_sky,
+ bool use_region_settings);
+
+ // debugging methods
+ void dumpUserPrefs();
+ void dumpPresets();
+
+ // Misc.
+ void requestRegionSettings();
+ bool sendRegionSettings(const LLEnvironmentSettings& new_settings);
+ boost::signals2::connection setPreferencesChangeCallback(const prefs_change_signal_t::slot_type& cb);
+ boost::signals2::connection setRegionSettingsChangeCallback(const region_settings_change_signal_t::slot_type& cb);
+ boost::signals2::connection setRegionChangeCallback(const region_change_signal_t::slot_type& cb);
+ boost::signals2::connection setRegionSettingsAppliedCallback(const region_settings_applied_signal_t::slot_type& cb);
+
+ static bool canEditRegionSettings(); /// @return true if we have access to editing region environment
+ static const std::string getScopeString(LLEnvKey::EScope scope);
+
+ // Public callbacks.
+ void onRegionCrossing();
+ void onTeleport();
+ void onRegionSettingsResponse(const LLSD& content);
+ void onRegionSettingsApplyResponse(bool ok);
+
+private:
+ friend class LLSingleton<LLEnvManagerNew>;
+ /*virtual*/ void initSingleton();
+
+ void loadUserPrefs();
+ void saveUserPrefs();
+
+ void updateSkyFromPrefs();
+ void updateWaterFromPrefs(bool interpolate);
+ void updateManagersFromPrefs(bool interpolate);
+
+ bool useRegionSky();
+ bool useRegionWater();
+
+ bool useDefaultSky();
+ bool useDefaultWater();
+
+ void onRegionChange(bool interpolate);
+
+ /// Emitted when user environment preferences change.
+ prefs_change_signal_t mUsePrefsChangeSignal;
+
+ /// Emitted when region environment settings update comes.
+ region_settings_change_signal_t mRegionSettingsChangeSignal;
+
+ /// Emitted when agent region changes. Move to LLAgent?
+ region_change_signal_t mRegionChangeSignal;
+
+ /// Emitted when agent region changes. Move to LLAgent?
+ region_settings_applied_signal_t mRegionSettingsAppliedSignal;
+
+ LLEnvPrefs mUserPrefs; /// User environment preferences.
+ LLEnvironmentSettings mCachedRegionPrefs; /// Cached region environment settings.
+ LLEnvironmentSettings mNewRegionPrefs; /// Not-yet-uploaded modified region env. settings.
+ bool mInterpNextChangeMessage; /// Interpolate env. settings on next region change.
+ LLUUID mCurRegionUUID; /// To avoid duplicated region env. settings requests.
+ LLUUID mLastReceivedID; /// Id of last received region env. settings.
+};
+
+#endif // LL_LLENVMANAGER_H
+
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 5398c13c44..b6566fcbd0 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -165,6 +165,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mIndexInTex = 0;
mTexture = NULL;
mTEOffset = -1;
+ mTextureIndex = 255;
setDrawable(drawablep);
mVObjp = objp;
@@ -364,14 +365,7 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
//allocate vertices in blocks of 4 for alignment
num_vertices = (num_vertices + 0x3) & ~0x3;
}
- else
- {
- if (mDrawablep->getVOVolume())
- {
- llerrs << "WTF?" << llendl;
- }
- }
-
+
if (mGeomCount != num_vertices ||
mIndicesCount != num_indices)
{
@@ -393,6 +387,26 @@ void LLFace::setGeomIndex(U16 idx)
}
}
+void LLFace::setTextureIndex(U8 index)
+{
+ if (index != mTextureIndex)
+ {
+ mTextureIndex = index;
+
+ if (mTextureIndex != 255)
+ {
+ mDrawablep->setState(LLDrawable::REBUILD_POSITION);
+ }
+ else
+ {
+ if (mDrawInfo && !mDrawInfo->mTextureList.empty())
+ {
+ llerrs << "Face with no texture index references indexed texture draw info." << llendl;
+ }
+ }
+ }
+}
+
void LLFace::setIndicesIndex(S32 idx)
{
if (mIndicesIndex != idx)
@@ -415,11 +429,11 @@ U16 LLFace::getGeometryAvatar(
if (mVertexBuffer.notNull())
{
- mVertexBuffer->getVertexStrider (vertices, mGeomIndex);
- mVertexBuffer->getNormalStrider (normals, mGeomIndex);
- mVertexBuffer->getTexCoord0Strider (tex_coords, mGeomIndex);
- mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex);
- mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex);
+ mVertexBuffer->getVertexStrider (vertices, mGeomIndex, mGeomCount);
+ mVertexBuffer->getNormalStrider (normals, mGeomIndex, mGeomCount);
+ mVertexBuffer->getTexCoord0Strider (tex_coords, mGeomIndex, mGeomCount);
+ mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex, mGeomCount);
+ mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex, mGeomCount);
}
return mGeomIndex;
@@ -432,17 +446,17 @@ U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no
if (mVertexBuffer.notNull())
{
- mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
+ mVertexBuffer->getVertexStrider(vertices, mGeomIndex, mGeomCount);
if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
{
- mVertexBuffer->getNormalStrider(normals, mGeomIndex);
+ mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount);
}
if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0))
{
- mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
+ mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
}
- mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
}
return mGeomIndex;
@@ -679,6 +693,19 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of
}
+bool less_than_max_mag(const LLVector4a& vec)
+{
+ LLVector4a MAX_MAG;
+ MAX_MAG.splat(1024.f*1024.f);
+
+ LLVector4a val;
+ val.setAbs(vec);
+
+ S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7;
+
+ return lt == 0x7;
+}
+
BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume)
{
@@ -713,6 +740,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
min = face.mExtents[0];
max = face.mExtents[1];
+ llassert(less_than_max_mag(min));
+ llassert(less_than_max_mag(max));
//min, max are in volume space, convert to drawable render space
LLVector4a center;
@@ -724,6 +753,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
size.setSub(max, min);
size.mul(0.5f);
+ llassert(less_than_max_mag(min));
+ llassert(less_than_max_mag(max));
+
if (!global_volume)
{
//VECTORIZE THIS
@@ -761,6 +793,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
newMin = newMax = center;
+ llassert(less_than_max_mag(center));
+
for (U32 i = 0; i < 4; i++)
{
LLVector4a delta;
@@ -772,6 +806,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
newMin.setMin(newMin,min);
newMax.setMax(newMax,max);
+
+ llassert(less_than_max_mag(newMin));
+ llassert(less_than_max_mag(newMax));
}
if (!mDrawablep->isActive())
@@ -780,14 +817,22 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
newMin.add(offset);
newMax.add(offset);
+
+ llassert(less_than_max_mag(newMin));
+ llassert(less_than_max_mag(newMax));
}
t.setAdd(newMin, newMax);
t.mul(0.5f);
+ llassert(less_than_max_mag(t));
+
//VECTORIZE THIS
mCenterLocal.set(t.getF32ptr());
+ llassert(less_than_max_mag(newMin));
+ llassert(less_than_max_mag(newMax));
+
t.setSub(newMax,newMin);
mBoundingSphereRadius = t.getLength3().getF32()*0.5f;
@@ -1078,27 +1123,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
const LLTextureEntry *tep = mVObjp->getTE(f);
const U8 bump_code = tep ? tep->getBumpmap() : 0;
- if (rebuild_pos)
- {
- mVertexBuffer->getVertexStrider(vert, mGeomIndex);
- vertices = (LLVector4a*) vert.get();
- }
- if (rebuild_normal)
- {
- mVertexBuffer->getNormalStrider(norm, mGeomIndex);
- normals = (LLVector4a*) norm.get();
- }
- if (rebuild_binormal)
- {
- mVertexBuffer->getBinormalStrider(binorm, mGeomIndex);
- binormals = (LLVector4a*) binorm.get();
- }
- if (rebuild_weights)
- {
- mVertexBuffer->getWeight4Strider(wght, mGeomIndex);
- weights = (LLVector4a*) wght.get();
- }
-
F32 tcoord_xoffset = 0.f ;
F32 tcoord_yoffset = 0.f ;
F32 tcoord_xscale = 1.f ;
@@ -1107,12 +1131,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (rebuild_tcoord)
{
- mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
- if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
- {
- mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
- }
-
in_atlas = isAtlasInUse() ;
if(in_atlas)
{
@@ -1125,11 +1143,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
tcoord_yscale = tmp->mV[1] ;
}
}
- if (rebuild_color)
- {
- mVertexBuffer->getColorStrider(colors, mGeomIndex);
- }
-
+
BOOL is_static = mDrawablep->isStatic();
BOOL is_global = is_static;
@@ -1168,7 +1182,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
// INDICES
if (full_rebuild)
{
- mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount, true);
+
__m128i* dst = (__m128i*) indicesp.get();
__m128i* src = (__m128i*) vf.mIndices;
__m128i offset = _mm_set1_epi16(index_offset);
@@ -1185,6 +1200,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
indicesp[i] = vf.mIndices[i]+index_offset;
}
+
+ mVertexBuffer->setBuffer(0);
}
LLMatrix4a mat_normal;
@@ -1330,6 +1347,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (!in_atlas && !do_bump)
{ //not in atlas or not bump mapped, might be able to do a cheap update
+ mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
+
if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
{
if (!do_tex_mat)
@@ -1402,9 +1421,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
}
+
+ mVertexBuffer->setBuffer(0);
}
else
{ //either bump mapped or in atlas, just do the whole expensive loop
+ mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, true);
+
+ std::vector<LLVector2> bump_tc;
+
for (S32 i = 0; i < num_vertices; i++)
{
LLVector2 tc(vf.mTexCoords[i]);
@@ -1535,8 +1560,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
*tex_coords++ = tc;
-
- if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
+ if (do_bump)
+ {
+ bump_tc.push_back(tc);
+ }
+ }
+
+ mVertexBuffer->setBuffer(0);
+
+
+ if (do_bump)
+ {
+ mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, true);
+
+ for (S32 i = 0; i < num_vertices; i++)
{
LLVector4a tangent;
tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);
@@ -1558,16 +1595,22 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
binormal.normalize3fast();
+ LLVector2 tc = bump_tc[i];
tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
*tex_coords2++ = tc;
- }
+ }
+
+ mVertexBuffer->setBuffer(0);
}
}
}
if (rebuild_pos)
{
+ mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, true);
+ vertices = (LLVector4a*) vert.get();
+
LLMatrix4a mat_vert;
mat_vert.loadu(mat_vert_in);
@@ -1580,10 +1623,28 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
mat_vert.affineTransform(*src++, *dst++);
}
while(dst < end);
+
+ F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0);
+ F32 *index_dst = (F32*) vertices;
+ F32 *index_end = (F32*) end;
+
+ index_dst += 3;
+ index_end += 3;
+ do
+ {
+ *index_dst = index;
+ index_dst += 4;
+ }
+ while (index_dst < index_end);
+
+ mVertexBuffer->setBuffer(0);
}
if (rebuild_normal)
{
+ mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, true);
+ normals = (LLVector4a*) norm.get();
+
for (S32 i = 0; i < num_vertices; i++)
{
LLVector4a normal;
@@ -1591,10 +1652,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
normal.normalize3fast();
normals[i] = normal;
}
+
+ mVertexBuffer->setBuffer(0);
}
if (rebuild_binormal)
{
+ mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, true);
+ binormals = (LLVector4a*) binorm.get();
+
for (S32 i = 0; i < num_vertices; i++)
{
LLVector4a binormal;
@@ -1602,15 +1668,22 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
binormal.normalize3fast();
binormals[i] = binormal;
}
+
+ mVertexBuffer->setBuffer(0);
}
if (rebuild_weights && vf.mWeights)
{
+ mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount, true);
+ weights = (LLVector4a*) wght.get();
LLVector4a::memcpyNonAliased16((F32*) weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32));
+ mVertexBuffer->setBuffer(0);
}
if (rebuild_color)
{
+ mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount, true);
+
LLVector4a src;
U32 vec[4];
@@ -1629,6 +1702,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
dst[i] = src;
}
+
+ mVertexBuffer->setBuffer(0);
}
if (rebuild_tcoord)
@@ -2045,13 +2120,13 @@ S32 LLFace::getColors(LLStrider<LLColor4U> &colors)
}
// llassert(mGeomIndex >= 0);
- mVertexBuffer->getColorStrider(colors, mGeomIndex);
+ mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount);
return mGeomIndex;
}
S32 LLFace::getIndices(LLStrider<U16> &indicesp)
{
- mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
+ mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount);
llassert(indicesp[0] != indicesp[1]);
return mIndicesIndex;
}
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index b2170c4cf3..b5eaeecd60 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -94,6 +94,8 @@ public:
U16 getGeomCount() const { return mGeomCount; } // vertex count for this face
U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool
U16 getGeomStart() const { return mGeomIndex; } // index into draw pool
+ void setTextureIndex(U8 index);
+ U8 getTextureIndex() const { return mTextureIndex; }
void setTexture(LLViewerTexture* tex) ;
void switchTexture(LLViewerTexture* new_texture);
void dirtyTexture();
@@ -262,6 +264,7 @@ private:
U16 mGeomCount; // vertex count for this face
U16 mGeomIndex; // index into draw pool
+ U8 mTextureIndex; // index of texture channel to use for pseudo-atlasing
U32 mIndicesCount;
U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!)
S32 mIndexInTex ;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 3bdab75acf..83844048d1 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -765,7 +765,7 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("OpenGLPre30");
}
- if (gGLManager.mNumTextureUnits <= 8)
+ if (gGLManager.mNumTextureImageUnits <= 8)
{
maskFeatures("TexUnit8orLess");
}
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
index cd5e779c4d..a29ccf2b6d 100644
--- a/indra/newview/llfilteredwearablelist.cpp
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -31,6 +31,7 @@
#include "llinventoryfunctions.h"
#include "llinventoryitemslist.h"
#include "llinventorymodel.h"
+#include "llviewerinventory.h"
LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector)
diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp
index 2c4153688a..a9f52282a5 100644
--- a/indra/newview/llfirstuse.cpp
+++ b/indra/newview/llfirstuse.cpp
@@ -131,7 +131,7 @@ void LLFirstUse::notMoving(bool enable)
// static
void LLFirstUse::viewPopup(bool enable)
{
- firstUseNotification("FirstViewPopup", enable, "HintView", LLSD(), LLSD().with("target", "view_popup").with("direction", "right"));
+// firstUseNotification("FirstViewPopup", enable, "HintView", LLSD(), LLSD().with("target", "view_popup").with("direction", "right"));
}
// static
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 3d1650d2f5..32a533570a 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -366,7 +366,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
LLFastTimer ftm(FTM_DO_FLEXIBLE_UPDATE);
LLVolume* volume = mVO->getVolume();
LLPath *path = &volume->getPath();
- if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) // if its uninitialized but not visible, what then? - Nyx
+ if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())
{
mVO->markForUpdate(TRUE);
if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0))
@@ -375,7 +375,11 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
}
}
- llassert_always(mInitialized);
+ if(!mInitialized)
+ {
+ //the object is not visible
+ return ;
+ }
S32 num_sections = 1 << mSimulateRes;
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index c95b046707..c6743ca13b 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -55,6 +55,7 @@
#include "llrender.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
+#include "lltrans.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -457,7 +458,7 @@ void LLFloaterAuction::onClickSellToAnyone(void* data)
LLSD args;
args["LAND_SIZE"] = llformat("%d", area);
args["SALE_PRICE"] = llformat("%d", sale_price);
- args["NAME"] = "Anyone";
+ args["NAME"] = LLTrans::getString("Anyone");
LLNotification::Params params("ConfirmLandSaleChange"); // Re-use existing dialog
params.substitutions(args)
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 50b19a4221..610142b5a9 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -461,15 +461,15 @@ void LLFloaterBuyLandUI::updateParcelInfo()
if (!authorizedBuyer.isNull() && buyer != authorizedBuyer)
{
- // Maybe the parcel is set for sale to a group we are in.
- bool authorized_group =
- gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_DEED)
- && gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_SET_SALE_INFO);
-
- if (!authorized_group)
- {
- mCannotBuyReason = getString("set_to_sell_to_other");
- return;
+ // Maybe the parcel is set for sale to a group we are in.
+ bool authorized_group =
+ gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_DEED)
+ && gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_SET_SALE_INFO);
+
+ if (!authorized_group)
+ {
+ mCannotBuyReason = getString("set_to_sell_to_other");
+ return;
}
}
}
diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp
deleted file mode 100644
index 22816ee802..0000000000
--- a/indra/newview/llfloaterdaycycle.cpp
+++ /dev/null
@@ -1,531 +0,0 @@
-/**
- * @file llfloaterdaycycle.cpp
- * @brief LLFloaterDayCycle class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterdaycycle.h"
-
-#include "pipeline.h"
-#include "llsky.h"
-
-#include "llsliderctrl.h"
-#include "llmultislider.h"
-#include "llmultisliderctrl.h"
-#include "llspinctrl.h"
-#include "llcheckboxctrl.h"
-#include "lluictrlfactory.h"
-#include "llviewercamera.h"
-#include "llcombobox.h"
-#include "lllineeditor.h"
-#include "llwlanimator.h"
-
-#include "v4math.h"
-#include "llviewerdisplay.h"
-#include "llviewercontrol.h"
-#include "llviewerwindow.h"
-
-#include "llwlparamset.h"
-#include "llwlparammanager.h"
-#include "llpostprocess.h"
-#include "llfloaterwindlight.h"
-
-
-std::map<std::string, LLWLSkyKey> LLFloaterDayCycle::sSliderToKey;
-const F32 LLFloaterDayCycle::sHoursPerDay = 24.0f;
-
-LLFloaterDayCycle::LLFloaterDayCycle(const LLSD& key)
-: LLFloater(key)
-{
-}
-
-BOOL LLFloaterDayCycle::postBuild()
-{
- // add the combo boxes
- LLComboBox* keyCombo = getChild<LLComboBox>("WLKeyPresets");
-
- if(keyCombo != NULL)
- {
- keyCombo->removeall();
- std::map<std::string, LLWLParamSet>::iterator mIt =
- LLWLParamManager::instance()->mParamList.begin();
- for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++)
- {
- keyCombo->add(std::string(mIt->first));
- }
-
- // set defaults on combo boxes
- keyCombo->selectFirstItem();
- }
-
- // add the time slider
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLTimeSlider");
-
- sldr->addSlider();
-
- // load it up
- initCallbacks();
-
- syncMenu();
- syncSliderTrack();
-
- return TRUE;
-}
-
-LLFloaterDayCycle::~LLFloaterDayCycle()
-{
-}
-
-void LLFloaterDayCycle::initCallbacks(void)
-{
- // WL Day Cycle
- getChild<LLUICtrl>("WLTimeSlider")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeSliderMoved, this, _1));
- getChild<LLUICtrl>("WLDayCycleKeys")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeMoved, this, _1));
- getChild<LLUICtrl>("WLCurKeyHour")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeChanged, this, _1));
- getChild<LLUICtrl>("WLCurKeyMin")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeChanged, this, _1));
- getChild<LLUICtrl>("WLKeyPresets")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyPresetChanged, this, _1));
-
- getChild<LLUICtrl>("WLLengthOfDayHour")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeRateChanged, this, _1));
- getChild<LLUICtrl>("WLLengthOfDayMin")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeRateChanged, this, _1));
- getChild<LLUICtrl>("WLLengthOfDaySec")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeRateChanged, this, _1));
- getChild<LLUICtrl>("WLUseLindenTime")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onUseLindenTime, this, _1));
- getChild<LLUICtrl>("WLAnimSky")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onRunAnimSky, this, _1));
- getChild<LLUICtrl>("WLStopAnimSky")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onStopAnimSky, this, _1));
-
- getChild<LLUICtrl>("WLLoadDayCycle")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onLoadDayCycle, this, _1));
- getChild<LLUICtrl>("WLSaveDayCycle")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onSaveDayCycle, this, _1));
-
- getChild<LLUICtrl>("WLAddKey")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onAddKey, this, _1));
- getChild<LLUICtrl>("WLDeleteKey")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onDeleteKey, this, _1));
-}
-
-void LLFloaterDayCycle::syncMenu()
-{
-// std::map<std::string, LLVector4> & currentParams = LLWLParamManager::instance()->mCurParams.mParamValues;
-
- // set time
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLTimeSlider");
- sldr->setCurSliderValue((F32)LLWLParamManager::instance()->mAnimator.getDayTime() * sHoursPerDay);
-
- LLSpinCtrl* secSpin = getChild<LLSpinCtrl>("WLLengthOfDaySec");
- LLSpinCtrl* minSpin = getChild<LLSpinCtrl>("WLLengthOfDayMin");
- LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>("WLLengthOfDayHour");
-
- F32 curRate;
- F32 hours, min, sec;
-
- // get the current rate
- curRate = LLWLParamManager::instance()->mDay.mDayRate;
- hours = (F32)((int)(curRate / 60 / 60));
- curRate -= (hours * 60 * 60);
- min = (F32)((int)(curRate / 60));
- curRate -= (min * 60);
- sec = curRate;
-
- hourSpin->setValue(hours);
- minSpin->setValue(min);
- secSpin->setValue(sec);
-
- // turn off Use Estate Time button if it's already being used
- if( LLWLParamManager::instance()->mAnimator.mUseLindenTime == true)
- {
- getChildView("WLUseLindenTime")->setEnabled(FALSE);
- }
- else
- {
- getChildView("WLUseLindenTime")->setEnabled(TRUE);
- }
-}
-
-void LLFloaterDayCycle::syncSliderTrack()
-{
- // clear the slider
- LLMultiSliderCtrl* kSldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
-
- kSldr->clear();
- sSliderToKey.clear();
-
- // add sliders
- std::map<F32, std::string>::iterator mIt =
- LLWLParamManager::instance()->mDay.mTimeMap.begin();
- for(; mIt != LLWLParamManager::instance()->mDay.mTimeMap.end(); mIt++)
- {
- addSliderKey(mIt->first * sHoursPerDay, mIt->second);
- }
-}
-
-void LLFloaterDayCycle::syncTrack()
-{
- // if no keys, do nothing
- if(sSliderToKey.size() == 0)
- {
- return;
- }
-
- LLMultiSliderCtrl* sldr;
- sldr = getChild<LLMultiSliderCtrl>(
- "WLDayCycleKeys");
- llassert_always(sSliderToKey.size() == sldr->getValue().size());
-
- LLMultiSliderCtrl* tSldr;
- tSldr = getChild<LLMultiSliderCtrl>(
- "WLTimeSlider");
-
- // create a new animation track
- LLWLParamManager::instance()->mDay.clearKeys();
-
- // add the keys one by one
- std::map<std::string, LLWLSkyKey>::iterator mIt = sSliderToKey.begin();
- for(; mIt != sSliderToKey.end(); mIt++)
- {
- LLWLParamManager::instance()->mDay.addKey(mIt->second.time / sHoursPerDay,
- mIt->second.presetName);
- }
-
- // set the param manager's track to the new one
- LLWLParamManager::instance()->resetAnimator(
- tSldr->getCurSliderValue() / sHoursPerDay, false);
-
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
-}
-
-void LLFloaterDayCycle::onRunAnimSky(LLUICtrl* ctrl)
-{
- // if no keys, do nothing
- if(sSliderToKey.size() == 0)
- {
- return;
- }
-
- LLMultiSliderCtrl* sldr;
- sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
- llassert_always(sSliderToKey.size() == sldr->getValue().size());
-
- LLMultiSliderCtrl* tSldr;
- tSldr = getChild<LLMultiSliderCtrl>("WLTimeSlider");
-
- // turn off linden time
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- // set the param manager's track to the new one
- LLWLParamManager::instance()->resetAnimator(
- tSldr->getCurSliderValue() / sHoursPerDay, true);
-
- llassert_always(LLWLParamManager::instance()->mAnimator.mTimeTrack.size() == sldr->getValue().size());
-}
-
-void LLFloaterDayCycle::onStopAnimSky(LLUICtrl* ctrl)
-{
- // if no keys, do nothing
- if(sSliderToKey.size() == 0) {
- return;
- }
-
- // turn off animation and using linden time
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-}
-
-void LLFloaterDayCycle::onUseLindenTime(LLUICtrl* ctrl)
-{
- LLComboBox* box = getChild<LLComboBox>("WLPresetsCombo");
- box->selectByValue("");
-
- LLWLParamManager::instance()->mAnimator.mIsRunning = true;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = true;
-}
-
-void LLFloaterDayCycle::onLoadDayCycle(LLUICtrl* ctrl)
-{
- LLWLParamManager::instance()->mDay.loadDayCycle("Default.xml");
-
- // sync it all up
- syncSliderTrack();
- syncMenu();
-
- // set the param manager's track to the new one
- LLMultiSliderCtrl* tSldr;
- tSldr = getChild<LLMultiSliderCtrl>(
- "WLTimeSlider");
- LLWLParamManager::instance()->resetAnimator(
- tSldr->getCurSliderValue() / sHoursPerDay, false);
-
- // and draw it
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
-}
-
-void LLFloaterDayCycle::onSaveDayCycle(LLUICtrl* ctrl)
-{
- LLWLParamManager::instance()->mDay.saveDayCycle("Default.xml");
-}
-
-
-void LLFloaterDayCycle::onTimeSliderMoved(LLUICtrl* ctrl)
-{
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>(
- "WLTimeSlider");
-
- /// get the slider value
- F32 val = sldr->getCurSliderValue() / sHoursPerDay;
-
- // set the value, turn off animation
- LLWLParamManager::instance()->mAnimator.setDayTime((F64)val);
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- // then call update once
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
-}
-
-void LLFloaterDayCycle::onKeyTimeMoved(LLUICtrl* ctrl)
-{
- LLComboBox* comboBox = getChild<LLComboBox>("WLKeyPresets");
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
- LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>("WLCurKeyHour");
- LLSpinCtrl* minSpin = getChild<LLSpinCtrl>("WLCurKeyMin");
-
- if(sldr->getValue().size() == 0) {
- return;
- }
-
- // make sure we have a slider
- const std::string& curSldr = sldr->getCurSlider();
- if(curSldr == "") {
- return;
- }
-
- F32 time = sldr->getCurSliderValue();
-
- // check to see if a key exists
- std::string presetName = sSliderToKey[curSldr].presetName;
- sSliderToKey[curSldr].time = time;
-
- // if it exists, turn on check box
- comboBox->selectByValue(presetName);
-
- // now set the spinners
- F32 hour = (F32)((S32)time);
- F32 min = (time - hour) * 60;
-
- // handle imprecision
- if(min >= 59) {
- min = 0;
- hour += 1;
- }
-
- hourSpin->set(hour);
- minSpin->set(min);
-
- syncTrack();
-
-}
-
-void LLFloaterDayCycle::onKeyTimeChanged(LLUICtrl* ctrl)
-{
- // if no keys, skipped
- if(sSliderToKey.size() == 0) {
- return;
- }
-
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>(
- "WLDayCycleKeys");
- LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>(
- "WLCurKeyHour");
- LLSpinCtrl* minSpin = getChild<LLSpinCtrl>(
- "WLCurKeyMin");
-
- F32 hour = hourSpin->get();
- F32 min = minSpin->get();
- F32 val = hour + min / 60.0f;
-
- const std::string& curSldr = sldr->getCurSlider();
- sldr->setCurSliderValue(val, TRUE);
- F32 time = sldr->getCurSliderValue() / sHoursPerDay;
-
- // now set the key's time in the sliderToKey map
- std::string presetName = sSliderToKey[curSldr].presetName;
- sSliderToKey[curSldr].time = time;
-
- syncTrack();
-}
-
-void LLFloaterDayCycle::onKeyPresetChanged(LLUICtrl* ctrl)
-{
- // get the time
- LLComboBox* comboBox = getChild<LLComboBox>(
- "WLKeyPresets");
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>(
- "WLDayCycleKeys");
-
- // do nothing if no sliders
- if(sldr->getValue().size() == 0) {
- return;
- }
-
- // change the map
- std::string newPreset(comboBox->getSelectedValue().asString());
- const std::string& curSldr = sldr->getCurSlider();
-
- // if null, don't use
- if(curSldr == "") {
- return;
- }
-
- sSliderToKey[curSldr].presetName = newPreset;
-
- syncTrack();
-}
-
-void LLFloaterDayCycle::onTimeRateChanged(LLUICtrl* ctrl)
-{
- // get the time
- LLSpinCtrl* secSpin = getChild<LLSpinCtrl>(
- "WLLengthOfDaySec");
-
- LLSpinCtrl* minSpin = getChild<LLSpinCtrl>(
- "WLLengthOfDayMin");
-
- LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>(
- "WLLengthOfDayHour");
-
- F32 hour;
- hour = (F32)hourSpin->getValue().asReal();
- F32 min;
- min = (F32)minSpin->getValue().asReal();
- F32 sec;
- sec = (F32)secSpin->getValue().asReal();
-
- F32 time = 60.0f * 60.0f * hour + 60.0f * min + sec;
- if(time <= 0) {
- time = 1;
- }
- LLWLParamManager::instance()->mDay.mDayRate = time;
-
- syncTrack();
-}
-
-void LLFloaterDayCycle::onAddKey(LLUICtrl* ctrl)
-{
- LLComboBox* comboBox = getChild<LLComboBox>(
- "WLKeyPresets");
- LLMultiSliderCtrl* kSldr = getChild<LLMultiSliderCtrl>(
- "WLDayCycleKeys");
- LLMultiSliderCtrl* tSldr = getChild<LLMultiSliderCtrl>(
- "WLTimeSlider");
-
- llassert_always(sSliderToKey.size() == kSldr->getValue().size());
-
- // get the values
- std::string newPreset(comboBox->getSelectedValue().asString());
-
- // add the slider key
- addSliderKey(tSldr->getCurSliderValue(), newPreset);
-
- syncTrack();
-}
-
-void LLFloaterDayCycle::addSliderKey(F32 time, const std::string & presetName)
-{
- LLMultiSliderCtrl* kSldr = getChild<LLMultiSliderCtrl>(
- "WLDayCycleKeys");
-
- // make a slider
- const std::string& sldrName = kSldr->addSlider(time);
- if(sldrName == "") {
- return;
- }
-
- // set the key
- LLWLSkyKey newKey;
- newKey.presetName = presetName;
- newKey.time = kSldr->getCurSliderValue();
-
- llassert_always(sldrName != LLStringUtil::null);
-
- // add to map
- sSliderToKey.insert(std::pair<std::string, LLWLSkyKey>(sldrName, newKey));
-
- llassert_always(sSliderToKey.size() == kSldr->getValue().size());
-
-}
-
-void LLFloaterDayCycle::deletePreset(std::string& presetName)
-{
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
-
- /// delete any reference
- std::map<std::string, LLWLSkyKey>::iterator curr_preset, next_preset;
- for(curr_preset = sSliderToKey.begin(); curr_preset != sSliderToKey.end(); curr_preset = next_preset)
- {
- next_preset = curr_preset;
- ++next_preset;
- if (curr_preset->second.presetName == presetName)
- {
- sldr->deleteSlider(curr_preset->first);
- sSliderToKey.erase(curr_preset);
- }
- }
-}
-
-void LLFloaterDayCycle::onDeleteKey(LLUICtrl* ctrl)
-{
- if(sSliderToKey.size() == 0) {
- return;
- }
-
- LLComboBox* comboBox = getChild<LLComboBox>(
- "WLKeyPresets");
- LLMultiSliderCtrl* sldr = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
-
- // delete from map
- const std::string& sldrName = sldr->getCurSlider();
- std::map<std::string, LLWLSkyKey>::iterator mIt = sSliderToKey.find(sldrName);
- sSliderToKey.erase(mIt);
-
- sldr->deleteCurSlider();
-
- if(sSliderToKey.size() == 0) {
- return;
- }
-
- const std::string& name = sldr->getCurSlider();
- comboBox->selectByValue(sSliderToKey[name].presetName);
- F32 time = sSliderToKey[name].time;
-
- LLSpinCtrl* hourSpin = getChild<LLSpinCtrl>("WLCurKeyHour");
- LLSpinCtrl* minSpin = getChild<LLSpinCtrl>("WLCurKeyMin");
-
- // now set the spinners
- F32 hour = (F32)((S32)time);
- F32 min = (time - hour) / 60;
- hourSpin->set(hour);
- minSpin->set(min);
-
- syncTrack();
-
-}
diff --git a/indra/newview/llfloaterdaycycle.h b/indra/newview/llfloaterdaycycle.h
deleted file mode 100644
index 993ddb8f07..0000000000
--- a/indra/newview/llfloaterdaycycle.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * @file llfloaterdaycycle.h
- * @brief LLFloaterDayCycle class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFLOATERDAYCYCLE_H
-#define LL_LLFLOATERDAYCYCLE_H
-
-#include "llfloater.h"
-
-#include <vector>
-#include "llwlparamset.h"
-#include "llwlanimator.h"
-
-struct WLColorControl;
-struct WLFloatControl;
-
-/// convenience class for holding keys mapped to sliders
-struct LLWLSkyKey
-{
-public:
- std::string presetName;
- F32 time;
-};
-
-/// Menu for all of windlight's functionality.
-/// Menuing system for adjusting the atmospheric settings of the world.
-class LLFloaterDayCycle : public LLFloater
-{
-public:
-
- LLFloaterDayCycle(const LLSD& key);
- virtual ~LLFloaterDayCycle();
- /*virtual*/ BOOL postBuild();
-
- /// initialize all
- void initCallbacks(void);
-
- /// on time slider moved
- void onTimeSliderMoved(LLUICtrl* ctrl);
-
- /// what happens when you move the key frame
- void onKeyTimeMoved(LLUICtrl* ctrl);
-
- /// what happens when you change the key frame's time
- void onKeyTimeChanged(LLUICtrl* ctrl);
-
- /// if you change the combo box, change the frame
- void onKeyPresetChanged(LLUICtrl* ctrl);
-
- /// run this when user says to run the sky animation
- void onRunAnimSky(LLUICtrl* ctrl);
-
- /// run this when user says to stop the sky animation
- void onStopAnimSky(LLUICtrl* ctrl);
-
- /// if you change the combo box, change the frame
- void onTimeRateChanged(LLUICtrl* ctrl);
-
- /// add a new key on slider
- void onAddKey(LLUICtrl* ctrl);
-
- /// delete any and all reference to a preset
- void deletePreset(std::string& presetName);
-
- /// delete a key frame
- void onDeleteKey(LLUICtrl* ctrl);
-
- /// button to load day
- void onLoadDayCycle(LLUICtrl* ctrl);
-
- /// button to save day
- void onSaveDayCycle(LLUICtrl* ctrl);
-
- /// toggle for Linden time
- void onUseLindenTime(LLUICtrl* ctrl);
-
- /// sync up sliders with day cycle structure
- void syncMenu();
-
- // makes sure key slider has what's in day cycle
- void syncSliderTrack();
-
- /// makes sure day cycle data structure has what's in menu
- void syncTrack();
-
- /// add a slider to the track
- void addSliderKey(F32 time, const std::string& presetName);
-
-private:
-
- // map of sliders to parameters
- static std::map<std::string, LLWLSkyKey> sSliderToKey;
-
- static const F32 sHoursPerDay;
-};
-
-
-#endif
diff --git a/indra/newview/llfloaterdeleteenvpreset.cpp b/indra/newview/llfloaterdeleteenvpreset.cpp
new file mode 100644
index 0000000000..d08aa81cfe
--- /dev/null
+++ b/indra/newview/llfloaterdeleteenvpreset.cpp
@@ -0,0 +1,285 @@
+/**
+ * @file llfloaterdeleteenvpreset.cpp
+ * @brief Floater to delete a water / sky / day cycle preset.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterdeleteenvpreset.h"
+
+// libs
+#include "llbutton.h"
+#include "llcombobox.h"
+#include "llnotificationsutil.h"
+
+// newview
+#include "lldaycyclemanager.h"
+#include "llwaterparammanager.h"
+
+static bool confirmation_callback(const LLSD& notification, const LLSD& response, boost::function<void()> cb)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ cb();
+ }
+ return false;
+
+}
+
+LLFloaterDeleteEnvPreset::LLFloaterDeleteEnvPreset(const LLSD &key)
+: LLFloater(key)
+, mPresetCombo(NULL)
+{
+}
+
+// virtual
+BOOL LLFloaterDeleteEnvPreset::postBuild()
+{
+ mPresetCombo = getChild<LLComboBox>("preset_combo");
+ mPresetCombo->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::postPopulate, this));
+
+ getChild<LLButton>("delete")->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::onBtnDelete, this));
+ getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::onBtnCancel, this));
+
+ // Listen to user preferences change, in which case we need to rebuild the presets list
+ // to disable the [new] current preset.
+ LLEnvManagerNew::instance().setPreferencesChangeCallback(boost::bind(&LLFloaterDeleteEnvPreset::populatePresetsList, this));
+
+ // Listen to presets addition/removal.
+ LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLFloaterDeleteEnvPreset::populateDayCyclesList, this));
+ LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterDeleteEnvPreset::populateSkyPresetsList, this));
+ LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterDeleteEnvPreset::populateWaterPresetsList, this));
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterDeleteEnvPreset::onOpen(const LLSD& key)
+{
+ std::string param = key.asString();
+ std::string floater_title = getString(std::string("title_") + param);
+ std::string combo_label = getString(std::string("label_" + param));
+
+ // Update floater title.
+ setTitle(floater_title);
+
+ // Update the combobox label.
+ getChild<LLUICtrl>("label")->setValue(combo_label);
+
+ // Populate the combobox.
+ populatePresetsList();
+}
+
+void LLFloaterDeleteEnvPreset::onBtnDelete()
+{
+ std::string param = mKey.asString();
+ std::string preset_name = mPresetCombo->getValue().asString();
+ boost::function<void()> confirm_cb;
+
+ if (param == "water")
+ {
+ // Don't allow deleting system presets.
+ if (LLWaterParamManager::instance().isSystemPreset(preset_name))
+ {
+ LLNotificationsUtil::add("WLNoEditDefault");
+ return;
+ }
+
+ confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteWaterPresetConfirmation, this);
+ }
+ else if (param == "sky")
+ {
+ // Don't allow deleting presets referenced by local day cycles.
+ if (LLDayCycleManager::instance().isSkyPresetReferenced(preset_name))
+ {
+ LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", getString("msg_sky_is_referenced")));
+ return;
+ }
+
+ LLWLParamManager& wl_mgr = LLWLParamManager::instance();
+
+ // Don't allow deleting system presets.
+ if (wl_mgr.isSystemPreset(preset_name))
+ {
+ LLNotificationsUtil::add("WLNoEditDefault");
+ return;
+ }
+
+ confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteSkyPresetConfirmation, this);
+ }
+ else if (param == "day_cycle")
+ {
+ LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
+
+ // Don't allow deleting system presets.
+ if (day_mgr.isSystemPreset(preset_name))
+ {
+ LLNotificationsUtil::add("WLNoEditDefault");
+ return;
+ }
+
+ confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteDayCycleConfirmation, this);
+ }
+ else
+ {
+ llwarns << "Unrecognized key" << llendl;
+ }
+
+ LLSD args;
+ args["MESSAGE"] = getString("msg_confirm_deletion");
+ LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(),
+ boost::bind(&confirmation_callback, _1, _2, confirm_cb));
+}
+
+void LLFloaterDeleteEnvPreset::onBtnCancel()
+{
+ closeFloater();
+}
+
+void LLFloaterDeleteEnvPreset::populatePresetsList()
+{
+ std::string param = mKey.asString();
+
+ if (param == "water")
+ {
+ populateWaterPresetsList();
+ }
+ else if (param == "sky")
+ {
+ populateSkyPresetsList();
+ }
+ else if (param == "day_cycle")
+ {
+ populateDayCyclesList();
+ }
+ else
+ {
+ llwarns << "Unrecognized key" << llendl;
+ }
+}
+
+void LLFloaterDeleteEnvPreset::populateWaterPresetsList()
+{
+ if (mKey.asString() != "water") return;
+
+ mPresetCombo->removeall();
+
+ std::string cur_preset;
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ if (!env_mgr.getUseRegionSettings())
+ {
+ cur_preset = env_mgr.getWaterPresetName();
+ }
+
+ LLWaterParamManager::preset_name_list_t presets;
+ LLWaterParamManager::instance().getUserPresetNames(presets); // list only user presets
+ for (LLWaterParamManager::preset_name_list_t::const_iterator it = presets.begin(); it != presets.end(); ++it)
+ {
+ std::string name = *it;
+
+ bool enabled = (name != cur_preset); // don't allow deleting current preset
+ mPresetCombo->add(name, ADD_BOTTOM, enabled);
+ }
+
+ postPopulate();
+}
+
+void LLFloaterDeleteEnvPreset::populateSkyPresetsList()
+{
+ if (mKey.asString() != "sky") return;
+
+ mPresetCombo->removeall();
+
+ std::string cur_preset;
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ if (!env_mgr.getUseRegionSettings() && env_mgr.getUseFixedSky())
+ {
+ cur_preset = env_mgr.getSkyPresetName();
+ }
+
+ LLWLParamManager::preset_name_list_t user_presets;
+ LLWLParamManager::instance().getUserPresetNames(user_presets);
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ const std::string& name = *it;
+ mPresetCombo->add(name, ADD_BOTTOM, /*enabled = */ name != cur_preset);
+ }
+
+ postPopulate();
+}
+
+void LLFloaterDeleteEnvPreset::populateDayCyclesList()
+{
+ if (mKey.asString() != "day_cycle") return;
+
+ mPresetCombo->removeall();
+
+ std::string cur_day;
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ if (!env_mgr.getUseRegionSettings() && env_mgr.getUseDayCycle())
+ {
+ cur_day = env_mgr.getDayCycleName();
+ }
+
+ LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
+ LLDayCycleManager::preset_name_list_t user_days;
+ day_mgr.getUserPresetNames(user_days); // list only user presets
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
+ {
+ const std::string& name = *it;
+ mPresetCombo->add(name, ADD_BOTTOM, name != cur_day);
+ }
+
+ postPopulate();
+}
+
+void LLFloaterDeleteEnvPreset::postPopulate()
+{
+ // Handle empty list and empty selection.
+ bool has_selection = mPresetCombo->getItemCount() > 0 && mPresetCombo->getSelectedValue().isDefined();
+
+ if (!has_selection)
+ {
+ mPresetCombo->setLabel(getString("combo_label"));
+ }
+
+ getChild<LLButton>("delete")->setEnabled(has_selection);
+}
+
+void LLFloaterDeleteEnvPreset::onDeleteDayCycleConfirmation()
+{
+ LLDayCycleManager::instance().deletePreset(mPresetCombo->getValue().asString());
+}
+
+void LLFloaterDeleteEnvPreset::onDeleteSkyPresetConfirmation()
+{
+ LLWLParamKey key(mPresetCombo->getValue().asString(), LLEnvKey::SCOPE_LOCAL);
+ LLWLParamManager::instance().removeParamSet(key, true);
+}
+
+void LLFloaterDeleteEnvPreset::onDeleteWaterPresetConfirmation()
+{
+ LLWaterParamManager::instance().removeParamSet(mPresetCombo->getValue().asString(), true);
+}
diff --git a/indra/newview/llfloaterdeleteenvpreset.h b/indra/newview/llfloaterdeleteenvpreset.h
new file mode 100644
index 0000000000..1211505273
--- /dev/null
+++ b/indra/newview/llfloaterdeleteenvpreset.h
@@ -0,0 +1,62 @@
+/**
+ * @file llfloaterdeleteenvpreset.h
+ * @brief Floater to delete a water / sky / day cycle preset.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERDELETEENVPRESET_H
+#define LL_LLFLOATERDELETEENVPRESET_H
+
+#include "llfloater.h"
+
+class LLComboBox;
+
+class LLFloaterDeleteEnvPreset : public LLFloater
+{
+ LOG_CLASS(LLFloaterDeleteEnvPreset);
+
+public:
+ LLFloaterDeleteEnvPreset(const LLSD &key);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ void onBtnDelete();
+ void onBtnCancel();
+
+private:
+ void populatePresetsList();
+ void populateWaterPresetsList();
+ void populateSkyPresetsList();
+ void populateDayCyclesList();
+
+ void postPopulate();
+
+ void onDeleteDayCycleConfirmation();
+ void onDeleteSkyPresetConfirmation();
+ void onDeleteWaterPresetConfirmation();
+
+ LLComboBox* mPresetCombo;
+};
+
+#endif // LL_LLFLOATERDELETEENVPRESET_H
diff --git a/indra/newview/llfloatereditdaycycle.cpp b/indra/newview/llfloatereditdaycycle.cpp
new file mode 100644
index 0000000000..b63677b258
--- /dev/null
+++ b/indra/newview/llfloatereditdaycycle.cpp
@@ -0,0 +1,825 @@
+/**
+ * @file llfloatereditdaycycle.cpp
+ * @brief Floater to create or edit a day cycle
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatereditdaycycle.h"
+
+// libs
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llloadingindicator.h"
+#include "llmultisliderctrl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llspinctrl.h"
+#include "lltimectrl.h"
+
+// newview
+#include "llagent.h"
+#include "lldaycyclemanager.h"
+#include "llenvmanager.h"
+#include "llregioninfomodel.h"
+#include "llviewerregion.h"
+#include "llwlparammanager.h"
+
+const F32 LLFloaterEditDayCycle::sHoursPerDay = 24.0f;
+
+LLFloaterEditDayCycle::LLFloaterEditDayCycle(const LLSD &key)
+: LLFloater(key)
+, mDayCycleNameEditor(NULL)
+, mDayCyclesCombo(NULL)
+, mTimeSlider(NULL)
+, mKeysSlider(NULL)
+, mSkyPresetsCombo(NULL)
+, mTimeCtrl(NULL)
+, mMakeDefaultCheckBox(NULL)
+, mSaveButton(NULL)
+{
+}
+
+// virtual
+BOOL LLFloaterEditDayCycle::postBuild()
+{
+ mDayCycleNameEditor = getChild<LLLineEditor>("day_cycle_name");
+ mDayCyclesCombo = getChild<LLComboBox>("day_cycle_combo");
+
+ mTimeSlider = getChild<LLMultiSliderCtrl>("WLTimeSlider");
+ mKeysSlider = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
+ mSkyPresetsCombo = getChild<LLComboBox>("WLSkyPresets");
+ mTimeCtrl = getChild<LLTimeCtrl>("time");
+ mSaveButton = getChild<LLButton>("save");
+ mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
+
+ initCallbacks();
+
+ // add the time slider
+ mTimeSlider->addSlider();
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterEditDayCycle::onOpen(const LLSD& key)
+{
+ bool new_day = isNewDay();
+ std::string param = key.asString();
+ std::string floater_title = getString(std::string("title_") + param);
+ std::string hint = getString(std::string("hint_" + param));
+
+ // Update floater title.
+ setTitle(floater_title);
+
+ // Update the hint at the top.
+ getChild<LLUICtrl>("hint")->setValue(hint);
+
+ // Hide the hint to the right of the combo if we're invoked to create a new preset.
+ getChildView("note")->setVisible(!new_day);
+
+ // Switch between the day cycle presets combobox and day cycle name input field.
+ mDayCyclesCombo->setVisible(!new_day);
+ mDayCycleNameEditor->setVisible(new_day);
+
+ // TODO: Make sure only one instance of the floater exists?
+
+ reset();
+}
+
+// virtual
+void LLFloaterEditDayCycle::onClose(bool app_quitting)
+{
+ if (!app_quitting) // there's no point to change environment if we're quitting
+ {
+ LLEnvManagerNew::instance().usePrefs(); // revert changes made to current day cycle
+ }
+}
+
+// virtual
+void LLFloaterEditDayCycle::draw()
+{
+ syncTimeSlider();
+ LLFloater::draw();
+}
+
+void LLFloaterEditDayCycle::initCallbacks(void)
+{
+ mDayCycleNameEditor->setKeystrokeCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleNameEdited, this), NULL);
+ mDayCyclesCombo->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleSelected, this));
+ mDayCyclesCombo->setTextEntryCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleNameEdited, this));
+ mTimeSlider->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onTimeSliderMoved, this));
+ mKeysSlider->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyTimeMoved, this));
+ mTimeCtrl->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyTimeChanged, this));
+ mSkyPresetsCombo->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyPresetChanged, this));
+
+ getChild<LLButton>("WLAddKey")->setClickedCallback(boost::bind(&LLFloaterEditDayCycle::onAddKey, this));
+ getChild<LLButton>("WLDeleteKey")->setClickedCallback(boost::bind(&LLFloaterEditDayCycle::onDeleteKey, this));
+
+ mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnSave, this));
+ mSaveButton->setRightMouseDownCallback(boost::bind(&LLFloaterEditDayCycle::dumpTrack, this));
+ getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnCancel, this));
+
+ // Connect to env manager events.
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ env_mgr.setRegionSettingsChangeCallback(boost::bind(&LLFloaterEditDayCycle::onRegionSettingsChange, this));
+ env_mgr.setRegionChangeCallback(boost::bind(&LLFloaterEditDayCycle::onRegionChange, this));
+ env_mgr.setRegionSettingsAppliedCallback(boost::bind(&LLFloaterEditDayCycle::onRegionSettingsApplied, this, _1));
+
+ // Connect to day cycle manager events.
+ LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleListChange, this));
+
+ // Connect to sky preset list changes.
+ LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEditDayCycle::onSkyPresetListChange, this));
+
+ // Connect to region info updates.
+ LLRegionInfoModel::instance().setUpdateCallback(boost::bind(&LLFloaterEditDayCycle::onRegionInfoUpdate, this));
+}
+
+void LLFloaterEditDayCycle::syncTimeSlider()
+{
+ // set time
+ mTimeSlider->setCurSliderValue((F32)LLWLParamManager::getInstance()->mAnimator.getDayTime() * sHoursPerDay);
+}
+
+void LLFloaterEditDayCycle::loadTrack()
+{
+ // clear the slider
+ mKeysSlider->clear();
+ mSliderToKey.clear();
+
+ // add sliders
+
+ lldebugs << "Adding " << LLWLParamManager::getInstance()->mDay.mTimeMap.size() << " keys to slider" << llendl;
+
+ LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay;
+ for (std::map<F32, LLWLParamKey>::iterator it = cur_dayp.mTimeMap.begin(); it != cur_dayp.mTimeMap.end(); ++it)
+ {
+ addSliderKey(it->first * sHoursPerDay, it->second);
+ }
+
+ // set drop-down menu to match preset of currently-selected keyframe (one is automatically selected initially)
+ const std::string& cur_sldr = mKeysSlider->getCurSlider();
+ if (strlen(cur_sldr.c_str()) > 0) // only do this if there is a curSldr, otherwise we put an invalid entry into the map
+ {
+ mSkyPresetsCombo->selectByValue(mSliderToKey[cur_sldr].keyframe.toStringVal());
+ }
+
+ syncTimeSlider();
+}
+
+void LLFloaterEditDayCycle::applyTrack()
+{
+ lldebugs << "Applying track (" << mSliderToKey.size() << ")" << llendl;
+
+ // if no keys, do nothing
+ if (mSliderToKey.size() == 0)
+ {
+ lldebugs << "No keys, not syncing" << llendl;
+ return;
+ }
+
+ llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
+
+ // create a new animation track
+ LLWLParamManager::getInstance()->mDay.clearKeyframes();
+
+ // add the keys one by one
+ for (std::map<std::string, SliderKey>::iterator it = mSliderToKey.begin();
+ it != mSliderToKey.end(); ++it)
+ {
+ LLWLParamManager::getInstance()->mDay.addKeyframe(it->second.time / sHoursPerDay,
+ it->second.keyframe);
+ }
+
+ // set the param manager's track to the new one
+ LLWLParamManager::getInstance()->resetAnimator(
+ mTimeSlider->getCurSliderValue() / sHoursPerDay, false);
+
+ LLWLParamManager::getInstance()->mAnimator.update(
+ LLWLParamManager::getInstance()->mCurParams);
+}
+
+void LLFloaterEditDayCycle::refreshSkyPresetsList()
+{
+ // Don't allow selecting region skies for a local day cycle,
+ // because thus we may end up with invalid day cycle.
+ bool include_region_skies = getSelectedDayCycle().scope == LLEnvKey::SCOPE_REGION;
+
+ mSkyPresetsCombo->removeall();
+
+ LLWLParamManager::preset_name_list_t region_presets;
+ LLWLParamManager::preset_name_list_t user_presets, sys_presets;
+ LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
+
+ if (include_region_skies)
+ {
+ // Add region presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
+ {
+ std::string preset_name = *it;
+ std::string item_title = preset_name + " (" + getRegionName() + ")";
+ mSkyPresetsCombo->add(preset_name, LLWLParamKey(*it, LLEnvKey::SCOPE_REGION).toStringVal());
+ }
+
+ if (!region_presets.empty())
+ {
+ mSkyPresetsCombo->addSeparator();
+ }
+ }
+
+ // Add user presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ mSkyPresetsCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
+ }
+
+ if (!user_presets.empty())
+ {
+ mSkyPresetsCombo->addSeparator();
+ }
+
+ // Add system presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
+ {
+ mSkyPresetsCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
+ }
+
+ // set defaults on combo boxes
+ mSkyPresetsCombo->selectFirstItem();
+}
+
+void LLFloaterEditDayCycle::refreshDayCyclesList()
+{
+ llassert(isNewDay() == false);
+
+ mDayCyclesCombo->removeall();
+
+#if 0 // Disable editing existing day cycle until the workflow is clear enough.
+ const LLSD& region_day = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
+ if (region_day.size() > 0)
+ {
+ LLWLParamKey key(getRegionName(), LLEnvKey::SCOPE_REGION);
+ mDayCyclesCombo->add(key.name, key.toLLSD());
+ mDayCyclesCombo->addSeparator();
+ }
+#endif
+
+ LLDayCycleManager::preset_name_list_t user_days, sys_days;
+ LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
+
+ // Add user days.
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
+ {
+ mDayCyclesCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
+ }
+
+ if (user_days.size() > 0)
+ {
+ mDayCyclesCombo->addSeparator();
+ }
+
+ // Add system days.
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
+ {
+ mDayCyclesCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
+ }
+
+ mDayCyclesCombo->setLabel(getString("combo_label"));
+}
+
+void LLFloaterEditDayCycle::onTimeSliderMoved()
+{
+ /// get the slider value
+ F32 val = mTimeSlider->getCurSliderValue() / sHoursPerDay;
+
+ // set the value, turn off animation
+ LLWLParamManager::getInstance()->mAnimator.setDayTime((F64)val);
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ // then call update once
+ LLWLParamManager::getInstance()->mAnimator.update(
+ LLWLParamManager::getInstance()->mCurParams);
+}
+
+void LLFloaterEditDayCycle::onKeyTimeMoved()
+{
+ if (mKeysSlider->getValue().size() == 0)
+ {
+ return;
+ }
+
+ // make sure we have a slider
+ const std::string& cur_sldr = mKeysSlider->getCurSlider();
+ if (cur_sldr == "")
+ {
+ return;
+ }
+
+ F32 time24 = mKeysSlider->getCurSliderValue();
+
+ // check to see if a key exists
+ LLWLParamKey key = mSliderToKey[cur_sldr].keyframe;
+ lldebugs << "Setting key time: " << time24 << LL_ENDL;
+ mSliderToKey[cur_sldr].time = time24;
+
+ // if it exists, turn on check box
+ mSkyPresetsCombo->selectByValue(key.toStringVal());
+
+ mTimeCtrl->setTime24(time24);
+
+ applyTrack();
+}
+
+void LLFloaterEditDayCycle::onKeyTimeChanged()
+{
+ // if no keys, skipped
+ if (mSliderToKey.size() == 0)
+ {
+ return;
+ }
+
+ F32 time24 = mTimeCtrl->getTime24();
+
+ const std::string& cur_sldr = mKeysSlider->getCurSlider();
+ mKeysSlider->setCurSliderValue(time24, TRUE);
+ F32 time = mKeysSlider->getCurSliderValue() / sHoursPerDay;
+
+ // now set the key's time in the sliderToKey map
+ lldebugs << "Setting key time: " << time << LL_ENDL;
+ mSliderToKey[cur_sldr].time = time;
+
+ applyTrack();
+}
+
+void LLFloaterEditDayCycle::onKeyPresetChanged()
+{
+ // do nothing if no sliders
+ if (mKeysSlider->getValue().size() == 0)
+ {
+ return;
+ }
+
+ // change the map
+
+ std::string stringVal = mSkyPresetsCombo->getSelectedValue().asString();
+ LLWLParamKey new_key(stringVal);
+ llassert(!new_key.name.empty());
+ const std::string& cur_sldr = mKeysSlider->getCurSlider();
+
+ // if null, don't use
+ if (cur_sldr == "")
+ {
+ return;
+ }
+
+ mSliderToKey[cur_sldr].keyframe = new_key;
+
+ // Apply changes to current day cycle.
+ applyTrack();
+}
+
+void LLFloaterEditDayCycle::onAddKey()
+{
+ llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
+
+ S32 max_sliders;
+ LLEnvKey::EScope scope = LLEnvKey::SCOPE_LOCAL; // *TODO: editing region day cycle
+ switch (scope)
+ {
+ case LLEnvKey::SCOPE_LOCAL:
+ max_sliders = 20; // *HACK this should be LLWLPacketScrubber::MAX_LOCAL_KEY_FRAMES;
+ break;
+ case LLEnvKey::SCOPE_REGION:
+ max_sliders = 12; // *HACK this should be LLWLPacketScrubber::MAX_REGION_KEY_FRAMES;
+ break;
+ default:
+ max_sliders = (S32) mKeysSlider->getMaxValue();
+ break;
+ }
+
+ if ((S32)mSliderToKey.size() >= max_sliders)
+ {
+ LLSD args;
+ args["SCOPE"] = LLEnvManagerNew::getScopeString(scope);
+ args["MAX"] = max_sliders;
+ LLNotificationsUtil::add("DayCycleTooManyKeyframes", args, LLSD(), LLNotificationFunctorRegistry::instance().DONOTHING);
+ return;
+ }
+
+ // add the slider key
+ std::string key_val = mSkyPresetsCombo->getSelectedValue().asString();
+ LLWLParamKey sky_params(key_val);
+ llassert(!sky_params.name.empty());
+
+ F32 time = mTimeSlider->getCurSliderValue();
+ addSliderKey(time, sky_params);
+
+ // apply the change to current day cycles
+ applyTrack();
+}
+
+void LLFloaterEditDayCycle::addSliderKey(F32 time, LLWLParamKey keyframe)
+{
+ // make a slider
+ const std::string& sldr_name = mKeysSlider->addSlider(time);
+ if (sldr_name.empty())
+ {
+ return;
+ }
+
+ // set the key
+ SliderKey newKey(keyframe, mKeysSlider->getCurSliderValue());
+
+ llassert_always(sldr_name != LLStringUtil::null);
+
+ // add to map
+ mSliderToKey.insert(std::pair<std::string, SliderKey>(sldr_name, newKey));
+
+ llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
+}
+
+LLWLParamKey LLFloaterEditDayCycle::getSelectedDayCycle()
+{
+ LLWLParamKey dc_key;
+
+ if (mDayCycleNameEditor->getVisible())
+ {
+ dc_key.name = mDayCycleNameEditor->getText();
+ dc_key.scope = LLEnvKey::SCOPE_LOCAL;
+ }
+ else
+ {
+ LLSD combo_val = mDayCyclesCombo->getValue();
+
+ if (!combo_val.isArray()) // manually typed text
+ {
+ dc_key.name = combo_val.asString();
+ dc_key.scope = LLEnvKey::SCOPE_LOCAL;
+ }
+ else
+ {
+ dc_key.fromLLSD(combo_val);
+ }
+ }
+
+ return dc_key;
+}
+
+bool LLFloaterEditDayCycle::isNewDay() const
+{
+ return mKey.asString() == "new";
+}
+
+void LLFloaterEditDayCycle::dumpTrack()
+{
+ LL_DEBUGS("Windlight") << "Dumping day cycle" << LL_ENDL;
+
+ LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay;
+ for (std::map<F32, LLWLParamKey>::iterator it = cur_dayp.mTimeMap.begin(); it != cur_dayp.mTimeMap.end(); ++it)
+ {
+ F32 time = it->first * 24.0f;
+ S32 h = (S32) time;
+ S32 m = (S32) ((time - h) * 60.0f);
+ LL_DEBUGS("Windlight") << llformat("(%.3f) %02d:%02d", time, h, m) << " => " << it->second.name << LL_ENDL;
+ }
+}
+
+void LLFloaterEditDayCycle::enableEditing(bool enable)
+{
+ mSkyPresetsCombo->setEnabled(enable);
+ mTimeCtrl->setEnabled(enable);
+ getChild<LLPanel>("day_cycle_slider_panel")->setCtrlsEnabled(enable);
+ mSaveButton->setEnabled(enable);
+ mMakeDefaultCheckBox->setEnabled(enable);
+}
+
+void LLFloaterEditDayCycle::reset()
+{
+ // clear the slider
+ mKeysSlider->clear();
+ mSliderToKey.clear();
+
+ refreshSkyPresetsList();
+
+ if (isNewDay())
+ {
+ mDayCycleNameEditor->setValue(LLSD());
+ F32 time = 0.5f * sHoursPerDay;
+ mSaveButton->setEnabled(FALSE); // will be enabled as soon as users enters a name
+ mTimeSlider->setCurSliderValue(time);
+
+ addSliderKey(time, LLWLParamKey("Default", LLEnvKey::SCOPE_LOCAL));
+ onKeyTimeMoved(); // update the time control and sky sky combo
+
+ applyTrack();
+ }
+ else
+ {
+ refreshDayCyclesList();
+
+ // Disable controls until a day cycle to edit is selected.
+ enableEditing(false);
+ }
+}
+
+void LLFloaterEditDayCycle::saveRegionDayCycle()
+{
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay; // the day cycle being edited
+
+ // Get current day cycle and the sky preset it references.
+ LLSD day_cycle = cur_dayp.asLLSD();
+ LLSD sky_map;
+ cur_dayp.getSkyMap(sky_map);
+
+ // Apply it to the region.
+ LLEnvironmentSettings new_region_settings;
+ new_region_settings.saveParams(day_cycle, sky_map, env_mgr.getRegionSettings().getWaterParams(), 0.0f);
+
+#if 1
+ LLEnvManagerNew::instance().setRegionSettings(new_region_settings);
+#else // Temporary disabled ability to upload new region settings from the Day Cycle Editor.
+ if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings))
+ {
+ llwarns << "Error applying region environment settings" << llendl;
+ return;
+ }
+
+ setApplyProgress(true);
+#endif
+}
+
+void LLFloaterEditDayCycle::setApplyProgress(bool started)
+{
+ LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("progress_indicator");
+
+ indicator->setVisible(started);
+
+ if (started)
+ {
+ indicator->start();
+ }
+ else
+ {
+ indicator->stop();
+ }
+}
+
+bool LLFloaterEditDayCycle::getApplyProgress() const
+{
+ return getChild<LLLoadingIndicator>("progress_indicator")->getVisible();
+}
+
+void LLFloaterEditDayCycle::onDeleteKey()
+{
+ if (mSliderToKey.size() == 0)
+ {
+ return;
+ }
+ else if (mSliderToKey.size() == 1)
+ {
+ LLNotifications::instance().add("EnvCannotDeleteLastDayCycleKey", LLSD(), LLSD());
+ return;
+ }
+
+ // delete from map
+ const std::string& sldr_name = mKeysSlider->getCurSlider();
+ std::map<std::string, SliderKey>::iterator mIt = mSliderToKey.find(sldr_name);
+ mSliderToKey.erase(mIt);
+
+ mKeysSlider->deleteCurSlider();
+
+ if (mSliderToKey.size() == 0)
+ {
+ return;
+ }
+
+ const std::string& name = mKeysSlider->getCurSlider();
+ mSkyPresetsCombo->selectByValue(mSliderToKey[name].keyframe.toStringVal());
+ F32 time24 = mSliderToKey[name].time;
+
+ mTimeCtrl->setTime24(time24);
+
+ applyTrack();
+}
+
+void LLFloaterEditDayCycle::onRegionSettingsChange()
+{
+ LL_DEBUGS("Windlight") << "Region settings changed" << LL_ENDL;
+
+ if (getApplyProgress()) // our region settings have being applied
+ {
+ setApplyProgress(false);
+
+ // Change preference if requested.
+ if (mMakeDefaultCheckBox->getValue())
+ {
+ LL_DEBUGS("Windlight") << "Changed environment preference to region settings" << llendl;
+ LLEnvManagerNew::instance().setUseRegionSettings(true);
+ }
+
+ closeFloater();
+ }
+}
+
+void LLFloaterEditDayCycle::onRegionChange()
+{
+ LL_DEBUGS("Windlight") << "Region changed" << LL_ENDL;
+
+ // If we're editing the region day cycle
+ if (getSelectedDayCycle().scope == LLEnvKey::SCOPE_REGION)
+ {
+ reset(); // undoes all unsaved changes
+ }
+}
+
+void LLFloaterEditDayCycle::onRegionSettingsApplied(bool success)
+{
+ LL_DEBUGS("Windlight") << "Region settings applied: " << success << LL_ENDL;
+
+ if (!success)
+ {
+ // stop progress indicator
+ setApplyProgress(false);
+ }
+}
+
+void LLFloaterEditDayCycle::onRegionInfoUpdate()
+{
+ LL_DEBUGS("Windlight") << "Region info updated" << LL_ENDL;
+ bool can_edit = true;
+
+ // If we've selected the region day cycle for editing.
+ if (getSelectedDayCycle().scope == LLEnvKey::SCOPE_REGION)
+ {
+ // check whether we have the access
+ can_edit = LLEnvManagerNew::canEditRegionSettings();
+ }
+
+ enableEditing(can_edit);
+}
+
+void LLFloaterEditDayCycle::onDayCycleNameEdited()
+{
+ // Disable saving a day cycle having empty name.
+ LLWLParamKey key = getSelectedDayCycle();
+ mSaveButton->setEnabled(!key.name.empty());
+}
+
+void LLFloaterEditDayCycle::onDayCycleSelected()
+{
+ LLSD day_data;
+ LLWLParamKey dc_key = getSelectedDayCycle();
+ bool can_edit = true;
+
+ if (dc_key.scope == LLEnvKey::SCOPE_LOCAL)
+ {
+ if (!LLDayCycleManager::instance().getPreset(dc_key.name, day_data))
+ {
+ llwarns << "No day cycle named " << dc_key.name << llendl;
+ return;
+ }
+ }
+ else
+ {
+ day_data = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
+ if (day_data.size() == 0)
+ {
+ llwarns << "Empty region day cycle" << llendl;
+ llassert(day_data.size() > 0);
+ return;
+ }
+
+ can_edit = LLEnvManagerNew::canEditRegionSettings();
+ }
+
+ // We may need to add or remove region skies from the list.
+ refreshSkyPresetsList();
+
+ F32 slider_time = mTimeSlider->getCurSliderValue() / sHoursPerDay;
+ LLWLParamManager::instance().applyDayCycleParams(day_data, dc_key.scope, slider_time);
+ loadTrack();
+
+ enableEditing(can_edit);
+}
+
+void LLFloaterEditDayCycle::onBtnSave()
+{
+ LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
+ LLWLParamKey selected_day = getSelectedDayCycle();
+
+ if (selected_day.scope == LLEnvKey::SCOPE_REGION)
+ {
+ saveRegionDayCycle();
+ closeFloater();
+ return;
+ }
+
+ std::string name = selected_day.name;
+ if (name.empty())
+ {
+ // *TODO: show an alert
+ llwarns << "Empty day cycle name" << llendl;
+ return;
+ }
+
+ // Don't allow overwriting system presets.
+ if (day_mgr.isSystemPreset(name))
+ {
+ LLNotificationsUtil::add("WLNoEditDefault");
+ return;
+ }
+
+ // Save, ask for confirmation for overwriting an existing preset.
+ if (day_mgr.presetExists(name))
+ {
+ LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditDayCycle::onSaveAnswer, this, _1, _2));
+ }
+ else
+ {
+ // new preset, hence no confirmation needed
+ onSaveConfirmed();
+ }
+}
+
+void LLFloaterEditDayCycle::onBtnCancel()
+{
+ closeFloater();
+}
+
+bool LLFloaterEditDayCycle::onSaveAnswer(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ // If they choose save, do it. Otherwise, don't do anything
+ if (option == 0)
+ {
+ onSaveConfirmed();
+ }
+
+ return false;
+}
+
+void LLFloaterEditDayCycle::onSaveConfirmed()
+{
+ std::string name = getSelectedDayCycle().name;
+
+ // Save preset.
+ LLSD data = LLWLParamManager::instance().mDay.asLLSD();
+ LL_DEBUGS("Windlight") << "Saving day cycle " << name << ": " << data << LL_ENDL;
+ LLDayCycleManager::instance().savePreset(name, data);
+
+ // Change preference if requested.
+ if (mMakeDefaultCheckBox->getValue())
+ {
+ LL_DEBUGS("Windlight") << name << " is now the new preferred day cycle" << llendl;
+ LLEnvManagerNew::instance().setUseDayCycle(name);
+ }
+
+ closeFloater();
+}
+
+void LLFloaterEditDayCycle::onDayCycleListChange()
+{
+ if (!isNewDay())
+ {
+ refreshDayCyclesList();
+ }
+}
+
+void LLFloaterEditDayCycle::onSkyPresetListChange()
+{
+ refreshSkyPresetsList();
+
+ // Refresh sliders from the currently visible day cycle.
+ loadTrack();
+}
+
+// static
+std::string LLFloaterEditDayCycle::getRegionName()
+{
+ return gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
+}
diff --git a/indra/newview/llfloatereditdaycycle.h b/indra/newview/llfloatereditdaycycle.h
new file mode 100644
index 0000000000..e6e4fe39c1
--- /dev/null
+++ b/indra/newview/llfloatereditdaycycle.h
@@ -0,0 +1,137 @@
+/**
+ * @file llfloatereditdaycycle.h
+ * @brief Floater to create or edit a day cycle
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATEREDITDAYCYCLE_H
+#define LL_LLFLOATEREDITDAYCYCLE_H
+
+#include "llfloater.h"
+
+#include "llwlparammanager.h" // for LLWLParamKey
+
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLLineEditor;
+class LLMultiSliderCtrl;
+class LLTimeCtrl;
+
+/**
+ * Floater for creating or editing a day cycle.
+ */
+class LLFloaterEditDayCycle : public LLFloater
+{
+ LOG_CLASS(LLFloaterEditDayCycle);
+
+public:
+ LLFloaterEditDayCycle(const LLSD &key);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void draw();
+
+private:
+
+ /// sync the time slider with day cycle structure
+ void syncTimeSlider();
+
+ // makes sure key slider has what's in day cycle
+ void loadTrack();
+
+ /// makes sure day cycle data structure has what's in menu
+ void applyTrack();
+
+ /// refresh the sky presets combobox
+ void refreshSkyPresetsList();
+
+ /// refresh the day cycle combobox
+ void refreshDayCyclesList();
+
+ /// add a slider to the track
+ void addSliderKey(F32 time, LLWLParamKey keyframe);
+
+ void initCallbacks();
+ LLWLParamKey getSelectedDayCycle();
+ bool isNewDay() const;
+ void dumpTrack();
+ void enableEditing(bool enable);
+ void reset();
+ void saveRegionDayCycle();
+
+ void setApplyProgress(bool started);
+ bool getApplyProgress() const;
+
+ void onTimeSliderMoved(); /// time slider moved
+ void onKeyTimeMoved(); /// a key frame moved
+ void onKeyTimeChanged(); /// a key frame's time changed
+ void onKeyPresetChanged(); /// sky preset selected
+ void onAddKey(); /// new key added on slider
+ void onDeleteKey(); /// a key frame deleted
+
+ void onRegionSettingsChange();
+ void onRegionChange();
+ void onRegionSettingsApplied(bool success);
+ void onRegionInfoUpdate();
+
+ void onDayCycleNameEdited();
+ void onDayCycleSelected();
+ void onBtnSave();
+ void onBtnCancel();
+
+ bool onSaveAnswer(const LLSD& notification, const LLSD& response);
+ void onSaveConfirmed();
+
+ void onDayCycleListChange();
+ void onSkyPresetListChange();
+
+ static std::string getRegionName();
+
+ /// convenience class for holding keyframes mapped to sliders
+ struct SliderKey
+ {
+ public:
+ SliderKey(LLWLParamKey kf, F32 t) : keyframe(kf), time(t) {}
+ SliderKey() : keyframe(), time(0.f) {} // Don't use this default constructor
+
+ LLWLParamKey keyframe;
+ F32 time;
+ };
+
+ static const F32 sHoursPerDay;
+
+ LLLineEditor* mDayCycleNameEditor;
+ LLComboBox* mDayCyclesCombo;
+ LLMultiSliderCtrl* mTimeSlider;
+ LLMultiSliderCtrl* mKeysSlider;
+ LLComboBox* mSkyPresetsCombo;
+ LLTimeCtrl* mTimeCtrl;
+ LLCheckBoxCtrl* mMakeDefaultCheckBox;
+ LLButton* mSaveButton;
+
+ // map of sliders to parameters
+ std::map<std::string, SliderKey> mSliderToKey;
+};
+
+#endif // LL_LLFLOATEREDITDAYCYCLE_H
diff --git a/indra/newview/llfloatereditsky.cpp b/indra/newview/llfloatereditsky.cpp
new file mode 100644
index 0000000000..abee7b5dc9
--- /dev/null
+++ b/indra/newview/llfloatereditsky.cpp
@@ -0,0 +1,923 @@
+/**
+ * @file llfloatereditsky.cpp
+ * @brief Floater to create or edit a sky preset
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatereditsky.h"
+
+// libs
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llmultisliderctrl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llsliderctrl.h"
+#include "lltabcontainer.h"
+#include "lltimectrl.h"
+
+// newview
+#include "llagent.h"
+#include "llcolorswatch.h"
+#include "llregioninfomodel.h"
+#include "llviewerregion.h"
+
+static const F32 WL_SUN_AMBIENT_SLIDER_SCALE = 3.0f;
+static const F32 WL_BLUE_HORIZON_DENSITY_SCALE = 2.0f;
+static const F32 WL_CLOUD_SLIDER_SCALE = 1.0f;
+
+static F32 sun_pos_to_time24(F32 sun_pos)
+{
+ return fmodf(sun_pos * 24.0f + 6, 24.0f);
+}
+
+static F32 time24_to_sun_pos(F32 time24)
+{
+ F32 sun_pos = fmodf((time24 - 6) / 24.0f, 1.0f);
+ if (sun_pos < 0) ++sun_pos;
+ return sun_pos;
+}
+
+LLFloaterEditSky::LLFloaterEditSky(const LLSD &key)
+: LLFloater(key)
+, mSkyPresetNameEditor(NULL)
+, mSkyPresetCombo(NULL)
+, mMakeDefaultCheckBox(NULL)
+, mSaveButton(NULL)
+{
+}
+
+// virtual
+BOOL LLFloaterEditSky::postBuild()
+{
+ mSkyPresetNameEditor = getChild<LLLineEditor>("sky_preset_name");
+ mSkyPresetCombo = getChild<LLComboBox>("sky_preset_combo");
+ mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
+ mSaveButton = getChild<LLButton>("save");
+
+ initCallbacks();
+
+ // Create the sun position scrubber on the slider.
+ getChild<LLMultiSliderCtrl>("WLSunPos")->addSlider(12.f);
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterEditSky::onOpen(const LLSD& key)
+{
+ bool new_preset = isNewPreset();
+ std::string param = key.asString();
+ std::string floater_title = getString(std::string("title_") + param);
+ std::string hint = getString(std::string("hint_" + param));
+
+ // Update floater title.
+ setTitle(floater_title);
+
+ // Update the hint at the top.
+ getChild<LLUICtrl>("hint")->setValue(hint);
+
+ // Hide the hint to the right of the combo if we're invoked to create a new preset.
+ getChildView("note")->setVisible(!new_preset);
+
+ // Switch between the sky presets combobox and preset name input field.
+ mSkyPresetCombo->setVisible(!new_preset);
+ mSkyPresetNameEditor->setVisible(new_preset);
+
+ reset();
+}
+
+// virtual
+void LLFloaterEditSky::onClose(bool app_quitting)
+{
+ if (!app_quitting) // there's no point to change environment if we're quitting
+ {
+ LLEnvManagerNew::instance().usePrefs(); // revert changes made to current environment
+ }
+}
+
+// virtual
+void LLFloaterEditSky::draw()
+{
+ syncControls();
+ LLFloater::draw();
+}
+
+void LLFloaterEditSky::initCallbacks(void)
+{
+ // *TODO: warn user if a region environment update comes while we're editing a region sky preset.
+
+ mSkyPresetNameEditor->setKeystrokeCallback(boost::bind(&LLFloaterEditSky::onSkyPresetNameEdited, this), NULL);
+ mSkyPresetCombo->setCommitCallback(boost::bind(&LLFloaterEditSky::onSkyPresetSelected, this));
+ mSkyPresetCombo->setTextEntryCallback(boost::bind(&LLFloaterEditSky::onSkyPresetNameEdited, this));
+
+ mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditSky::onBtnSave, this));
+ getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditSky::onBtnCancel, this));
+
+ LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLFloaterEditSky::onRegionSettingsChange, this));
+ LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEditSky::onSkyPresetListChange, this));
+
+ // Connect to region info updates.
+ LLRegionInfoModel::instance().setUpdateCallback(boost::bind(&LLFloaterEditSky::onRegionInfoUpdate, this));
+
+ //-------------------------------------------------------------------------
+
+ LLWLParamManager& param_mgr = LLWLParamManager::instance();
+
+ // blue horizon
+ getChild<LLUICtrl>("WLBlueHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mBlueHorizon));
+
+ // haze density, horizon, mult, and altitude
+ getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mHazeDensity));
+ getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mHazeHorizon));
+ getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mDensityMult));
+ getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mMaxAlt));
+
+ // blue density
+ getChild<LLUICtrl>("WLBlueDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mBlueDensity));
+
+ // Lighting
+
+ // sunlight
+ getChild<LLUICtrl>("WLSunlight")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mSunlight));
+
+ // glow
+ getChild<LLUICtrl>("WLGlowR")->setCommitCallback(boost::bind(&LLFloaterEditSky::onGlowRMoved, this, _1, &param_mgr.mGlow));
+ getChild<LLUICtrl>("WLGlowB")->setCommitCallback(boost::bind(&LLFloaterEditSky::onGlowBMoved, this, _1, &param_mgr.mGlow));
+
+ // ambient
+ getChild<LLUICtrl>("WLAmbient")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mAmbient));
+
+ // time of day
+ getChild<LLUICtrl>("WLSunPos")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunMoved, this, _1, &param_mgr.mLightnorm)); // multi-slider
+ getChild<LLTimeCtrl>("WLDayTime")->setCommitCallback(boost::bind(&LLFloaterEditSky::onTimeChanged, this)); // time ctrl
+ getChild<LLUICtrl>("WLEastAngle")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunMoved, this, _1, &param_mgr.mLightnorm));
+
+ // Clouds
+
+ // Cloud Color
+ getChild<LLUICtrl>("WLCloudColor")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mCloudColor));
+
+ // Cloud
+ getChild<LLUICtrl>("WLCloudX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mCloudMain));
+ getChild<LLUICtrl>("WLCloudY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlGMoved, this, _1, &param_mgr.mCloudMain));
+ getChild<LLUICtrl>("WLCloudDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlBMoved, this, _1, &param_mgr.mCloudMain));
+
+ // Cloud Detail
+ getChild<LLUICtrl>("WLCloudDetailX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mCloudDetail));
+ getChild<LLUICtrl>("WLCloudDetailY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlGMoved, this, _1, &param_mgr.mCloudDetail));
+ getChild<LLUICtrl>("WLCloudDetailDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlBMoved, this, _1, &param_mgr.mCloudDetail));
+
+ // Cloud extras
+ getChild<LLUICtrl>("WLCloudCoverage")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mCloudCoverage));
+ getChild<LLUICtrl>("WLCloudScale")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mCloudScale));
+ getChild<LLUICtrl>("WLCloudLockX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollXToggled, this, _1));
+ getChild<LLUICtrl>("WLCloudLockY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollYToggled, this, _1));
+ getChild<LLUICtrl>("WLCloudScrollX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollXMoved, this, _1));
+ getChild<LLUICtrl>("WLCloudScrollY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollYMoved, this, _1));
+ getChild<LLUICtrl>("WLDistanceMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mDistanceMult));
+
+ // Dome
+ getChild<LLUICtrl>("WLGamma")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mWLGamma));
+ getChild<LLUICtrl>("WLStarAlpha")->setCommitCallback(boost::bind(&LLFloaterEditSky::onStarAlphaMoved, this, _1));
+}
+
+//=================================================================================================
+
+void LLFloaterEditSky::syncControls()
+{
+ bool err;
+
+ LLWLParamManager * param_mgr = LLWLParamManager::getInstance();
+
+ LLWLParamSet& cur_params = param_mgr->mCurParams;
+
+ // blue horizon
+ param_mgr->mBlueHorizon = cur_params.getVector(param_mgr->mBlueHorizon.mName, err);
+ setColorSwatch("WLBlueHorizon", param_mgr->mBlueHorizon, WL_BLUE_HORIZON_DENSITY_SCALE);
+
+ // haze density, horizon, mult, and altitude
+ param_mgr->mHazeDensity = cur_params.getVector(param_mgr->mHazeDensity.mName, err);
+ childSetValue("WLHazeDensity", param_mgr->mHazeDensity.r);
+ param_mgr->mHazeHorizon = cur_params.getVector(param_mgr->mHazeHorizon.mName, err);
+ childSetValue("WLHazeHorizon", param_mgr->mHazeHorizon.r);
+ param_mgr->mDensityMult = cur_params.getVector(param_mgr->mDensityMult.mName, err);
+ childSetValue("WLDensityMult", param_mgr->mDensityMult.x *
+ param_mgr->mDensityMult.mult);
+ param_mgr->mMaxAlt = cur_params.getVector(param_mgr->mMaxAlt.mName, err);
+ childSetValue("WLMaxAltitude", param_mgr->mMaxAlt.x);
+
+ // blue density
+ param_mgr->mBlueDensity = cur_params.getVector(param_mgr->mBlueDensity.mName, err);
+ setColorSwatch("WLBlueDensity", param_mgr->mBlueDensity, WL_BLUE_HORIZON_DENSITY_SCALE);
+
+ // Lighting
+
+ // sunlight
+ param_mgr->mSunlight = cur_params.getVector(param_mgr->mSunlight.mName, err);
+ setColorSwatch("WLSunlight", param_mgr->mSunlight, WL_SUN_AMBIENT_SLIDER_SCALE);
+
+ // glow
+ param_mgr->mGlow = cur_params.getVector(param_mgr->mGlow.mName, err);
+ childSetValue("WLGlowR", 2 - param_mgr->mGlow.r / 20.0f);
+ childSetValue("WLGlowB", -param_mgr->mGlow.b / 5.0f);
+
+ // ambient
+ param_mgr->mAmbient = cur_params.getVector(param_mgr->mAmbient.mName, err);
+ setColorSwatch("WLAmbient", param_mgr->mAmbient, WL_SUN_AMBIENT_SLIDER_SCALE);
+
+ F32 time24 = sun_pos_to_time24(param_mgr->mCurParams.getFloat("sun_angle",err) / F_TWO_PI);
+ getChild<LLMultiSliderCtrl>("WLSunPos")->setCurSliderValue(time24, TRUE);
+ getChild<LLTimeCtrl>("WLDayTime")->setTime24(time24);
+ childSetValue("WLEastAngle", param_mgr->mCurParams.getFloat("east_angle",err) / F_TWO_PI);
+
+ // Clouds
+
+ // Cloud Color
+ param_mgr->mCloudColor = cur_params.getVector(param_mgr->mCloudColor.mName, err);
+ setColorSwatch("WLCloudColor", param_mgr->mCloudColor, WL_CLOUD_SLIDER_SCALE);
+
+ // Cloud
+ param_mgr->mCloudMain = cur_params.getVector(param_mgr->mCloudMain.mName, err);
+ childSetValue("WLCloudX", param_mgr->mCloudMain.r);
+ childSetValue("WLCloudY", param_mgr->mCloudMain.g);
+ childSetValue("WLCloudDensity", param_mgr->mCloudMain.b);
+
+ // Cloud Detail
+ param_mgr->mCloudDetail = cur_params.getVector(param_mgr->mCloudDetail.mName, err);
+ childSetValue("WLCloudDetailX", param_mgr->mCloudDetail.r);
+ childSetValue("WLCloudDetailY", param_mgr->mCloudDetail.g);
+ childSetValue("WLCloudDetailDensity", param_mgr->mCloudDetail.b);
+
+ // Cloud extras
+ param_mgr->mCloudCoverage = cur_params.getVector(param_mgr->mCloudCoverage.mName, err);
+ param_mgr->mCloudScale = cur_params.getVector(param_mgr->mCloudScale.mName, err);
+ childSetValue("WLCloudCoverage", param_mgr->mCloudCoverage.x);
+ childSetValue("WLCloudScale", param_mgr->mCloudScale.x);
+
+ // cloud scrolling
+ bool lockX = !param_mgr->mCurParams.getEnableCloudScrollX();
+ bool lockY = !param_mgr->mCurParams.getEnableCloudScrollY();
+ childSetValue("WLCloudLockX", lockX);
+ childSetValue("WLCloudLockY", lockY);
+
+ // disable if locked, enable if not
+ if (lockX)
+ {
+ childDisable("WLCloudScrollX");
+ }
+ else
+ {
+ childEnable("WLCloudScrollX");
+ }
+ if (lockY)
+ {
+ childDisable("WLCloudScrollY");
+ }
+ else
+ {
+ childEnable("WLCloudScrollY");
+ }
+
+ // *HACK cloud scrolling is off my an additive of 10
+ childSetValue("WLCloudScrollX", param_mgr->mCurParams.getCloudScrollX() - 10.0f);
+ childSetValue("WLCloudScrollY", param_mgr->mCurParams.getCloudScrollY() - 10.0f);
+
+ param_mgr->mDistanceMult = cur_params.getVector(param_mgr->mDistanceMult.mName, err);
+ childSetValue("WLDistanceMult", param_mgr->mDistanceMult.x);
+
+ // Tweak extras
+
+ param_mgr->mWLGamma = cur_params.getVector(param_mgr->mWLGamma.mName, err);
+ childSetValue("WLGamma", param_mgr->mWLGamma.x);
+
+ childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness());
+}
+
+void LLFloaterEditSky::setColorSwatch(const std::string& name, const WLColorControl& from_ctrl, F32 k)
+{
+ // Set the value, dividing it by <k> first.
+ LLVector4 color_vec = from_ctrl;
+ getChild<LLColorSwatchCtrl>(name)->set(LLColor4(color_vec / k));
+}
+
+// color control callbacks
+void LLFloaterEditSky::onColorControlMoved(LLUICtrl* ctrl, WLColorControl* color_ctrl)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
+ LLVector4 color_vec(swatch->get().mV);
+
+ // Set intensity to maximum of the RGB values.
+ color_vec.mV[3] = llmax(color_vec.mV[0], llmax(color_vec.mV[1], color_vec.mV[2]));
+
+ // Multiply RGB values by the appropriate factor.
+ F32 k = WL_CLOUD_SLIDER_SCALE;
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ k = WL_SUN_AMBIENT_SLIDER_SCALE;
+ }
+ if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ k = WL_BLUE_HORIZON_DENSITY_SCALE;
+ }
+
+ color_vec *= k; // intensity isn't affected by the multiplication
+
+ // Apply the new RGBI value.
+ *color_ctrl = color_vec;
+ color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditSky::onColorControlRMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+
+ color_ctrl->r = sldr_ctrl->getValueF32();
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ color_ctrl->r *= WL_SUN_AMBIENT_SLIDER_SCALE;
+ }
+ if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ color_ctrl->r *= WL_BLUE_HORIZON_DENSITY_SCALE;
+ }
+
+ // move i if it's the max
+ if (color_ctrl->r >= color_ctrl->g && color_ctrl->r >= color_ctrl->b && color_ctrl->hasSliderName)
+ {
+ color_ctrl->i = color_ctrl->r;
+ std::string name = color_ctrl->mSliderName;
+ name.append("I");
+
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ childSetValue(name, color_ctrl->r / WL_SUN_AMBIENT_SLIDER_SCALE);
+ }
+ else if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ childSetValue(name, color_ctrl->r / WL_BLUE_HORIZON_DENSITY_SCALE);
+ }
+ else
+ {
+ childSetValue(name, color_ctrl->r);
+ }
+ }
+
+ color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditSky::onColorControlGMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+
+ color_ctrl->g = sldr_ctrl->getValueF32();
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ color_ctrl->g *= WL_SUN_AMBIENT_SLIDER_SCALE;
+ }
+ if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ color_ctrl->g *= WL_BLUE_HORIZON_DENSITY_SCALE;
+ }
+
+ // move i if it's the max
+ if (color_ctrl->g >= color_ctrl->r && color_ctrl->g >= color_ctrl->b && color_ctrl->hasSliderName)
+ {
+ color_ctrl->i = color_ctrl->g;
+ std::string name = color_ctrl->mSliderName;
+ name.append("I");
+
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ childSetValue(name, color_ctrl->g / WL_SUN_AMBIENT_SLIDER_SCALE);
+ }
+ else if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ childSetValue(name, color_ctrl->g / WL_BLUE_HORIZON_DENSITY_SCALE);
+ }
+ else
+ {
+ childSetValue(name, color_ctrl->g);
+ }
+ }
+
+ color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditSky::onColorControlBMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+
+ color_ctrl->b = sldr_ctrl->getValueF32();
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ color_ctrl->b *= WL_SUN_AMBIENT_SLIDER_SCALE;
+ }
+ if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ color_ctrl->b *= WL_BLUE_HORIZON_DENSITY_SCALE;
+ }
+
+ // move i if it's the max
+ if (color_ctrl->b >= color_ctrl->r && color_ctrl->b >= color_ctrl->g && color_ctrl->hasSliderName)
+ {
+ color_ctrl->i = color_ctrl->b;
+ std::string name = color_ctrl->mSliderName;
+ name.append("I");
+
+ if (color_ctrl->isSunOrAmbientColor)
+ {
+ childSetValue(name, color_ctrl->b / WL_SUN_AMBIENT_SLIDER_SCALE);
+ }
+ else if (color_ctrl->isBlueHorizonOrDensity)
+ {
+ childSetValue(name, color_ctrl->b / WL_BLUE_HORIZON_DENSITY_SCALE);
+ }
+ else
+ {
+ childSetValue(name, color_ctrl->b);
+ }
+ }
+
+ color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+/// GLOW SPECIFIC CODE
+void LLFloaterEditSky::onGlowRMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+
+ // scaled by 20
+ color_ctrl->r = (2 - sldr_ctrl->getValueF32()) * 20;
+
+ color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+/// \NOTE that we want NEGATIVE (-) B
+void LLFloaterEditSky::onGlowBMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+
+ /// \NOTE that we want NEGATIVE (-) B and NOT by 20 as 20 is too big
+ color_ctrl->b = -sldr_ctrl->getValueF32() * 5;
+
+ color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditSky::onFloatControlMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ WLFloatControl * floatControl = static_cast<WLFloatControl *>(userdata);
+
+ floatControl->x = sldr_ctrl->getValueF32() / floatControl->mult;
+
+ floatControl->update(LLWLParamManager::getInstance()->mCurParams);
+ LLWLParamManager::getInstance()->propagateParameters();
+}
+
+
+// Lighting callbacks
+
+// time of day
+void LLFloaterEditSky::onSunMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLMultiSliderCtrl* sun_msldr = getChild<LLMultiSliderCtrl>("WLSunPos");
+ LLSliderCtrl* east_sldr = getChild<LLSliderCtrl>("WLEastAngle");
+ LLTimeCtrl* time_ctrl = getChild<LLTimeCtrl>("WLDayTime");
+ WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+
+ F32 time24 = sun_msldr->getCurSliderValue();
+ time_ctrl->setTime24(time24); // sync the time ctrl with the new sun position
+
+ // get the two angles
+ LLWLParamManager * param_mgr = LLWLParamManager::getInstance();
+
+ param_mgr->mCurParams.setSunAngle(F_TWO_PI * time24_to_sun_pos(time24));
+ param_mgr->mCurParams.setEastAngle(F_TWO_PI * east_sldr->getValueF32());
+
+ // set the sun vector
+ color_ctrl->r = -sin(param_mgr->mCurParams.getEastAngle()) *
+ cos(param_mgr->mCurParams.getSunAngle());
+ color_ctrl->g = sin(param_mgr->mCurParams.getSunAngle());
+ color_ctrl->b = cos(param_mgr->mCurParams.getEastAngle()) *
+ cos(param_mgr->mCurParams.getSunAngle());
+ color_ctrl->i = 1.f;
+
+ color_ctrl->update(param_mgr->mCurParams);
+ param_mgr->propagateParameters();
+}
+
+void LLFloaterEditSky::onTimeChanged()
+{
+ F32 time24 = getChild<LLTimeCtrl>("WLDayTime")->getTime24();
+ getChild<LLMultiSliderCtrl>("WLSunPos")->setCurSliderValue(time24, TRUE);
+ onSunMoved(getChild<LLUICtrl>("WLSunPos"), &LLWLParamManager::instance().mLightnorm);
+}
+
+void LLFloaterEditSky::onStarAlphaMoved(LLUICtrl* ctrl)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ LLWLParamManager::getInstance()->mCurParams.setStarBrightness(sldr_ctrl->getValueF32());
+}
+
+// Clouds
+void LLFloaterEditSky::onCloudScrollXMoved(LLUICtrl* ctrl)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+ // *HACK all cloud scrolling is off by an additive of 10.
+ LLWLParamManager::getInstance()->mCurParams.setCloudScrollX(sldr_ctrl->getValueF32() + 10.0f);
+}
+
+void LLFloaterEditSky::onCloudScrollYMoved(LLUICtrl* ctrl)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ // *HACK all cloud scrolling is off by an additive of 10.
+ LLWLParamManager::getInstance()->mCurParams.setCloudScrollY(sldr_ctrl->getValueF32() + 10.0f);
+}
+
+void LLFloaterEditSky::onCloudScrollXToggled(LLUICtrl* ctrl)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLCheckBoxCtrl* cb_ctrl = static_cast<LLCheckBoxCtrl*>(ctrl);
+
+ bool lock = cb_ctrl->get();
+ LLWLParamManager::getInstance()->mCurParams.setEnableCloudScrollX(!lock);
+
+ LLSliderCtrl* sldr = getChild<LLSliderCtrl>("WLCloudScrollX");
+
+ if (cb_ctrl->get())
+ {
+ sldr->setEnabled(false);
+ }
+ else
+ {
+ sldr->setEnabled(true);
+ }
+
+}
+
+void LLFloaterEditSky::onCloudScrollYToggled(LLUICtrl* ctrl)
+{
+ LLWLParamManager::getInstance()->mAnimator.deactivate();
+
+ LLCheckBoxCtrl* cb_ctrl = static_cast<LLCheckBoxCtrl*>(ctrl);
+ bool lock = cb_ctrl->get();
+ LLWLParamManager::getInstance()->mCurParams.setEnableCloudScrollY(!lock);
+
+ LLSliderCtrl* sldr = getChild<LLSliderCtrl>("WLCloudScrollY");
+
+ if (cb_ctrl->get())
+ {
+ sldr->setEnabled(false);
+ }
+ else
+ {
+ sldr->setEnabled(true);
+ }
+}
+
+//=================================================================================================
+
+void LLFloaterEditSky::reset()
+{
+ if (isNewPreset())
+ {
+ mSkyPresetNameEditor->setValue(LLSD());
+ mSaveButton->setEnabled(FALSE); // will be enabled as soon as users enters a name
+ }
+ else
+ {
+ refreshSkyPresetsList();
+
+ // Disable controls until a sky preset to edit is selected.
+ enableEditing(false);
+ }
+}
+
+bool LLFloaterEditSky::isNewPreset() const
+{
+ return mKey.asString() == "new";
+}
+
+void LLFloaterEditSky::refreshSkyPresetsList()
+{
+ mSkyPresetCombo->removeall();
+
+ LLWLParamManager::preset_name_list_t region_presets, user_presets, sys_presets;
+ LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
+
+#if 0 // Disable editing region skies until the workflow is clear enough.
+ // Add region presets.
+ std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
+ {
+ std::string item_title = *it + " (" + region_name + ")";
+ mSkyPresetCombo->add(item_title, LLWLParamKey(*it, LLEnvKey::SCOPE_REGION).toLLSD());
+ }
+ if (region_presets.size() > 0)
+ {
+ mSkyPresetCombo->addSeparator();
+ }
+#endif
+
+ // Add user presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
+ }
+ if (user_presets.size() > 0)
+ {
+ mSkyPresetCombo->addSeparator();
+ }
+
+ // Add system presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
+ {
+ mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
+ }
+
+ mSkyPresetCombo->setLabel(getString("combo_label"));
+}
+
+void LLFloaterEditSky::enableEditing(bool enable)
+{
+ // Enable/disable the tab and their contents.
+ LLTabContainer* tab_container = getChild<LLTabContainer>("WindLight Tabs");
+ tab_container->setEnabled(enable);
+ for (S32 i = 0; i < tab_container->getTabCount(); ++i)
+ {
+ tab_container->enableTabButton(i, enable);
+ tab_container->getPanelByIndex(i)->setCtrlsEnabled(enable);
+ }
+
+ // Enable/disable saving.
+ mSaveButton->setEnabled(enable);
+ mMakeDefaultCheckBox->setEnabled(enable);
+}
+
+void LLFloaterEditSky::saveRegionSky()
+{
+ LLWLParamKey key(getSelectedSkyPreset());
+ llassert(key.scope == LLEnvKey::SCOPE_REGION);
+
+ LL_DEBUGS("Windlight") << "Saving region sky preset: " << key.name << llendl;
+ LLWLParamManager& wl_mgr = LLWLParamManager::instance();
+ wl_mgr.mCurParams.mName = key.name;
+ wl_mgr.setParamSet(key, wl_mgr.mCurParams);
+
+ // *TODO: save to cached region settings.
+ LL_WARNS("Windlight") << "Saving region sky is not fully implemented yet" << LL_ENDL;
+}
+
+LLWLParamKey LLFloaterEditSky::getSelectedSkyPreset()
+{
+ LLWLParamKey key;
+
+ if (mSkyPresetNameEditor->getVisible())
+ {
+ key.name = mSkyPresetNameEditor->getText();
+ key.scope = LLEnvKey::SCOPE_LOCAL;
+ }
+ else
+ {
+ LLSD combo_val = mSkyPresetCombo->getValue();
+
+ if (!combo_val.isArray()) // manually typed text
+ {
+ key.name = combo_val.asString();
+ key.scope = LLEnvKey::SCOPE_LOCAL;
+ }
+ else
+ {
+ key.fromLLSD(combo_val);
+ }
+ }
+
+ return key;
+}
+
+void LLFloaterEditSky::onSkyPresetNameEdited()
+{
+ // Disable saving a sky preset having empty name.
+ LLWLParamKey key = getSelectedSkyPreset();
+ mSaveButton->setEnabled(!key.name.empty());
+}
+
+void LLFloaterEditSky::onSkyPresetSelected()
+{
+ LLWLParamKey key = getSelectedSkyPreset();
+ LLWLParamSet sky_params;
+
+ if (!LLWLParamManager::instance().getParamSet(key, sky_params))
+ {
+ // Manually entered string?
+ LL_WARNS("Windlight") << "No sky preset named " << key.toString() << LL_ENDL;
+ return;
+ }
+
+ LLEnvManagerNew::instance().useSkyParams(sky_params.getAll());
+ //syncControls();
+
+ bool can_edit = (key.scope == LLEnvKey::SCOPE_LOCAL || LLEnvManagerNew::canEditRegionSettings());
+ enableEditing(can_edit);
+
+ mMakeDefaultCheckBox->setEnabled(key.scope == LLEnvKey::SCOPE_LOCAL);
+}
+
+bool LLFloaterEditSky::onSaveAnswer(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ // If they choose save, do it. Otherwise, don't do anything
+ if (option == 0)
+ {
+ onSaveConfirmed();
+ }
+
+ return false;
+}
+
+void LLFloaterEditSky::onSaveConfirmed()
+{
+ // Save current params to the selected preset.
+ LLWLParamKey key(getSelectedSkyPreset());
+
+ LL_DEBUGS("Windlight") << "Saving sky preset " << key.name << LL_ENDL;
+ LLWLParamManager& wl_mgr = LLWLParamManager::instance();
+ if (wl_mgr.hasParamSet(key))
+ {
+ wl_mgr.setParamSet(key, wl_mgr.mCurParams);
+ }
+ else
+ {
+ wl_mgr.addParamSet(key, wl_mgr.mCurParams);
+ }
+
+ wl_mgr.savePreset(key);
+
+ // Change preference if requested.
+ if (mMakeDefaultCheckBox->getValue())
+ {
+ LL_DEBUGS("Windlight") << key.name << " is now the new preferred sky preset" << llendl;
+ LLEnvManagerNew::instance().setUseSkyPreset(key.name);
+ }
+
+ closeFloater();
+}
+
+void LLFloaterEditSky::onBtnSave()
+{
+ LLWLParamKey selected_sky = getSelectedSkyPreset();
+ LLWLParamManager& wl_mgr = LLWLParamManager::instance();
+
+ if (selected_sky.scope == LLEnvKey::SCOPE_REGION)
+ {
+ saveRegionSky();
+ closeFloater();
+ return;
+ }
+
+ std::string name = selected_sky.name;
+ if (name.empty())
+ {
+ // *TODO: show an alert
+ llwarns << "Empty sky preset name" << llendl;
+ return;
+ }
+
+ // Don't allow overwriting system presets.
+ if (wl_mgr.isSystemPreset(name))
+ {
+ LLNotificationsUtil::add("WLNoEditDefault");
+ return;
+ }
+
+ // Save, ask for confirmation for overwriting an existing preset.
+ if (wl_mgr.hasParamSet(selected_sky))
+ {
+ LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditSky::onSaveAnswer, this, _1, _2));
+ }
+ else
+ {
+ // new preset, hence no confirmation needed
+ onSaveConfirmed();
+ }
+}
+
+void LLFloaterEditSky::onBtnCancel()
+{
+ closeFloater();
+}
+
+void LLFloaterEditSky::onSkyPresetListChange()
+{
+ LLWLParamKey key = getSelectedSkyPreset(); // preset being edited
+ if (!LLWLParamManager::instance().hasParamSet(key))
+ {
+ // Preset we've been editing doesn't exist anymore. Close the floater.
+ closeFloater(false);
+ }
+ else
+ {
+ // A new preset has been added.
+ // Refresh the presets list, though it may not make sense as the floater is about to be closed.
+ refreshSkyPresetsList();
+ }
+}
+
+void LLFloaterEditSky::onRegionSettingsChange()
+{
+ // If creating a new sky, don't bother.
+ if (isNewPreset())
+ {
+ return;
+ }
+
+ if (getSelectedSkyPreset().scope == LLEnvKey::SCOPE_REGION) // if editing a region sky
+ {
+ // reset the floater to its initial state
+ reset();
+
+ // *TODO: Notify user?
+ }
+ else // editing a local sky
+ {
+ refreshSkyPresetsList();
+ }
+}
+
+void LLFloaterEditSky::onRegionInfoUpdate()
+{
+ bool can_edit = true;
+
+ // If we've selected a region sky preset for editing.
+ if (getSelectedSkyPreset().scope == LLEnvKey::SCOPE_REGION)
+ {
+ // check whether we have the access
+ can_edit = LLEnvManagerNew::canEditRegionSettings();
+ }
+
+ enableEditing(can_edit);
+}
diff --git a/indra/newview/llfloatereditsky.h b/indra/newview/llfloatereditsky.h
new file mode 100644
index 0000000000..a06c4fc5fa
--- /dev/null
+++ b/indra/newview/llfloatereditsky.h
@@ -0,0 +1,113 @@
+/**
+ * @file llfloatereditsky.h
+ * @brief Floater to create or edit a sky preset
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATEREDITSKY_H
+#define LL_LLFLOATEREDITSKY_H
+
+#include "llfloater.h"
+#include "llwlparammanager.h"
+
+class LLButton;
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLLineEditor;
+
+/**
+ * Floater for creating or editing a sky preset.
+ */
+class LLFloaterEditSky : public LLFloater
+{
+ LOG_CLASS(LLFloaterEditSky);
+
+public:
+ LLFloaterEditSky(const LLSD &key);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void draw();
+
+private:
+ void initCallbacks(void);
+
+ //-- WL stuff begins ------------------------------------------------------
+
+ void syncControls(); /// sync up sliders with parameters
+
+ void setColorSwatch(const std::string& name, const WLColorControl& from_ctrl, F32 k);
+
+ // general purpose callbacks for dealing with color controllers
+ void onColorControlMoved(LLUICtrl* ctrl, WLColorControl* color_ctrl);
+ void onColorControlRMoved(LLUICtrl* ctrl, void* userdata);
+ void onColorControlGMoved(LLUICtrl* ctrl, void* userdata);
+ void onColorControlBMoved(LLUICtrl* ctrl, void* userdata);
+ void onFloatControlMoved(LLUICtrl* ctrl, void* userdata);
+
+ // lighting callbacks for glow
+ void onGlowRMoved(LLUICtrl* ctrl, void* userdata);
+ void onGlowBMoved(LLUICtrl* ctrl, void* userdata);
+
+ // lighting callbacks for sun
+ void onSunMoved(LLUICtrl* ctrl, void* userdata);
+ void onTimeChanged();
+
+ // for handling when the star slider is moved to adjust the alpha
+ void onStarAlphaMoved(LLUICtrl* ctrl);
+
+ // handle cloud scrolling
+ void onCloudScrollXMoved(LLUICtrl* ctrl);
+ void onCloudScrollYMoved(LLUICtrl* ctrl);
+ void onCloudScrollXToggled(LLUICtrl* ctrl);
+ void onCloudScrollYToggled(LLUICtrl* ctrl);
+
+ //-- WL stuff ends --------------------------------------------------------
+
+ void reset(); /// reset the floater to its initial state
+ bool isNewPreset() const;
+ void refreshSkyPresetsList();
+ void enableEditing(bool enable);
+ void saveRegionSky();
+ LLWLParamKey getSelectedSkyPreset();
+
+ void onSkyPresetNameEdited();
+ void onSkyPresetSelected();
+ bool onSaveAnswer(const LLSD& notification, const LLSD& response);
+ void onSaveConfirmed();
+
+ void onBtnSave();
+ void onBtnCancel();
+
+ void onSkyPresetListChange();
+ void onRegionSettingsChange();
+ void onRegionInfoUpdate();
+
+ LLLineEditor* mSkyPresetNameEditor;
+ LLComboBox* mSkyPresetCombo;
+ LLCheckBoxCtrl* mMakeDefaultCheckBox;
+ LLButton* mSaveButton;
+};
+
+#endif // LL_LLFLOATEREDITSKY_H
diff --git a/indra/newview/llfloatereditwater.cpp b/indra/newview/llfloatereditwater.cpp
new file mode 100644
index 0000000000..64cfc4054f
--- /dev/null
+++ b/indra/newview/llfloatereditwater.cpp
@@ -0,0 +1,772 @@
+/**
+ * @file llfloatereditwater.cpp
+ * @brief Floater to create or edit a water preset
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatereditwater.h"
+
+// libs
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcolorswatch.h"
+#include "llcombobox.h"
+//#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llsliderctrl.h"
+#include "lltexturectrl.h"
+
+// newview
+#include "llagent.h"
+#include "llregioninfomodel.h"
+#include "llviewerregion.h"
+#include "llwaterparammanager.h"
+
+#undef max // Fixes a Windows compiler error
+
+LLFloaterEditWater::LLFloaterEditWater(const LLSD &key)
+: LLFloater(key)
+, mWaterPresetNameEditor(NULL)
+, mWaterPresetCombo(NULL)
+, mMakeDefaultCheckBox(NULL)
+, mSaveButton(NULL)
+{
+}
+
+// virtual
+BOOL LLFloaterEditWater::postBuild()
+{
+ mWaterPresetNameEditor = getChild<LLLineEditor>("water_preset_name");
+ mWaterPresetCombo = getChild<LLComboBox>("water_preset_combo");
+ mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
+ mSaveButton = getChild<LLButton>("save");
+
+ initCallbacks();
+ refreshWaterPresetsList();
+ syncControls();
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterEditWater::onOpen(const LLSD& key)
+{
+ bool new_preset = isNewPreset();
+ std::string param = key.asString();
+ std::string floater_title = getString(std::string("title_") + param);
+ std::string hint = getString(std::string("hint_" + param));
+
+ // Update floater title.
+ setTitle(floater_title);
+
+ // Update the hint at the top.
+ getChild<LLUICtrl>("hint")->setValue(hint);
+
+ // Hide the hint to the right of the combo if we're invoked to create a new preset.
+ getChildView("note")->setVisible(!new_preset);
+
+ // Switch between the water presets combobox and preset name input field.
+ mWaterPresetCombo->setVisible(!new_preset);
+ mWaterPresetNameEditor->setVisible(new_preset);
+
+ reset();
+}
+
+// virtual
+void LLFloaterEditWater::onClose(bool app_quitting)
+{
+ if (!app_quitting) // there's no point to change environment if we're quitting
+ {
+ LLEnvManagerNew::instance().usePrefs(); // revert changes made to current environment
+ }
+}
+
+// virtual
+void LLFloaterEditWater::draw()
+{
+ syncControls();
+ LLFloater::draw();
+}
+
+void LLFloaterEditWater::initCallbacks(void)
+{
+ mWaterPresetNameEditor->setKeystrokeCallback(boost::bind(&LLFloaterEditWater::onWaterPresetNameEdited, this), NULL);
+ mWaterPresetCombo->setCommitCallback(boost::bind(&LLFloaterEditWater::onWaterPresetSelected, this));
+ mWaterPresetCombo->setTextEntryCallback(boost::bind(&LLFloaterEditWater::onWaterPresetNameEdited, this));
+
+ mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditWater::onBtnSave, this));
+ getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditWater::onBtnCancel, this));
+
+ LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLFloaterEditWater::onRegionSettingsChange, this));
+ LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEditWater::onWaterPresetListChange, this));
+
+ // Connect to region info updates.
+ LLRegionInfoModel::instance().setUpdateCallback(boost::bind(&LLFloaterEditWater::onRegionInfoUpdate, this));
+
+ //-------------------------------------------------------------------------
+
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+
+ getChild<LLUICtrl>("WaterFogColor")->setCommitCallback(boost::bind(&LLFloaterEditWater::onWaterFogColorMoved, this, _1, &water_mgr.mFogColor));
+ //getChild<LLUICtrl>("WaterGlow")->setCommitCallback(boost::bind(&LLFloaterEditWater::onColorControlAMoved, this, _1, &water_mgr.mFogColor));
+
+ // fog density
+ getChild<LLUICtrl>("WaterFogDensity")->setCommitCallback(boost::bind(&LLFloaterEditWater::onExpFloatControlMoved, this, _1, &water_mgr.mFogDensity));
+ getChild<LLUICtrl>("WaterUnderWaterFogMod")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mUnderWaterFogMod));
+
+ // blue density
+ getChild<LLUICtrl>("WaterNormalScaleX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlXMoved, this, _1, &water_mgr.mNormalScale));
+ getChild<LLUICtrl>("WaterNormalScaleY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlYMoved, this, _1, &water_mgr.mNormalScale));
+ getChild<LLUICtrl>("WaterNormalScaleZ")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlZMoved, this, _1, &water_mgr.mNormalScale));
+
+ // fresnel
+ getChild<LLUICtrl>("WaterFresnelScale")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mFresnelScale));
+ getChild<LLUICtrl>("WaterFresnelOffset")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mFresnelOffset));
+
+ // scale above/below
+ getChild<LLUICtrl>("WaterScaleAbove")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mScaleAbove));
+ getChild<LLUICtrl>("WaterScaleBelow")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mScaleBelow));
+
+ // blur mult
+ getChild<LLUICtrl>("WaterBlurMult")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mBlurMultiplier));
+
+ // wave direction
+ getChild<LLUICtrl>("WaterWave1DirX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlXMoved, this, _1, &water_mgr.mWave1Dir));
+ getChild<LLUICtrl>("WaterWave1DirY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlYMoved, this, _1, &water_mgr.mWave1Dir));
+ getChild<LLUICtrl>("WaterWave2DirX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlXMoved, this, _1, &water_mgr.mWave2Dir));
+ getChild<LLUICtrl>("WaterWave2DirY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlYMoved, this, _1, &water_mgr.mWave2Dir));
+
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("WaterNormalMap");
+ texture_ctrl->setDefaultImageAssetID(DEFAULT_WATER_NORMAL);
+ texture_ctrl->setCommitCallback(boost::bind(&LLFloaterEditWater::onNormalMapPicked, this, _1));
+}
+
+//=============================================================================
+
+void LLFloaterEditWater::syncControls()
+{
+ // *TODO: Eliminate slow getChild() calls.
+
+ bool err;
+
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+
+ LLWaterParamSet& current_params = water_mgr.mCurParams;
+
+ // blue horizon
+ water_mgr.mFogColor = current_params.getVector4(water_mgr.mFogColor.mName, err);
+
+ LLColor4 col = water_mgr.getFogColor();
+ //getChild<LLUICtrl>("WaterGlow")->setValue(col.mV[3]);
+ col.mV[3] = 1.0f;
+ getChild<LLColorSwatchCtrl>("WaterFogColor")->set(col);
+
+ // fog and wavelets
+ water_mgr.mFogDensity.mExp =
+ log(current_params.getFloat(water_mgr.mFogDensity.mName, err)) /
+ log(water_mgr.mFogDensity.mBase);
+ water_mgr.setDensitySliderValue(water_mgr.mFogDensity.mExp);
+ getChild<LLUICtrl>("WaterFogDensity")->setValue(water_mgr.mFogDensity.mExp);
+
+ water_mgr.mUnderWaterFogMod.mX =
+ current_params.getFloat(water_mgr.mUnderWaterFogMod.mName, err);
+ getChild<LLUICtrl>("WaterUnderWaterFogMod")->setValue(water_mgr.mUnderWaterFogMod.mX);
+
+ water_mgr.mNormalScale = current_params.getVector3(water_mgr.mNormalScale.mName, err);
+ getChild<LLUICtrl>("WaterNormalScaleX")->setValue(water_mgr.mNormalScale.mX);
+ getChild<LLUICtrl>("WaterNormalScaleY")->setValue(water_mgr.mNormalScale.mY);
+ getChild<LLUICtrl>("WaterNormalScaleZ")->setValue(water_mgr.mNormalScale.mZ);
+
+ // Fresnel
+ water_mgr.mFresnelScale.mX = current_params.getFloat(water_mgr.mFresnelScale.mName, err);
+ getChild<LLUICtrl>("WaterFresnelScale")->setValue(water_mgr.mFresnelScale.mX);
+ water_mgr.mFresnelOffset.mX = current_params.getFloat(water_mgr.mFresnelOffset.mName, err);
+ getChild<LLUICtrl>("WaterFresnelOffset")->setValue(water_mgr.mFresnelOffset.mX);
+
+ // Scale Above/Below
+ water_mgr.mScaleAbove.mX = current_params.getFloat(water_mgr.mScaleAbove.mName, err);
+ getChild<LLUICtrl>("WaterScaleAbove")->setValue(water_mgr.mScaleAbove.mX);
+ water_mgr.mScaleBelow.mX = current_params.getFloat(water_mgr.mScaleBelow.mName, err);
+ getChild<LLUICtrl>("WaterScaleBelow")->setValue(water_mgr.mScaleBelow.mX);
+
+ // blur mult
+ water_mgr.mBlurMultiplier.mX = current_params.getFloat(water_mgr.mBlurMultiplier.mName, err);
+ getChild<LLUICtrl>("WaterBlurMult")->setValue(water_mgr.mBlurMultiplier.mX);
+
+ // wave directions
+ water_mgr.mWave1Dir = current_params.getVector2(water_mgr.mWave1Dir.mName, err);
+ getChild<LLUICtrl>("WaterWave1DirX")->setValue(water_mgr.mWave1Dir.mX);
+ getChild<LLUICtrl>("WaterWave1DirY")->setValue(water_mgr.mWave1Dir.mY);
+
+ water_mgr.mWave2Dir = current_params.getVector2(water_mgr.mWave2Dir.mName, err);
+ getChild<LLUICtrl>("WaterWave2DirX")->setValue(water_mgr.mWave2Dir.mX);
+ getChild<LLUICtrl>("WaterWave2DirY")->setValue(water_mgr.mWave2Dir.mY);
+
+ LLTextureCtrl* textCtrl = getChild<LLTextureCtrl>("WaterNormalMap");
+ textCtrl->setImageAssetID(water_mgr.getNormalMapID());
+}
+
+// color control callbacks
+void LLFloaterEditWater::onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ color_ctrl->mR = sldr_ctrl->getValueF32();
+
+ // move i if it's the max
+ if (color_ctrl->mR >= color_ctrl->mG
+ && color_ctrl->mR >= color_ctrl->mB
+ && color_ctrl->mHasSliderName)
+ {
+ color_ctrl->mI = color_ctrl->mR;
+ std::string name = color_ctrl->mSliderName;
+ name.append("I");
+
+ getChild<LLUICtrl>(name)->setValue(color_ctrl->mR);
+ }
+
+ color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ color_ctrl->mG = sldr_ctrl->getValueF32();
+
+ // move i if it's the max
+ if (color_ctrl->mG >= color_ctrl->mR
+ && color_ctrl->mG >= color_ctrl->mB
+ && color_ctrl->mHasSliderName)
+ {
+ color_ctrl->mI = color_ctrl->mG;
+ std::string name = color_ctrl->mSliderName;
+ name.append("I");
+
+ getChild<LLUICtrl>(name)->setValue(color_ctrl->mG);
+
+ }
+
+ color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ color_ctrl->mB = sldr_ctrl->getValueF32();
+
+ // move i if it's the max
+ if (color_ctrl->mB >= color_ctrl->mR
+ && color_ctrl->mB >= color_ctrl->mG
+ && color_ctrl->mHasSliderName)
+ {
+ color_ctrl->mI = color_ctrl->mB;
+ std::string name = color_ctrl->mSliderName;
+ name.append("I");
+
+ getChild<LLUICtrl>(name)->setValue(color_ctrl->mB);
+ }
+
+ color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ color_ctrl->mA = sldr_ctrl->getValueF32();
+
+ color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+
+void LLFloaterEditWater::onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ color_ctrl->mI = sldr_ctrl->getValueF32();
+
+ // only for sliders where we pass a name
+ if (color_ctrl->mHasSliderName)
+ {
+ // set it to the top
+ F32 maxVal = std::max(std::max(color_ctrl->mR, color_ctrl->mG), color_ctrl->mB);
+ F32 iVal;
+
+ iVal = color_ctrl->mI;
+
+ // get the names of the other sliders
+ std::string rName = color_ctrl->mSliderName;
+ rName.append("R");
+ std::string gName = color_ctrl->mSliderName;
+ gName.append("G");
+ std::string bName = color_ctrl->mSliderName;
+ bName.append("B");
+
+ // handle if at 0
+ if (iVal == 0)
+ {
+ color_ctrl->mR = 0;
+ color_ctrl->mG = 0;
+ color_ctrl->mB = 0;
+
+ // if all at the start
+ // set them all to the intensity
+ }
+ else if (maxVal == 0)
+ {
+ color_ctrl->mR = iVal;
+ color_ctrl->mG = iVal;
+ color_ctrl->mB = iVal;
+ }
+ else
+ {
+ // add delta amounts to each
+ F32 delta = (iVal - maxVal) / maxVal;
+ color_ctrl->mR *= (1.0f + delta);
+ color_ctrl->mG *= (1.0f + delta);
+ color_ctrl->mB *= (1.0f + delta);
+ }
+
+ // set the sliders to the new vals
+ getChild<LLUICtrl>(rName)->setValue(color_ctrl->mR);
+ getChild<LLUICtrl>(gName)->setValue(color_ctrl->mG);
+ getChild<LLUICtrl>(bName)->setValue(color_ctrl->mB);
+ }
+
+ // now update the current parameters and send them to shaders
+ color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+// vector control callbacks
+void LLFloaterEditWater::onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ vector_ctrl->mX = sldr_ctrl->getValueF32();
+
+ vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+// vector control callbacks
+void LLFloaterEditWater::onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ vector_ctrl->mY = sldr_ctrl->getValueF32();
+
+ vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+// vector control callbacks
+void LLFloaterEditWater::onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ vector_ctrl->mZ = sldr_ctrl->getValueF32();
+
+ vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+
+// vector control callbacks
+void LLFloaterEditWater::onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ vector_ctrl->mX = sldr_ctrl->getValueF32();
+
+ vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+// vector control callbacks
+void LLFloaterEditWater::onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ vector_ctrl->mY = sldr_ctrl->getValueF32();
+
+ vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ floatControl->mX = sldr_ctrl->getValueF32() / floatControl->mMult;
+
+ floatControl->update(LLWaterParamManager::getInstance()->mCurParams);
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl)
+{
+ LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+
+ F32 val = sldr_ctrl->getValueF32();
+ expFloatControl->mExp = val;
+ LLWaterParamManager::getInstance()->setDensitySliderValue(val);
+
+ expFloatControl->update(LLWaterParamManager::getInstance()->mCurParams);
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+{
+ LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
+ *color_ctrl = swatch->get();
+
+ color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+ LLWaterParamManager::getInstance()->propagateParameters();
+}
+
+void LLFloaterEditWater::onNormalMapPicked(LLUICtrl* ctrl)
+{
+ LLTextureCtrl* textCtrl = static_cast<LLTextureCtrl*>(ctrl);
+ LLUUID textID = textCtrl->getImageAssetID();
+ LLWaterParamManager::getInstance()->setNormalMapID(textID);
+}
+
+//=============================================================================
+
+void LLFloaterEditWater::reset()
+{
+ if (isNewPreset())
+ {
+ mWaterPresetNameEditor->setValue(LLSD());
+ mSaveButton->setEnabled(FALSE); // will be enabled as soon as users enters a name
+ }
+ else
+ {
+ refreshWaterPresetsList();
+
+ // Disable controls until a water preset to edit is selected.
+ enableEditing(false);
+ }
+}
+
+bool LLFloaterEditWater::isNewPreset() const
+{
+ return mKey.asString() == "new";
+}
+
+void LLFloaterEditWater::refreshWaterPresetsList()
+{
+ mWaterPresetCombo->removeall();
+
+#if 0 // *TODO: enable when we have a clear workflow to edit existing region environment
+ // If the region already has water params, add them to the list.
+ const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings();
+ if (region_settings.getWaterParams().size() != 0)
+ {
+ const std::string& region_name = gAgent.getRegion()->getName();
+ mWaterPresetCombo->add(region_name, LLSD().with(0, region_name).with(1, LLEnvKey::SCOPE_REGION));
+ mWaterPresetCombo->addSeparator();
+ }
+#endif
+
+ std::list<std::string> user_presets, system_presets;
+ LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
+
+ // Add local user presets first.
+ for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ const std::string& name = *it;
+ mWaterPresetCombo->add(name, LLSD().with(0, name).with(1, LLEnvKey::SCOPE_LOCAL)); // [<name>, <scope>]
+ }
+
+ if (user_presets.size() > 0)
+ {
+ mWaterPresetCombo->addSeparator();
+ }
+
+ // Add local system presets.
+ for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
+ {
+ const std::string& name = *it;
+ mWaterPresetCombo->add(name, LLSD().with(0, name).with(1, LLEnvKey::SCOPE_LOCAL)); // [<name>, <scope>]
+ }
+
+ mWaterPresetCombo->setLabel(getString("combo_label"));
+}
+
+void LLFloaterEditWater::enableEditing(bool enable)
+{
+ // Enable/disable water controls.
+ getChild<LLPanel>("panel_water_preset")->setCtrlsEnabled(enable);
+
+ // Enable/disable saving.
+ mSaveButton->setEnabled(enable);
+ mMakeDefaultCheckBox->setEnabled(enable);
+}
+
+void LLFloaterEditWater::saveRegionWater()
+{
+ llassert(getCurrentScope() == LLEnvKey::SCOPE_REGION); // make sure we're editing region water
+
+ LL_DEBUGS("Windlight") << "Saving region water preset" << llendl;
+
+ //LLWaterParamSet region_water = water_mgr.mCurParams;
+
+ // *TODO: save to cached region settings.
+ LL_WARNS("Windlight") << "Saving region water is not fully implemented yet" << LL_ENDL;
+}
+
+std::string LLFloaterEditWater::getCurrentPresetName() const
+{
+ std::string name;
+ LLEnvKey::EScope scope;
+ getSelectedPreset(name, scope);
+ return name;
+}
+
+LLEnvKey::EScope LLFloaterEditWater::getCurrentScope() const
+{
+ std::string name;
+ LLEnvKey::EScope scope;
+ getSelectedPreset(name, scope);
+ return scope;
+}
+
+void LLFloaterEditWater::getSelectedPreset(std::string& name, LLEnvKey::EScope& scope) const
+{
+ if (mWaterPresetNameEditor->getVisible())
+ {
+ name = mWaterPresetNameEditor->getText();
+ scope = LLEnvKey::SCOPE_LOCAL;
+ }
+ else
+ {
+ LLSD combo_val = mWaterPresetCombo->getValue();
+
+ if (!combo_val.isArray()) // manually typed text
+ {
+ name = combo_val.asString();
+ scope = LLEnvKey::SCOPE_LOCAL;
+ }
+ else
+ {
+ name = combo_val[0].asString();
+ scope = (LLEnvKey::EScope) combo_val[1].asInteger();
+ }
+ }
+}
+
+void LLFloaterEditWater::onWaterPresetNameEdited()
+{
+ // Disable saving a water preset having empty name.
+ mSaveButton->setEnabled(!getCurrentPresetName().empty());
+}
+
+void LLFloaterEditWater::onWaterPresetSelected()
+{
+ LLWaterParamSet water_params;
+ std::string name;
+ LLEnvKey::EScope scope;
+
+ getSelectedPreset(name, scope);
+
+ // Display selected preset.
+ if (scope == LLEnvKey::SCOPE_REGION)
+ {
+ water_params.setAll(LLEnvManagerNew::instance().getRegionSettings().getWaterParams());
+ }
+ else // local preset selected
+ {
+ if (!LLWaterParamManager::instance().getParamSet(name, water_params))
+ {
+ // Manually entered string?
+ LL_WARNS("Windlight") << "No water preset named " << name << LL_ENDL;
+ return;
+ }
+ }
+
+ LLEnvManagerNew::instance().useWaterParams(water_params.getAll());
+
+ bool can_edit = (scope == LLEnvKey::SCOPE_LOCAL || LLEnvManagerNew::canEditRegionSettings());
+ enableEditing(can_edit);
+
+ mMakeDefaultCheckBox->setEnabled(scope == LLEnvKey::SCOPE_LOCAL);
+}
+
+bool LLFloaterEditWater::onSaveAnswer(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ // If they choose save, do it. Otherwise, don't do anything
+ if (option == 0)
+ {
+ onSaveConfirmed();
+ }
+
+ return false;
+}
+
+void LLFloaterEditWater::onSaveConfirmed()
+{
+ // Save currently displayed water params to the selected preset.
+ std::string name = getCurrentPresetName();
+
+ LL_DEBUGS("Windlight") << "Saving sky preset " << name << LL_ENDL;
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+ if (water_mgr.hasParamSet(name))
+ {
+ water_mgr.setParamSet(name, water_mgr.mCurParams);
+ }
+ else
+ {
+ water_mgr.addParamSet(name, water_mgr.mCurParams);
+ }
+
+ water_mgr.savePreset(name);
+
+ // Change preference if requested.
+ if (mMakeDefaultCheckBox->getEnabled() && mMakeDefaultCheckBox->getValue())
+ {
+ LL_DEBUGS("Windlight") << name << " is now the new preferred water preset" << llendl;
+ LLEnvManagerNew::instance().setUseWaterPreset(name);
+ }
+
+ closeFloater();
+}
+
+void LLFloaterEditWater::onBtnSave()
+{
+ LLEnvKey::EScope scope;
+ std::string name;
+ getSelectedPreset(name, scope);
+
+ if (scope == LLEnvKey::SCOPE_REGION)
+ {
+ saveRegionWater();
+ closeFloater();
+ return;
+ }
+
+ if (name.empty())
+ {
+ // *TODO: show an alert
+ llwarns << "Empty water preset name" << llendl;
+ return;
+ }
+
+ // Don't allow overwriting system presets.
+ LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
+ if (water_mgr.isSystemPreset(name))
+ {
+ LLNotificationsUtil::add("WLNoEditDefault");
+ return;
+ }
+
+ // Save, ask for confirmation for overwriting an existing preset.
+ if (water_mgr.hasParamSet(name))
+ {
+ LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditWater::onSaveAnswer, this, _1, _2));
+ }
+ else
+ {
+ // new preset, hence no confirmation needed
+ onSaveConfirmed();
+ }
+}
+
+void LLFloaterEditWater::onBtnCancel()
+{
+ closeFloater();
+}
+
+void LLFloaterEditWater::onWaterPresetListChange()
+{
+ std::string name;
+ LLEnvKey::EScope scope;
+ getSelectedPreset(name, scope); // preset being edited
+
+ if (scope == LLEnvKey::SCOPE_LOCAL && !LLWaterParamManager::instance().hasParamSet(name))
+ {
+ // Preset we've been editing doesn't exist anymore. Close the floater.
+ closeFloater(false);
+ }
+ else
+ {
+ // A new preset has been added.
+ // Refresh the presets list, though it may not make sense as the floater is about to be closed.
+ refreshWaterPresetsList();
+ }
+}
+
+void LLFloaterEditWater::onRegionSettingsChange()
+{
+ // If creating a new preset, don't bother.
+ if (isNewPreset())
+ {
+ return;
+ }
+
+ if (getCurrentScope() == LLEnvKey::SCOPE_REGION) // if editing region water
+ {
+ // reset the floater to its initial state
+ reset();
+
+ // *TODO: Notify user?
+ }
+ else // editing a local preset
+ {
+ refreshWaterPresetsList();
+ }
+}
+
+void LLFloaterEditWater::onRegionInfoUpdate()
+{
+ bool can_edit = true;
+
+ // If we've selected the region water for editing.
+ if (getCurrentScope() == LLEnvKey::SCOPE_REGION)
+ {
+ // check whether we have the access
+ can_edit = LLEnvManagerNew::canEditRegionSettings();
+ }
+
+ enableEditing(can_edit);
+}
diff --git a/indra/newview/llfloaterwater.h b/indra/newview/llfloatereditwater.h
index e3db91e80d..2211bca59f 100644
--- a/indra/newview/llfloaterwater.h
+++ b/indra/newview/llfloatereditwater.h
@@ -1,10 +1,10 @@
/**
- * @file llfloaterwindlight.h
- * @brief LLFloaterWater class definition
+ * @file llfloatereditwater.h
+ * @brief Floater to create or edit a water preset
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,17 +24,16 @@
* $/LicenseInfo$
*/
-/*
- * Menu for adjusting the atmospheric settings of the world
- */
-
-#ifndef LL_LLFLOATER_WATER_H
-#define LL_LLFLOATER_WATER_H
+#ifndef LL_LLFLOATEREDITWATER_H
+#define LL_LLFLOATEREDITWATER_H
#include "llfloater.h"
+#include "llenvmanager.h" // for LLEnvKey
-#include <vector>
-#include "llwlparamset.h"
+class LLButton;
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLLineEditor;
struct WaterVector2Control;
struct WaterVector3Control;
@@ -42,66 +41,75 @@ struct WaterColorControl;
struct WaterFloatControl;
struct WaterExpFloatControl;
-/// Menuing system for all of windlight's functionality
-class LLFloaterWater : public LLFloater
+class LLFloaterEditWater : public LLFloater
{
+ LOG_CLASS(LLFloaterEditWater);
+
public:
+ LLFloaterEditWater(const LLSD &key);
- LLFloaterWater(const LLSD& key);
- virtual ~LLFloaterWater();
/*virtual*/ BOOL postBuild();
- /// initialize all
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void draw();
+
+private:
void initCallbacks(void);
- bool newPromptCallback(const LLSD& notification, const LLSD& response);
+ //-- WL stuff begins ------------------------------------------------------
- /// general purpose callbacks for dealing with color controllers
- void onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
- void onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
- void onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
- void onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
- void onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
+ void syncControls(); /// sync up sliders with parameters
- void onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl);
- void onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl);
- void onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl);
+ // general purpose callbacks for dealing with color controllers
+ void onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
+ void onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
+ void onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
+ void onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
+ void onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
+
+ void onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl);
+ void onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl);
+ void onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl);
+
+ void onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl);
+ void onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl);
- void onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl);
- void onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl);
-
void onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl);
void onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl);
- void onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* colorControl);
-
- /// handle if they choose a new normal map
- void onNormalMapPicked(LLUICtrl* ctrl);
+ void onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
- /// when user hits the load preset button
- void onNewPreset();
+ void onNormalMapPicked(LLUICtrl* ctrl); /// handle if they choose a new normal map
- /// when user hits the save preset button
- void onSavePreset();
+ //-- WL stuff ends --------------------------------------------------------
- /// prompts a user when overwriting a preset
- bool saveAlertCallback(const LLSD& notification, const LLSD& response);
+ void reset();
+ bool isNewPreset() const;
+ void refreshWaterPresetsList();
+ void enableEditing(bool enable);
+ void saveRegionWater();
- /// when user hits the save preset button
- void onDeletePreset();
+ std::string getCurrentPresetName() const;
+ LLEnvKey::EScope getCurrentScope() const;
+ void getSelectedPreset(std::string& name, LLEnvKey::EScope& scope) const;
- /// prompts a user when overwriting a preset
- bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
+ void onWaterPresetNameEdited();
+ void onWaterPresetSelected();
+ bool onSaveAnswer(const LLSD& notification, const LLSD& response);
+ void onSaveConfirmed();
- /// what to do when you change the preset name
- void onChangePresetName(LLUICtrl* ctrl);
+ void onBtnSave();
+ void onBtnCancel();
- /// sync up sliders with parameters
- void syncMenu();
+ void onWaterPresetListChange();
+ void onRegionSettingsChange();
+ void onRegionInfoUpdate();
-private:
- static std::set<std::string> sDefaultPresets;
+ LLLineEditor* mWaterPresetNameEditor;
+ LLComboBox* mWaterPresetCombo;
+ LLCheckBoxCtrl* mMakeDefaultCheckBox;
+ LLButton* mSaveButton;
};
-
-#endif
+#endif // LL_LLFLOATEREDITWATER_H
diff --git a/indra/newview/llfloaterenvironmentsettings.cpp b/indra/newview/llfloaterenvironmentsettings.cpp
new file mode 100644
index 0000000000..4dbc8cdee0
--- /dev/null
+++ b/indra/newview/llfloaterenvironmentsettings.cpp
@@ -0,0 +1,282 @@
+/**
+ * @file llfloaterenvironmentsettings.cpp
+ * @brief LLFloaterEnvironmentSettings class definition
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterenvironmentsettings.h"
+
+#include "llcombobox.h"
+#include "llradiogroup.h"
+
+#include "lldaycyclemanager.h"
+#include "llenvmanager.h"
+#include "llwaterparammanager.h"
+#include "llwlparamset.h"
+#include "llwlparammanager.h"
+
+LLFloaterEnvironmentSettings::LLFloaterEnvironmentSettings(const LLSD &key)
+: LLFloater(key)
+ ,mRegionSettingsRadioGroup(NULL)
+ ,mDayCycleSettingsRadioGroup(NULL)
+ ,mWaterPresetCombo(NULL)
+ ,mSkyPresetCombo(NULL)
+ ,mDayCyclePresetCombo(NULL)
+{
+}
+
+// virtual
+BOOL LLFloaterEnvironmentSettings::postBuild()
+{
+ mRegionSettingsRadioGroup = getChild<LLRadioGroup>("region_settings_radio_group");
+ mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSwitchRegionSettings, this));
+
+ mDayCycleSettingsRadioGroup = getChild<LLRadioGroup>("sky_dayc_settings_radio_group");
+ mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSwitchDayCycle, this));
+
+ mWaterPresetCombo = getChild<LLComboBox>("water_settings_preset_combo");
+ mWaterPresetCombo->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSelectWaterPreset, this));
+
+ mSkyPresetCombo = getChild<LLComboBox>("sky_settings_preset_combo");
+ mSkyPresetCombo->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSelectSkyPreset, this));
+
+ mDayCyclePresetCombo = getChild<LLComboBox>("dayc_settings_preset_combo");
+ mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSelectDayCyclePreset, this));
+
+ childSetCommitCallback("ok_btn", boost::bind(&LLFloaterEnvironmentSettings::onBtnOK, this), NULL);
+ getChild<LLUICtrl>("ok_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance()));
+ childSetCommitCallback("cancel_btn", boost::bind(&LLFloaterEnvironmentSettings::onBtnCancel, this), NULL);
+ getChild<LLUICtrl>("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance()));
+
+ setCloseCallback(boost::bind(&LLFloaterEnvironmentSettings::cancel, this));
+
+ LLEnvManagerNew::instance().setPreferencesChangeCallback(boost::bind(&LLFloaterEnvironmentSettings::refresh, this));
+ LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLFloaterEnvironmentSettings::populateDayCyclePresetsList, this));
+ LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEnvironmentSettings::populateSkyPresetsList, this));
+ LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEnvironmentSettings::populateWaterPresetsList, this));
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterEnvironmentSettings::onOpen(const LLSD& key)
+{
+ refresh();
+}
+
+void LLFloaterEnvironmentSettings::onSwitchRegionSettings()
+{
+ getChild<LLView>("user_environment_settings")->setEnabled(mRegionSettingsRadioGroup->getSelectedIndex() != 0);
+
+ apply();
+}
+
+void LLFloaterEnvironmentSettings::onSwitchDayCycle()
+{
+ bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
+
+ mSkyPresetCombo->setEnabled(is_fixed_sky);
+ mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
+
+ apply();
+}
+
+void LLFloaterEnvironmentSettings::onSelectWaterPreset()
+{
+ apply();
+}
+
+void LLFloaterEnvironmentSettings::onSelectSkyPreset()
+{
+ apply();
+}
+
+void LLFloaterEnvironmentSettings::onSelectDayCyclePreset()
+{
+ apply();
+}
+
+void LLFloaterEnvironmentSettings::onBtnOK()
+{
+ // Save and apply new user preferences.
+ bool use_region_settings = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
+ bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
+ std::string water_preset = mWaterPresetCombo->getValue().asString();
+ std::string sky_preset = mSkyPresetCombo->getValue().asString();
+ std::string day_cycle = mDayCyclePresetCombo->getValue().asString();
+
+ LLEnvManagerNew::instance().setUserPrefs(
+ water_preset,
+ sky_preset,
+ day_cycle,
+ use_fixed_sky,
+ use_region_settings);
+
+ // *TODO: This triggers applying user preferences again, which is suboptimal.
+ closeFloater();
+}
+
+void LLFloaterEnvironmentSettings::onBtnCancel()
+{
+ closeFloater();
+}
+
+void LLFloaterEnvironmentSettings::refresh()
+{
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+
+ bool use_region_settings = env_mgr.getUseRegionSettings();
+ bool use_fixed_sky = env_mgr.getUseFixedSky();
+
+ // Set up radio buttons according to user preferences.
+ mRegionSettingsRadioGroup->setSelectedIndex(use_region_settings ? 0 : 1);
+ mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1);
+
+ // Populate the combo boxes with appropriate lists of available presets.
+ populateWaterPresetsList();
+ populateSkyPresetsList();
+ populateDayCyclePresetsList();
+
+ // Enable/disable other controls based on user preferences.
+ getChild<LLView>("user_environment_settings")->setEnabled(!use_region_settings);
+ mSkyPresetCombo->setEnabled(use_fixed_sky);
+ mDayCyclePresetCombo->setEnabled(!use_fixed_sky);
+
+ // Select the current presets in combo boxes.
+ mWaterPresetCombo->selectByValue(env_mgr.getWaterPresetName());
+ mSkyPresetCombo->selectByValue(env_mgr.getSkyPresetName());
+ mDayCyclePresetCombo->selectByValue(env_mgr.getDayCycleName());
+}
+
+void LLFloaterEnvironmentSettings::apply()
+{
+ // Update environment with the user choice.
+ bool use_region_settings = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
+ bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
+ std::string water_preset = mWaterPresetCombo->getValue().asString();
+ std::string sky_preset = mSkyPresetCombo->getValue().asString();
+ std::string day_cycle = mDayCyclePresetCombo->getValue().asString();
+
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ if (use_region_settings)
+ {
+ env_mgr.useRegionSettings();
+ }
+ else
+ {
+ if (use_fixed_sky)
+ {
+ env_mgr.useSkyPreset(sky_preset);
+ }
+ else
+ {
+ env_mgr.useDayCycle(day_cycle, LLEnvKey::SCOPE_LOCAL);
+ }
+
+ env_mgr.useWaterPreset(water_preset);
+ }
+}
+
+void LLFloaterEnvironmentSettings::cancel()
+{
+ // Revert environment to user preferences.
+ LLEnvManagerNew::instance().usePrefs();
+}
+
+void LLFloaterEnvironmentSettings::populateWaterPresetsList()
+{
+ mWaterPresetCombo->removeall();
+
+ std::list<std::string> user_presets, system_presets;
+ LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
+
+ // Add user presets first.
+ for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ mWaterPresetCombo->add(*it);
+ }
+
+ if (user_presets.size() > 0)
+ {
+ mWaterPresetCombo->addSeparator();
+ }
+
+ // Add system presets.
+ for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
+ {
+ mWaterPresetCombo->add(*it);
+ }
+}
+
+void LLFloaterEnvironmentSettings::populateSkyPresetsList()
+{
+ mSkyPresetCombo->removeall();
+
+ LLWLParamManager::preset_name_list_t region_presets; // unused as we don't list region presets here
+ LLWLParamManager::preset_name_list_t user_presets, sys_presets;
+ LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
+
+ // Add user presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ mSkyPresetCombo->add(*it);
+ }
+
+ if (!user_presets.empty())
+ {
+ mSkyPresetCombo->addSeparator();
+ }
+
+ // Add system presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
+ {
+ mSkyPresetCombo->add(*it);
+ }
+}
+
+void LLFloaterEnvironmentSettings::populateDayCyclePresetsList()
+{
+ mDayCyclePresetCombo->removeall();
+
+ LLDayCycleManager::preset_name_list_t user_days, sys_days;
+ LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
+
+ // Add user days.
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
+ {
+ mDayCyclePresetCombo->add(*it);
+ }
+
+ if (user_days.size() > 0)
+ {
+ mDayCyclePresetCombo->addSeparator();
+ }
+
+ // Add system days.
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
+ {
+ mDayCyclePresetCombo->add(*it);
+ }
+}
diff --git a/indra/newview/llfloaterenvironmentsettings.h b/indra/newview/llfloaterenvironmentsettings.h
new file mode 100644
index 0000000000..0ab458a0f6
--- /dev/null
+++ b/indra/newview/llfloaterenvironmentsettings.h
@@ -0,0 +1,71 @@
+/**
+ * @file llfloaterenvironmentsettings.h
+ * @brief LLFloaterEnvironmentSettings class definition
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERENVIRONMENTSETTINGS_H
+#define LL_LLFLOATERENVIRONMENTSETTINGS_H
+
+#include "llfloater.h"
+
+class LLComboBox;
+class LLRadioGroup;
+
+class LLFloaterEnvironmentSettings : public LLFloater
+{
+ LOG_CLASS(LLFloaterEnvironmentSettings);
+
+public:
+ LLFloaterEnvironmentSettings(const LLSD &key);
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+private:
+ void onSwitchRegionSettings();
+ void onSwitchDayCycle();
+
+ void onSelectWaterPreset();
+ void onSelectSkyPreset();
+ void onSelectDayCyclePreset();
+
+ void onBtnOK();
+ void onBtnCancel();
+
+ void refresh(); /// update controls with user prefs
+ void apply();
+ void cancel();
+
+ void populateWaterPresetsList();
+ void populateSkyPresetsList();
+ void populateDayCyclePresetsList();
+
+ LLRadioGroup* mRegionSettingsRadioGroup;
+ LLRadioGroup* mDayCycleSettingsRadioGroup;
+
+ LLComboBox* mWaterPresetCombo;
+ LLComboBox* mSkyPresetCombo;
+ LLComboBox* mDayCyclePresetCombo;
+};
+
+#endif // LL_LLFLOATERENVIRONMENTSETTINGS_H
diff --git a/indra/newview/llfloaterenvsettings.cpp b/indra/newview/llfloaterenvsettings.cpp
deleted file mode 100644
index fcaef1f34b..0000000000
--- a/indra/newview/llfloaterenvsettings.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/**
- * @file llfloaterenvsettings.cpp
- * @brief LLFloaterEnvSettings class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterenvsettings.h"
-
-#include "llfloaterreg.h"
-#include "llfloaterwindlight.h"
-#include "llfloaterwater.h"
-#include "lluictrlfactory.h"
-#include "llsliderctrl.h"
-#include "llcombobox.h"
-#include "llcolorswatch.h"
-#include "llwlanimator.h"
-
-#include "llwlparamset.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llmath.h"
-#include "llviewerwindow.h"
-
-#include "pipeline.h"
-
-#include <sstream>
-
-LLFloaterEnvSettings::LLFloaterEnvSettings(const LLSD& key)
- : LLFloater(key)
-{
-}
-// virtual
-LLFloaterEnvSettings::~LLFloaterEnvSettings()
-{
-}
-// virtual
-BOOL LLFloaterEnvSettings::postBuild()
-{
- // load it up
- initCallbacks();
- syncMenu();
- return TRUE;
-}
-
-void LLFloaterEnvSettings::initCallbacks(void)
-{
- // our three sliders
- getChild<LLUICtrl>("EnvTimeSlider")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeDayTime, this, _1));
- getChild<LLUICtrl>("EnvCloudSlider")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeCloudCoverage, this, _1));
- getChild<LLUICtrl>("EnvWaterFogSlider")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeWaterFogDensity, this, _1, &LLWaterParamManager::instance()->mFogDensity));
-
- // color picker
- getChild<LLUICtrl>("EnvWaterColor")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onChangeWaterColor, this, _1, &LLWaterParamManager::instance()->mFogColor));
-
- // WL Top
- getChild<LLUICtrl>("EnvAdvancedSkyButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onOpenAdvancedSky, this));
- getChild<LLUICtrl>("EnvAdvancedWaterButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onOpenAdvancedWater, this));
- getChild<LLUICtrl>("EnvUseEstateTimeButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onUseEstateTime, this));
-}
-
-// menu maintenance functions
-
-void LLFloaterEnvSettings::syncMenu()
-{
- LLSliderCtrl* sldr;
- sldr = getChild<LLSliderCtrl>("EnvTimeSlider");
-
- // sync the clock
- F32 val = (F32)LLWLParamManager::instance()->mAnimator.getDayTime();
- std::string timeStr = timeToString(val);
-
- LLTextBox* textBox;
- textBox = getChild<LLTextBox>("EnvTimeText");
-
- textBox->setValue(timeStr);
-
- // sync time slider which starts at 6 AM
- val -= 0.25;
- if(val < 0)
- {
- val++;
- }
- sldr->setValue(val);
-
- // sync cloud coverage
- bool err;
- getChild<LLUICtrl>("EnvCloudSlider")->setValue(LLWLParamManager::instance()->mCurParams.getFloat("cloud_shadow", err));
-
- LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
- // sync water params
- LLColor4 col = param_mgr->getFogColor();
- LLColorSwatchCtrl* colCtrl = getChild<LLColorSwatchCtrl>("EnvWaterColor");
- col.mV[3] = 1.0f;
- colCtrl->set(col);
-
- getChild<LLUICtrl>("EnvWaterFogSlider")->setValue(param_mgr->mFogDensity.mExp);
- param_mgr->setDensitySliderValue(param_mgr->mFogDensity.mExp);
-
- // turn off Use Estate Time button if it's already being used
- if(LLWLParamManager::instance()->mAnimator.mUseLindenTime)
- {
- getChildView("EnvUseEstateTimeButton")->setEnabled(FALSE);
- } else {
- getChildView("EnvUseEstateTimeButton")->setEnabled(TRUE);
- }
-
- if(!gPipeline.canUseVertexShaders())
- {
- getChildView("EnvWaterColor")->setEnabled(FALSE);
- getChildView("EnvWaterColorText")->setEnabled(FALSE);
- //getChildView("EnvAdvancedWaterButton")->setEnabled(FALSE);
- }
- else
- {
- getChildView("EnvWaterColor")->setEnabled(TRUE);
- getChildView("EnvWaterColorText")->setEnabled(TRUE);
- //getChildView("EnvAdvancedWaterButton")->setEnabled(TRUE);
- }
-
- // only allow access to these if they are using windlight
- if(!gPipeline.canUseWindLightShaders())
- {
-
- getChildView("EnvCloudSlider")->setEnabled(FALSE);
- getChildView("EnvCloudText")->setEnabled(FALSE);
- //getChildView("EnvAdvancedSkyButton")->setEnabled(FALSE);
- }
- else
- {
- getChildView("EnvCloudSlider")->setEnabled(TRUE);
- getChildView("EnvCloudText")->setEnabled(TRUE);
- //getChildView("EnvAdvancedSkyButton")->setEnabled(TRUE);
- }
-}
-
-void LLFloaterEnvSettings::onChangeDayTime(LLUICtrl* ctrl)
-{
- LLSliderCtrl* sldr = static_cast<LLSliderCtrl*>(ctrl);
-
- // deactivate animator
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- F32 val = sldr->getValueF32() + 0.25f;
- if(val > 1.0)
- {
- val--;
- }
-
- LLWLParamManager::instance()->mAnimator.setDayTime((F64)val);
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
-}
-
-void LLFloaterEnvSettings::onChangeCloudCoverage(LLUICtrl* ctrl)
-{
- LLSliderCtrl* sldr = static_cast<LLSliderCtrl*>(ctrl);
-
- // deactivate animator
- //LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- //LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- F32 val = sldr->getValueF32();
- LLWLParamManager::instance()->mCurParams.set("cloud_shadow", val);
-}
-
-void LLFloaterEnvSettings::onChangeWaterFogDensity(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl)
-{
- LLSliderCtrl* sldr;
- sldr = getChild<LLSliderCtrl>("EnvWaterFogSlider");
-
- F32 val = sldr->getValueF32();
- expFloatControl->mExp = val;
- LLWaterParamManager::instance()->setDensitySliderValue(val);
-
- expFloatControl->update(LLWaterParamManager::instance()->mCurParams);
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterEnvSettings::onChangeWaterColor(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
- *colorControl = swatch->get();
-
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-
-void LLFloaterEnvSettings::onOpenAdvancedSky()
-{
- LLFloaterReg::showInstance("env_windlight");
-}
-
-void LLFloaterEnvSettings::onOpenAdvancedWater()
-{
- LLFloaterReg::showInstance("env_water");
-}
-
-
-void LLFloaterEnvSettings::onUseEstateTime()
-{
- LLFloaterWindLight* wl = LLFloaterReg::findTypedInstance<LLFloaterWindLight>("env_windlight");
- if(wl)
- {
- LLComboBox* box = wl->getChild<LLComboBox>("WLPresetsCombo");
- box->selectByValue("");
- }
-
- LLWLParamManager::instance()->mAnimator.mIsRunning = true;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = true;
-}
-
-std::string LLFloaterEnvSettings::timeToString(F32 curTime)
-{
- S32 hours;
- S32 min;
-
- // get hours and minutes
- hours = (S32) (24.0 * curTime);
- curTime -= ((F32) hours / 24.0f);
- min = llround(24.0f * 60.0f * curTime);
-
- // handle case where it's 60
- if(min == 60)
- {
- hours++;
- min = 0;
- }
-
- std::string newTime = getString("timeStr");
- struct tm * timeT;
- time_t secT = time(0);
- timeT = gmtime (&secT);
-
- timeT->tm_hour = hours;
- timeT->tm_min = min;
- secT = mktime (timeT);
- secT -= LLStringOps::getLocalTimeOffset ();
-
- LLSD substitution;
- substitution["datetime"] = (S32) secT;
-
- LLStringUtil::format (newTime, substitution);
- return newTime;
-}
diff --git a/indra/newview/llfloaterenvsettings.h b/indra/newview/llfloaterenvsettings.h
deleted file mode 100644
index a6280cfb97..0000000000
--- a/indra/newview/llfloaterenvsettings.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * @file llfloaterskysettings.h
- * @brief LLFloaterEnvSettings class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-/*
- * Simple menu for adjusting the atmospheric settings of the world
- */
-
-#ifndef LL_LLFLOATERENVSETTINGS_H
-#define LL_LLFLOATERENVSETTINGS_H
-
-#include "llfloater.h"
-
-struct WaterColorControl;
-struct WaterExpFloatControl;
-
-/// Menuing system for all of windlight's functionality
-class LLFloaterEnvSettings : public LLFloater
-{
-public:
-
- LLFloaterEnvSettings(const LLSD& key);
- /*virtual*/ ~LLFloaterEnvSettings();
- /*virtual*/ BOOL postBuild();
- /// initialize all the callbacks for the menu
- void initCallbacks(void);
-
- /// handle if time of day is changed
- void onChangeDayTime(LLUICtrl* ctrl);
-
- /// handle if cloud coverage is changed
- void onChangeCloudCoverage(LLUICtrl* ctrl);
-
- /// handle change in water fog density
- void onChangeWaterFogDensity(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl);
-
- /// handle change in water fog color
- void onChangeWaterColor(LLUICtrl* ctrl, WaterColorControl* colorControl);
-
- /// open the advanced sky settings menu
- void onOpenAdvancedSky();
-
- /// open the advanced water settings menu
- void onOpenAdvancedWater();
-
- /// sync time with the server
- void onUseEstateTime();
-
- //// menu management
-
- /// sync up sliders with parameters
- void syncMenu();
-
- /// convert the present time to a digital clock time
- std::string timeToString(F32 curTime);
-
-private:
-};
-
-
-#endif
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index 627defd006..3012638d44 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -71,9 +71,18 @@ void LLFloaterHelpBrowser::buildURLHistory()
}
}
+void LLFloaterHelpBrowser::onOpen(const LLSD& key)
+{
+ gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+}
+
//virtual
void LLFloaterHelpBrowser::onClose(bool app_quitting)
{
+ if (!app_quitting)
+ {
+ gSavedSettings.setBOOL("HelpFloaterOpen", FALSE);
+ }
// really really destroy the help browser when it's closed, it'll be recreated.
destroy(); // really destroy this dialog on closure, it's relatively heavyweight.
}
diff --git a/indra/newview/llfloaterhelpbrowser.h b/indra/newview/llfloaterhelpbrowser.h
index 2731c81b9c..afe0f4df69 100644
--- a/indra/newview/llfloaterhelpbrowser.h
+++ b/indra/newview/llfloaterhelpbrowser.h
@@ -42,6 +42,7 @@ class LLFloaterHelpBrowser :
/*virtual*/ BOOL postBuild();
/*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void onOpen(const LLSD& key);
// inherited from LLViewerMediaObserver
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 0d0c1f594d..9b7593ce61 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -1818,6 +1818,7 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
mClearBtn(NULL),
mMatureCtrl(NULL),
mPushRestrictionCtrl(NULL),
+ mSeeAvatarsCtrl(NULL),
mParcel(parcel)
{
}
@@ -1860,6 +1861,9 @@ BOOL LLPanelLandOptions::postBuild()
mPushRestrictionCtrl = getChild<LLCheckBoxCtrl>( "PushRestrictCheck");
childSetCommitCallback("PushRestrictCheck", onCommitAny, this);
+ mSeeAvatarsCtrl = getChild<LLCheckBoxCtrl>( "SeeAvatarsCheck");
+ childSetCommitCallback("SeeAvatarsCheck", onCommitAny, this);
+
mCheckShowDirectory = getChild<LLCheckBoxCtrl>( "ShowDirectoryCheck");
childSetCommitCallback("ShowDirectoryCheck", onCommitAny, this);
@@ -1952,7 +1956,7 @@ void LLPanelLandOptions::refresh()
mCheckEditLand ->set(FALSE);
mCheckEditLand ->setEnabled(FALSE);
-
+
mCheckSafe ->set(FALSE);
mCheckSafe ->setEnabled(FALSE);
@@ -1968,6 +1972,9 @@ void LLPanelLandOptions::refresh()
mPushRestrictionCtrl->set(FALSE);
mPushRestrictionCtrl->setEnabled(FALSE);
+ mSeeAvatarsCtrl->set(TRUE);
+ mSeeAvatarsCtrl->setEnabled(FALSE);
+
mLandingTypeCombo->setCurrentByIndex(0);
mLandingTypeCombo->setEnabled(FALSE);
@@ -2001,7 +2008,7 @@ void LLPanelLandOptions::refresh()
BOOL can_change_terraform = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_EDIT);
mCheckEditLand ->set( parcel->getAllowTerraform() );
mCheckEditLand ->setEnabled( can_change_terraform );
-
+
mCheckSafe ->set( !parcel->getAllowDamage() );
mCheckSafe ->setEnabled( can_change_options );
@@ -2027,6 +2034,10 @@ void LLPanelLandOptions::refresh()
mPushRestrictionCtrl->setEnabled(can_change_options);
}
+ mSeeAvatarsCtrl->set(parcel->getSeeAVs());
+ mSeeAvatarsCtrl->setLabel(getString("see_avs_text"));
+ mSeeAvatarsCtrl->setEnabled(can_change_options && parcel->getHaveNewParcelLimitData());
+
BOOL can_change_landing_point = LLViewerParcelMgr::isParcelModifiableByAgent(parcel,
GP_LAND_SET_LANDING_POINT);
mLandingTypeCombo->setCurrentByIndex((S32)parcel->getLandingType());
@@ -2231,6 +2242,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
BOOL allow_publish = FALSE;
BOOL mature_publish = self->mMatureCtrl->get();
BOOL push_restriction = self->mPushRestrictionCtrl->get();
+ BOOL see_avs = self->mSeeAvatarsCtrl->get();
BOOL show_directory = self->mCheckShowDirectory->get();
// we have to get the index from a lookup, not from the position in the dropdown!
S32 category_index = LLParcel::getCategoryFromString(self->mCategoryCombo->getSelectedValue());
@@ -2264,6 +2276,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
parcel->setCategory((LLParcel::ECategory)category_index);
parcel->setLandingType((LLParcel::ELandingType)landing_type_index);
parcel->setSnapshotID(snapshot_id);
+ parcel->setSeeAVs(see_avs);
// Send current parcel data upstream to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 8a70fa24d8..6fceca1acd 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -348,6 +348,7 @@ private:
LLCheckBoxCtrl *mMatureCtrl;
LLCheckBoxCtrl *mPushRestrictionCtrl;
+ LLCheckBoxCtrl *mSeeAvatarsCtrl;
LLSafeHandle<LLParcelSelection>& mParcel;
};
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index e8da1aa42c..ab6753b4be 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -98,7 +98,8 @@
#include "llvfile.h"
#include "llvfs.h"
#include "llcallbacklist.h"
-
+#include "llviewerobjectlist.h"
+#include "llanimationstates.h"
#include "glod/glod.h"
//static
@@ -177,6 +178,80 @@ std::string lod_label_name[NUM_LOD+1] =
"I went off the end of the lod_label_name array. Me so smart."
};
+
+#define LL_DEGENERACY_TOLERANCE 1e-7f
+
+inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
+{
+ volatile F32 p0 = a[0] * b[0];
+ volatile F32 p1 = a[1] * b[1];
+ volatile F32 p2 = a[2] * b[2];
+ return p0 + p1 + p2;
+}
+
+bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE)
+{
+ // small area check
+ {
+ LLVector4a edge1; edge1.setSub( a, b );
+ LLVector4a edge2; edge2.setSub( a, c );
+ //////////////////////////////////////////////////////////////////////////
+ /// Linden Modified
+ //////////////////////////////////////////////////////////////////////////
+
+ // If no one edge is more than 10x longer than any other edge, we weaken
+ // the tolerance by a factor of 1e-4f.
+
+ LLVector4a edge3; edge3.setSub( c, b );
+ const F32 len1sq = edge1.dot3(edge1).getF32();
+ const F32 len2sq = edge2.dot3(edge2).getF32();
+ const F32 len3sq = edge3.dot3(edge3).getF32();
+ bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq);
+ bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq);
+ bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq);
+ if ( abOK && acOK && cbOK )
+ {
+ tolerance *= 1e-4f;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ /// End Modified
+ //////////////////////////////////////////////////////////////////////////
+
+ LLVector4a cross; cross.setCross3( edge1, edge2 );
+
+ LLVector4a edge1b; edge1b.setSub( b, a );
+ LLVector4a edge2b; edge2b.setSub( b, c );
+ LLVector4a crossb; crossb.setCross3( edge1b, edge2b );
+
+ if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance ))
+ {
+ return true;
+ }
+ }
+
+ // point triangle distance check
+ {
+ LLVector4a Q; Q.setSub(a, b);
+ LLVector4a R; R.setSub(c, b);
+
+ const F32 QQ = dot3fpu(Q, Q);
+ const F32 RR = dot3fpu(R, R);
+ const F32 QR = dot3fpu(R, Q);
+
+ volatile F32 QQRR = QQ * RR;
+ volatile F32 QRQR = QR * QR;
+ F32 Det = (QQRR - QRQR);
+
+ if( Det == 0.0f )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool validate_face(const LLVolumeFace& face)
{
for (U32 i = 0; i < face.mNumIndices; ++i)
@@ -188,6 +263,31 @@ bool validate_face(const LLVolumeFace& face)
}
}
+ if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
+ {
+ llwarns << "Face has invalid number of indices." << llendl;
+ return false;
+ }
+
+ /*const LLVector4a scale(0.5f);
+
+ for (U32 i = 0; i < face.mNumIndices; i+=3)
+ {
+ U16 idx1 = face.mIndices[i];
+ U16 idx2 = face.mIndices[i+1];
+ U16 idx3 = face.mIndices[i+2];
+
+ LLVector4a v1; v1.setMul(face.mPositions[idx1], scale);
+ LLVector4a v2; v2.setMul(face.mPositions[idx2], scale);
+ LLVector4a v3; v3.setMul(face.mPositions[idx3], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ llwarns << "Degenerate face found!" << llendl;
+ return false;
+ }
+ }*/
+
return true;
}
@@ -313,15 +413,17 @@ BOOL LLFloaterModelPreview::postBuild()
childSetCommitCallback("pelvis_offset", onPelvisOffsetCommit, this);
childSetCommitCallback("lod_file_or_limit", refresh, this);
- childSetCommitCallback("physics_load_radio", refresh, this);
+ childSetCommitCallback("physics_load_radio", onPhysicsLoadRadioCommit, this);
//childSetCommitCallback("physics_optimize", refresh, this);
//childSetCommitCallback("physics_use_hull", refresh, this);
childDisable("upload_skin");
childDisable("upload_joints");
-
+
childDisable("ok_btn");
+ childSetCommitCallback("confirm_checkbox", refresh, this);
+
mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn");
mCommitCallbackRegistrar.add("ModelImport.ViewOption.Action", boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _2));
@@ -381,12 +483,6 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
{
sInstance = NULL;
- if ( mModelPreview && mModelPreview->getResetJointFlag() )
- {
- gAgentAvatarp->resetJointPositions();
- }
-
-
if ( mModelPreview )
{
delete mModelPreview;
@@ -475,6 +571,29 @@ void LLFloaterModelPreview::onPelvisOffsetCommit( LLUICtrl*, void* userdata )
}
//static
+void LLFloaterModelPreview::onPhysicsLoadRadioCommit( LLUICtrl*, void *userdata)
+{
+ LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
+ if (fmp)
+ {
+ if (fmp->childGetValue("physics_use_lod").asBoolean())
+ {
+ onPhysicsUseLOD(NULL,NULL);
+ }
+ if (fmp->childGetValue("physics_load_from_file").asBoolean())
+ {
+
+ }
+ LLModelPreview *model_preview = fmp->mModelPreview;
+ if (model_preview)
+ {
+ model_preview->refresh();
+ model_preview->updateStatusMessages();
+ }
+ }
+}
+
+//static
void LLFloaterModelPreview::onUploadJointsCommit(LLUICtrl*,void* userdata)
{
LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata;
@@ -578,6 +697,11 @@ void LLFloaterModelPreview::draw()
childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING)));
}
else
+ if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING )
+ {
+ childSetTextArg("status", "[STATUS]", getString("status_parse_error"));
+ }
+ else
{
childSetTextArg("status", "[STATUS]", getString("status_idle"));
}
@@ -997,7 +1121,7 @@ LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* pre
std::deque<std::string>& jointsFromNodes )
: mJointList( jointMap )
, mJointsFromNode( jointsFromNodes )
-, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE)
+, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0)
{
mJointMap["mPelvis"] = "mPelvis";
mJointMap["mTorso"] = "mTorso";
@@ -1162,11 +1286,7 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3&
void LLModelLoader::run()
{
- if (!doLoadModel())
- {
- mPreview = NULL;
- }
-
+ doLoadModel();
doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
}
@@ -1230,6 +1350,23 @@ bool LLModelLoader::doLoadModel()
return false;
}
+ //Verify some basic properties of the dae
+ //1. Basic validity check on controller
+ U32 controllerCount = (int) db->getElementCount( NULL, "controller" );
+ bool result = false;
+ for ( int i=0; i<controllerCount; ++i )
+ {
+ domController* pController = NULL;
+ db->getElement( (daeElement**) &pController, i , NULL, "controller" );
+ result = mPreview->verifyController( pController );
+ if (!result)
+ {
+ setLoadState( ERROR_PARSING );
+ return true;
+ }
+ }
+
+
//get unit scale
mTransform.setIdentity();
@@ -1280,7 +1417,7 @@ bool LLModelLoader::doLoadModel()
if(model->getStatus() != LLModel::NO_ERRORS)
{
setLoadState(ERROR_PARSING + model->getStatus()) ;
- return true ; //abort
+ return false; //abort
}
if (model.notNull() && validate_model(model))
@@ -1577,7 +1714,7 @@ bool LLModelLoader::doLoadModel()
{
//llinfos<<"joint "<<lookingForJoint.c_str()<<llendl;
LLMatrix4 jointTransform = mJointList[lookingForJoint];
- LLJoint* pJoint = gAgentAvatarp->getJoint( lookingForJoint );
+ LLJoint* pJoint = mPreview->getPreviewAvatar()->getJoint( lookingForJoint );
if ( pJoint )
{
pJoint->storeCurrentXform( jointTransform.getTranslation() );
@@ -1639,7 +1776,7 @@ bool LLModelLoader::doLoadModel()
{
if (pos.getCount() <= j+2)
{
- llerrs << "WTF?" << llendl;
+ llerrs << "Invalid position array size." << llendl;
}
LLVector3 v(pos[j], pos[j+1], pos[j+2]);
@@ -1764,11 +1901,19 @@ bool LLModelLoader::doLoadModel()
{
llwarns << "document has no visual_scene" << llendl;
setLoadState( ERROR_PARSING );
- return false;
+ return true;
}
+
setLoadState( DONE );
- processElement(scene);
+ bool badElement = false;
+
+ processElement( scene, badElement );
+
+ if ( badElement )
+ {
+ setLoadState( ERROR_PARSING );
+ }
return true;
}
@@ -2129,7 +2274,8 @@ void LLModelLoader::loadTextures()
iter->second[i].mMaterial[j].mDiffuseMap =
LLViewerTextureManager::getFetchedTextureFromUrl("file://" + iter->second[i].mMaterial[j].mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW);
iter->second[i].mMaterial[j].mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE);
- iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage();
+ iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage(0, F32_MAX);
+ mNumOfFetchingTextures++ ;
}
}
}
@@ -2158,6 +2304,90 @@ bool LLModelLoader::isNodeAJoint( domNode* pNode )
return false;
}
+//-----------------------------------------------------------------------------
+// verifyCount
+//-----------------------------------------------------------------------------
+bool LLModelPreview::verifyCount( int expected, int result )
+{
+ if ( expected != result )
+ {
+ llinfos<< "Error: (expected/got)"<<expected<<"/"<<result<<"verts"<<llendl;
+ return false;
+ }
+ return true;
+}
+//-----------------------------------------------------------------------------
+// verifyController
+//-----------------------------------------------------------------------------
+bool LLModelPreview::verifyController( domController* pController )
+{
+
+ bool result = true;
+
+ domSkin* pSkin = pController->getSkin();
+
+ if ( pSkin )
+ {
+ xsAnyURI & uri = pSkin->getSource();
+ domElement* pElement = uri.getElement();
+
+ if ( !pElement )
+ {
+ llinfos<<"Can't resolve skin source"<<llendl;
+ return false;
+ }
+
+ daeString type_str = pElement->getTypeName();
+ if ( stricmp(type_str, "geometry") == 0 )
+ {
+ //Skin is reference directly by geometry and get the vertex count from skin
+ domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights();
+ U32 vertexWeightsCount = pVertexWeights->getCount();
+ domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement();
+ domMesh* pMesh = pGeometry->getMesh();
+
+ if ( pMesh )
+ {
+ //Get vertex count from geometry
+ domVertices* pVertices = pMesh->getVertices();
+ if ( !pVertices )
+ {
+ llinfos<<"No vertices!"<<llendl;
+ return false;
+ }
+
+ if ( pVertices )
+ {
+ xsAnyURI src = pVertices->getInput_array()[0]->getSource();
+ domSource* pSource = (domSource*) (domElement*) src.getElement();
+ U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount();
+ result = verifyCount( verticesCount, vertexWeightsCount );
+ if ( !result )
+ {
+ return result;
+ }
+ }
+ }
+
+ U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount();
+ result = verifyCount( vcountCount, vertexWeightsCount );
+ if ( !result )
+ {
+ return result;
+ }
+
+ domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array();
+ U32 sum = 0;
+ for (size_t i=0; i<vcountCount; i++)
+ {
+ sum += pVertexWeights->getVcount()->getValue()[i];
+ }
+ result = verifyCount( sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount() );
+ }
+ }
+
+ return result;
+}
//-----------------------------------------------------------------------------
// extractTranslation()
@@ -2268,7 +2498,7 @@ daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::strin
return NULL;
}
-void LLModelLoader::processElement(daeElement* element)
+void LLModelLoader::processElement( daeElement* element, bool& badElement )
{
LLMatrix4 saved_transform = mTransform;
@@ -2301,8 +2531,11 @@ void LLModelLoader::processElement(daeElement* element)
{
domFloat3 dom_value = scale->getValue();
+
+ LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]);
+ scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes
LLMatrix4 scaling;
- scaling.initScale(LLVector3(dom_value[0], dom_value[1], dom_value[2]));
+ scaling.initScale(scale_vector);
scaling *= mTransform;
mTransform = scaling;
@@ -2365,6 +2598,12 @@ void LLModelLoader::processElement(daeElement* element)
}
}
}
+ else
+ {
+ llinfos<<"Unable to resolve geometry URL."<<llendl;
+ badElement = true;
+ }
+
}
domInstance_node* instance_node = daeSafeCast<domInstance_node>(element);
@@ -2373,7 +2612,7 @@ void LLModelLoader::processElement(daeElement* element)
daeElement* instance = instance_node->getUrl().getElement();
if (instance)
{
- processElement(instance);
+ processElement(instance,badElement);
}
}
@@ -2381,7 +2620,7 @@ void LLModelLoader::processElement(daeElement* element)
daeTArray< daeSmartRef<daeElement> > children = element->getChildren();
for (S32 i = 0; i < children.getCount(); i++)
{
- processElement(children[i]);
+ processElement(children[i],badElement);
}
domNode* node = daeSafeCast<domNode>(element);
@@ -2597,6 +2836,7 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
mLoading = false;
mLoadState = LLModelLoader::STARTING;
mGroup = 0;
+ mLODFrozen = false;
mBuildShareTolerance = 0.f;
mBuildQueueMode = GLOD_QUEUE_GREEDY;
mBuildBorderMode = GLOD_BORDER_UNLOCK;
@@ -2605,6 +2845,13 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
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;
@@ -2649,13 +2896,15 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
mMasterLegacyJointList.push_front("mHipLeft");
mMasterLegacyJointList.push_front("mKneeLeft");
mMasterLegacyJointList.push_front("mFootLeft");
+
+ createPreviewAvatar();
}
LLModelPreview::~LLModelPreview()
{
if (mModelLoader)
{
- delete mModelLoader;
+ mModelLoader->mPreview = NULL;
mModelLoader = NULL;
}
//*HACK : *TODO : turn this back on when we understand why this crashes
@@ -2670,7 +2919,8 @@ U32 LLModelPreview::calcResourceCost()
if (mFMP && mModelLoader)
{
- if ( getLoadState() < LLModelLoader::ERROR_PARSING )
+ const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
+ if ( getLoadState() < LLModelLoader::ERROR_PARSING && confirmed_checkbox )
{
mFMP->childEnable("ok_btn");
}
@@ -2702,7 +2952,7 @@ U32 LLModelPreview::calcResourceCost()
if ( mFMP && mFMP->childGetValue("upload_joints").asBoolean() )
{
- gAgentAvatarp->setPelvisOffset( mPelvisZOffset );
+ getPreviewAvatar()->setPelvisOffset( mPelvisZOffset );
}
F32 streaming_cost = 0.f;
@@ -2812,7 +3062,8 @@ void LLModelPreview::rebuildUploadData()
F32 max_scale = 0.f;
- if ( mBaseScene.size() > 0 )
+ const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
+ if ( mBaseScene.size() > 0 && confirmed_checkbox )
{
mFMP->childEnable("ok_btn");
}
@@ -3216,6 +3467,8 @@ void LLModelPreview::loadModelCallback(S32 lod)
}
mLoading = false;
+ if (mFMP)
+ mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->set(FALSE);
refresh();
mModelLoadedSignal();
@@ -3229,7 +3482,7 @@ void LLModelPreview::resetPreviewTarget()
mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f;
}
- setPreviewTarget(mPreviewScale.magVec()*2.f);
+ setPreviewTarget(mPreviewScale.magVec()*10.f);
}
void LLModelPreview::generateNormals()
@@ -3247,6 +3500,8 @@ void LLModelPreview::generateNormals()
F32 angle_cutoff = mFMP->childGetValue("crease_angle").asReal();
+ mRequestedCreaseAngle[which_lod] = angle_cutoff;
+
angle_cutoff *= DEG_TO_RAD;
if (which_lod == 3 && !mBaseModel.empty())
@@ -3266,7 +3521,7 @@ void LLModelPreview::generateNormals()
mVertexBuffer[which_lod].clear();
refresh();
-
+ updateStatusMessages();
}
void LLModelPreview::clearMaterials()
@@ -3342,6 +3597,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
{
lod_mode = iface->getFirstSelectedIndex();
}
+ mRequestedLoDMode[mPreviewLOD] = lod_mode;
F32 lod_error_threshold = mFMP->childGetValue("lod_error_threshold").asReal();
@@ -3365,6 +3621,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
{
build_operator = iface->getFirstSelectedIndex();
}
+ mRequestedBuildOperator[mPreviewLOD] = build_operator;
if (build_operator == 0)
{
@@ -3381,6 +3638,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
{
queue_mode = iface->getFirstSelectedIndex();
}
+ mRequestedQueueMode[mPreviewLOD] = queue_mode;
if (queue_mode == 0)
{
@@ -3402,6 +3660,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
{
border_mode = iface->getFirstSelectedIndex();
}
+ mRequestedBorderMode[mPreviewLOD] = border_mode;
if (border_mode == 0)
{
@@ -3437,6 +3696,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
mBuildShareTolerance = share_tolerance;
object_dirty = true;
}
+ mRequestedShareTolerance[mPreviewLOD] = share_tolerance;
if (mGroup == 0)
{
@@ -3545,6 +3805,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
U32 submeshes = 0;
mRequestedTriangleCount[lod] = triangle_count;
+ mRequestedErrorThreshold[lod] = lod_error_threshold;
glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode);
stop_gloderror();
@@ -3739,7 +4000,35 @@ void LLModelPreview::updateStatusMessages()
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]->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
+ const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j);
+ for (S32 k = 0; k < face.mNumIndices && !has_degenerate; )
+ {
+ LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale);
+ LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale);
+ LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale);
+
+ if (ll_is_degenerate(v1,v2,v3))
+ {
+ has_degenerate = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH]));
std::string mesh_status_na = mFMP->getString("mesh_status_na");
@@ -3832,6 +4121,21 @@ void LLModelPreview::updateStatusMessages()
}
}
+
+ //make sure no hulls have more than 256 points in them
+ for (U32 i = 0; upload_ok && i < mModel[LLModel::LOD_PHYSICS].size(); ++i)
+ {
+ LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i];
+
+ for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j)
+ {
+ if (mdl->mPhysics.mHull[j].size() > 256)
+ {
+ upload_ok = false;
+ }
+ }
+ }
+
bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false;
bool skinAndRigOk = true;
@@ -3851,10 +4155,23 @@ void LLModelPreview::updateStatusMessages()
}
}
- if ( upload_ok && !errorStateFromLoader && skinAndRigOk )
+ if(upload_ok && mModelLoader)
+ {
+ if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
+ {
+ upload_ok = false ;
+ }
+ }
+
+ const BOOL confirmed_checkbox = mFMP->getChild<LLCheckBoxCtrl>("confirm_checkbox")->getValue().asBoolean();
+ if ( upload_ok && !errorStateFromLoader && skinAndRigOk && !has_degenerate && confirmed_checkbox)
{
mFMP->childEnable("ok_btn");
}
+ else
+ {
+ mFMP->childDisable("ok_btn");
+ }
//add up physics triangles etc
S32 start = 0;
@@ -4021,6 +4338,9 @@ void LLModelPreview::updateStatusMessages()
{ // auto generate, also the default case for wizard which has no radio selection
fmp->mLODMode[mPreviewLOD] = 1;
+ //don't actually regenerate lod when refreshing UI
+ mLODFrozen = true;
+
for (U32 i = 0; i < num_file_controls; ++i)
{
mFMP->childDisable(file_controls[i]);
@@ -4033,20 +4353,21 @@ void LLModelPreview::updateStatusMessages()
//if (threshold)
{
- U32 lod_mode = 0;
- LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode");
- if (iface)
- {
- lod_mode = iface->getFirstSelectedIndex();
- }
-
LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>("lod_error_threshold");
LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit");
limit->setMaxValue(mMaxTriangleLimit);
- limit->setValue(mRequestedTriangleCount[mPreviewLOD]);
+ limit->forceSetValue(mRequestedTriangleCount[mPreviewLOD]);
+
+ threshold->forceSetValue(mRequestedErrorThreshold[mPreviewLOD]);
- if (lod_mode == 0)
+ mFMP->getChild<LLComboBox>("lod_mode")->selectNthItem(mRequestedLoDMode[mPreviewLOD]);
+ mFMP->getChild<LLComboBox>("build_operator")->selectNthItem(mRequestedBuildOperator[mPreviewLOD]);
+ mFMP->getChild<LLComboBox>("queue_mode")->selectNthItem(mRequestedQueueMode[mPreviewLOD]);
+ mFMP->getChild<LLComboBox>("border_mode")->selectNthItem(mRequestedBorderMode[mPreviewLOD]);
+ mFMP->getChild<LLSpinCtrl>("share_tolerance")->setValue(mRequestedShareTolerance[mPreviewLOD]);
+
+ if (mRequestedLoDMode[mPreviewLOD] == 0)
{
limit->setVisible(true);
threshold->setVisible(false);
@@ -4060,6 +4381,8 @@ void LLModelPreview::updateStatusMessages()
threshold->setVisible(true);
}
}
+
+ mLODFrozen = false;
}
}
@@ -4075,6 +4398,20 @@ void LLModelPreview::updateStatusMessages()
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]);
+ }
+
}
void LLModelPreview::setPreviewTarget(F32 distance)
@@ -4189,11 +4526,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
const LLModel::weight_list& weight_list = base_mdl->getJointInfluences(pos);
LLVector4 w(0,0,0,0);
- if (weight_list.size() > 4)
- {
- llerrs << "WTF?" << llendl;
- }
-
+
for (U32 i = 0; i < weight_list.size(); ++i)
{
F32 wght = llmin(weight_list[i].mWeight, 0.999999f);
@@ -4241,42 +4574,6 @@ void LLModelPreview::update()
}
//-----------------------------------------------------------------------------
-// changeAvatarsJointPositions()
-//-----------------------------------------------------------------------------
-void LLModelPreview::changeAvatarsJointPositions( LLModel* pModel )
-{
- if ( mMasterJointList.empty() )
- {
- return;
- }
-
- std::vector<std::string> :: const_iterator jointListItBegin = pModel->mSkinInfo.mJointNames.begin();
- std::vector<std::string> :: const_iterator jointListItEnd = pModel->mSkinInfo.mJointNames.end();
-
- S32 index = 0;
- for ( ; jointListItBegin!=jointListItEnd; ++jointListItBegin, ++index )
- {
- std::string elem = *jointListItBegin;
- //llinfos<<"joint "<<elem<<llendl;
-
- S32 matrixCnt = pModel->mSkinInfo.mAlternateBindMatrix.size();
- if ( matrixCnt < 1 )
- {
- llinfos<<"Total WTF moment :"<<matrixCnt<<llendl;
- }
- else
- {
- LLMatrix4 jointTransform = pModel->mSkinInfo.mAlternateBindMatrix[index];
-
- LLJoint* pJoint = gAgentAvatarp->getJoint( elem );
- if ( pJoint )
- {
- pJoint->storeCurrentXform( jointTransform.getTranslation() );
- }
- }
- }
-}
-//-----------------------------------------------------------------------------
// getTranslationForJointOffset()
//-----------------------------------------------------------------------------
LLVector3 LLModelPreview::getTranslationForJointOffset( std::string joint )
@@ -4290,6 +4587,30 @@ LLVector3 LLModelPreview::getTranslationForJointOffset( std::string joint )
return LLVector3(0.0f,0.0f,0.0f);
}
//-----------------------------------------------------------------------------
+// createPreviewAvatar
+//-----------------------------------------------------------------------------
+void LLModelPreview::createPreviewAvatar( void )
+{
+ mPreviewAvatar = (LLVOAvatar*)gObjectList.createObjectViewer( LL_PCODE_LEGACY_AVATAR, gAgent.getRegion() );
+ if ( mPreviewAvatar )
+ {
+ mPreviewAvatar->createDrawable( &gPipeline );
+ mPreviewAvatar->mIsDummy = TRUE;
+ mPreviewAvatar->mSpecialRenderMode = 1;
+ mPreviewAvatar->setPositionAgent( LLVector3::zero );
+ mPreviewAvatar->slamPosition();
+ mPreviewAvatar->updateJointLODs();
+ mPreviewAvatar->updateGeometry( mPreviewAvatar->mDrawable );
+ mPreviewAvatar->startMotion( ANIM_AGENT_STAND );
+ mPreviewAvatar->hideSkirt();
+ }
+ else
+ {
+ llinfos<<"Failed to create preview avatar for upload model window"<<llendl;
+ }
+}
+
+//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
BOOL LLModelPreview::render()
@@ -4403,25 +4724,6 @@ BOOL LLModelPreview::render()
mFMP->childSetEnabled("upload_joints", upload_skin);
- //poke at avatar when we upload custom joints
- /*
- if ( 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;
- if ( !model->mSkinWeights.empty() )
- {
- changeAvatarsJointPositions( model );
- }
- }
- }
- }
- */
-
F32 explode = mFMP->childGetValue("physics_explode").asReal();
glClear(GL_DEPTH_BUFFER_BIT);
@@ -4437,11 +4739,11 @@ BOOL LLModelPreview::render()
LLVector3 target_pos = mPreviewTarget+offset;
F32 z_near = 0.001f;
- F32 z_far = mCameraDistance+mPreviewScale.magVec()+mCameraOffset.magVec();
+ F32 z_far = mCameraDistance*10.0f+mPreviewScale.magVec()+mCameraOffset.magVec();
if (skin_weight)
{
- target_pos = gAgentAvatarp->getPositionAgent();
+ target_pos = getPreviewAvatar()->getPositionAgent();
z_near = 0.01f;
z_far = 1024.f;
mCameraDistance = 16.f;
@@ -4587,39 +4889,43 @@ BOOL LLModelPreview::render()
LLModel::Decomposition& physics = model->mPhysics;
- if (physics.mMesh.empty())
- { //build vertex buffer for physics mesh
- gMeshRepo.buildPhysicsMesh(physics);
- }
-
- if (!physics.mMesh.empty())
- { //render hull instead of mesh
+ if (!physics.mHull.empty())
+ {
render_mesh = false;
- for (U32 i = 0; i < physics.mMesh.size(); ++i)
- {
- if (explode > 0.f)
+
+ 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)
{
- gGL.pushMatrix();
+ if (explode > 0.f)
+ {
+ gGL.pushMatrix();
- LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
- offset *= explode;
+ LLVector3 offset = model->mHullCenter[i]-model->mCenterOfHullCenters;
+ offset *= explode;
- gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
- }
+ gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]);
+ }
- static std::vector<LLColor4U> hull_colors;
+ 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, 255));
- }
+ if (i+1 >= hull_colors.size())
+ {
+ hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255));
+ }
- glColor4ubv(hull_colors[i].mV);
- LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
+ glColor4ubv(hull_colors[i].mV);
+ LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
- if (explode > 0.f)
- {
- gGL.popMatrix();
+ if (explode > 0.f)
+ {
+ gGL.popMatrix();
+ }
}
}
}
@@ -4645,9 +4951,10 @@ BOOL LLModelPreview::render()
glColor3f(1.f, 1.f, 0.f);
- glLineWidth(3.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);
}
@@ -4656,13 +4963,86 @@ BOOL LLModelPreview::render()
gGL.popMatrix();
}
+ glLineWidth(3.f);
+ glPointSize(8.f);
+ gPipeline.enableLightsFullbright(LLColor4::white);
+ //show degenerate triangles
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+ LLGLDisable cull(GL_CULL_FACE);
+ glColor4f(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;
+
+ glMultMatrixf((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(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
+
+ 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
{
- LLVOAvatarSelf* avatar = gAgentAvatarp;
- target_pos = avatar->getPositionAgent();
+ target_pos = getPreviewAvatar()->getPositionAgent();
LLViewerCamera::getInstance()->setOriginAndLookAt(
target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera
@@ -4671,7 +5051,7 @@ BOOL LLModelPreview::render()
if (joint_positions)
{
- avatar->renderCollisionVolumes();
+ getPreviewAvatar()->renderCollisionVolumes();
}
for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
@@ -4702,7 +5082,7 @@ BOOL LLModelPreview::render()
LLMatrix4 mat[64];
for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j)
{
- LLJoint* joint = avatar->getJoint(model->mSkinInfo.mJointNames[j]);
+ LLJoint* joint = getPreviewAvatar()->getJoint(model->mSkinInfo.mJointNames[j]);
if (joint)
{
mat[j] = model->mSkinInfo.mInvBindMatrix[j];
@@ -4921,13 +5301,24 @@ void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture
{
LLModelPreview* preview = (LLModelPreview*) userdata;
preview->refresh();
+
+ if(final && preview->mModelLoader)
+ {
+ if(preview->mModelLoader->mNumOfFetchingTextures > 0)
+ {
+ preview->mModelLoader->mNumOfFetchingTextures-- ;
+ }
+ }
}
void LLModelPreview::onLODParamCommit(bool enforce_tri_limit)
{
- genLODs(mPreviewLOD, 3, enforce_tri_limit);
- updateStatusMessages();
- refresh();
+ if (!mLODFrozen)
+ {
+ genLODs(mPreviewLOD, 3, enforce_tri_limit);
+ updateStatusMessages();
+ refresh();
+ }
}
LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl)
@@ -4939,35 +5330,7 @@ LLFloaterModelPreview::DecompRequest::DecompRequest(const std::string& stage, LL
mParams = sInstance->mDecompParams;
//copy out positions and indices
- if (mdl)
- {
- U16 index_offset = 0;
-
- mPositions.clear();
- mIndices.clear();
-
- //queue up vertex positions and indices
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- const LLVolumeFace& face = mdl->getVolumeFace(i);
- if (mPositions.size() + face.mNumVertices > 65535)
- {
- continue;
- }
-
- for (U32 j = 0; j < face.mNumVertices; ++j)
- {
- mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
- }
-
- for (U32 j = 0; j < face.mNumIndices; ++j)
- {
- mIndices.push_back(face.mIndices[j]+index_offset);
- }
-
- index_offset += face.mNumVertices;
- }
- }
+ assignData(mdl) ;
}
void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index 4d8b46807f..d4f6b4d293 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -50,6 +50,7 @@ class domProfile_COMMON;
class domInstance_geometry;
class domNode;
class domTranslate;
+class domController;
class LLMenuButton;
class LLToggleableMenu;
@@ -107,7 +108,7 @@ public:
void loadModelCallback();
void loadTextures() ; //called in the main thread.
- void processElement(daeElement* element);
+ void processElement(daeElement* element, bool& badElement);
std::vector<LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
LLImportMaterial profileToMaterial(domProfile_COMMON* material);
std::string getElementLabel(daeElement *element);
@@ -131,6 +132,9 @@ public:
JointTransformMap& mJointList;
std::deque<std::string>& mJointsFromNode;
+ S32 mNumOfFetchingTextures ; //updated in the main thread
+ bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
+
private:
static std::list<LLModelLoader*> sActiveLoaderList;
static bool isAlive(LLModelLoader* loader) ;
@@ -199,6 +203,8 @@ protected:
static void onUploadJointsCommit(LLUICtrl*,void*);
static void onUploadSkinCommit(LLUICtrl*,void*);
+ static void onPhysicsLoadRadioCommit(LLUICtrl*,void *data);
+
static void onPreviewLODCommit(LLUICtrl*,void*);
static void onGenerateNormalsCommit(LLUICtrl*,void*);
@@ -309,9 +315,6 @@ public:
void setHasPivot( bool val ) { mHasPivot = val; }
void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
- //Sets the current avatars joints to new positions
- //Makes in world go to shit, however
- void changeAvatarsJointPositions( LLModel* pModel );
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
void critiqueJointToNodeMappingFromScene( void );
@@ -325,6 +328,8 @@ public:
//Accessors for the legacy rigs
const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
+ //Verify that a controller matches vertex counts
+ bool verifyController( domController* pController );
static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
@@ -341,6 +346,14 @@ public:
LLVector3 getTranslationForJointOffset( std::string joint );
+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; }
+
protected:
friend class LLModelLoader;
friend class LLFloaterModelPreview;
@@ -373,13 +386,20 @@ public:
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];
@@ -415,6 +435,7 @@ public:
std::deque<std::string> mMasterLegacyJointList;
std::deque<std::string> mJointsFromNode;
JointTransformMap mJointTransformMap;
+ LLPointer<LLVOAvatar> mPreviewAvatar;
};
#endif // LL_LLFLOATERMODELPREVIEW_H
diff --git a/indra/newview/llfloatermodelwizard.cpp b/indra/newview/llfloatermodelwizard.cpp
index faf81dbc5c..707c8288df 100644
--- a/indra/newview/llfloatermodelwizard.cpp
+++ b/indra/newview/llfloatermodelwizard.cpp
@@ -422,8 +422,11 @@ void LLFloaterModelWizard::executePhysicsStage(std::string stage_name)
{
LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];
DecompRequest* request = new DecompRequest(stage_name, mdl);
- sInstance->mCurRequest.insert(request);
- gMeshRepo.mDecompThread->submitRequest(request);
+ if(request->isValid())
+ {
+ sInstance->mCurRequest.insert(request);
+ gMeshRepo.mDecompThread->submitRequest(request);
+ }
}
}
}
@@ -438,35 +441,7 @@ LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLM
mParams = sInstance->mDecompParams;
//copy out positions and indices
- if (mdl)
- {
- U16 index_offset = 0;
-
- mPositions.clear();
- mIndices.clear();
-
- //queue up vertex positions and indices
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- const LLVolumeFace& face = mdl->getVolumeFace(i);
- if (mPositions.size() + face.mNumVertices > 65535)
- {
- continue;
- }
-
- for (U32 j = 0; j < face.mNumVertices; ++j)
- {
- mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
- }
-
- for (U32 j = 0; j < face.mNumIndices; ++j)
- {
- mIndices.push_back(face.mIndices[j]+index_offset);
- }
-
- index_offset += face.mNumVertices;
- }
- }
+ assignData(mdl) ;
}
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 4b15695cbf..7848484ac6 100644..100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -187,12 +187,26 @@ void LLVoiceSetKeyDialog::onCancel(void* user_data)
void handleNameTagOptionChanged(const LLSD& newvalue);
void handleDisplayNamesOptionChanged(const LLSD& newvalue);
bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response);
+bool callback_clear_cache(const LLSD& notification, const LLSD& response);
//bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
//bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLFloaterPreference* floater);
void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator);
+bool callback_clear_cache(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if ( option == 0 ) // YES
+ {
+ // flag client texture cache for clearing next time the client runs
+ gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
+ LLNotificationsUtil::add("CacheWillClear");
+ }
+
+ return false;
+}
+
bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -305,7 +319,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.Cancel", boost::bind(&LLFloaterPreference::onBtnCancel, this));
mCommitCallbackRegistrar.add("Pref.OK", boost::bind(&LLFloaterPreference::onBtnOK, this));
-// mCommitCallbackRegistrar.add("Pref.ClearCache", boost::bind(&LLFloaterPreference::onClickClearCache, this));
+ mCommitCallbackRegistrar.add("Pref.ClearCache", boost::bind(&LLFloaterPreference::onClickClearCache, this));
mCommitCallbackRegistrar.add("Pref.WebClearCache", boost::bind(&LLFloaterPreference::onClickBrowserClearCache, this));
mCommitCallbackRegistrar.add("Pref.SetCache", boost::bind(&LLFloaterPreference::onClickSetCache, this));
mCommitCallbackRegistrar.add("Pref.ResetCache", boost::bind(&LLFloaterPreference::onClickResetCache, this));
@@ -313,6 +327,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.SelectSkin", boost::bind(&LLFloaterPreference::onSelectSkin, this));
mCommitCallbackRegistrar.add("Pref.VoiceSetKey", boost::bind(&LLFloaterPreference::onClickSetKey, this));
mCommitCallbackRegistrar.add("Pref.VoiceSetMiddleMouse", boost::bind(&LLFloaterPreference::onClickSetMiddleMouse, this));
+ mCommitCallbackRegistrar.add("Pref.SetSounds", boost::bind(&LLFloaterPreference::onClickSetSounds, this));
// mCommitCallbackRegistrar.add("Pref.ClickSkipDialogs", boost::bind(&LLFloaterPreference::onClickSkipDialogs, this));
// mCommitCallbackRegistrar.add("Pref.ClickResetDialogs", boost::bind(&LLFloaterPreference::onClickResetDialogs, this));
mCommitCallbackRegistrar.add("Pref.ClickEnablePopup", boost::bind(&LLFloaterPreference::onClickEnablePopup, this));
@@ -809,6 +824,11 @@ void LLFloaterPreference::refreshEnabledGraphics()
}
}
+void LLFloaterPreference::onClickClearCache()
+{
+ LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache);
+}
+
void LLFloaterPreference::onClickBrowserClearCache()
{
LLNotificationsUtil::add("ConfirmClearBrowserCache", LLSD(), LLSD(), callback_clear_browser_cache);
@@ -868,14 +888,15 @@ void LLFloaterPreference::onClickSetCache()
void LLFloaterPreference::onClickResetCache()
{
- if (!gSavedSettings.getString("CacheLocation").empty())
+ if (gDirUtilp->getCacheDir(false) == gDirUtilp->getCacheDir(true))
{
- gSavedSettings.setString("NewCacheLocation", "");
- gSavedSettings.setString("NewCacheLocationTopFolder", "");
+ // The cache location was already the default.
+ return;
}
-
+ gSavedSettings.setString("NewCacheLocation", "");
+ gSavedSettings.setString("NewCacheLocationTopFolder", "");
LLNotificationsUtil::add("CacheWillBeMoved");
- std::string cache_location = gDirUtilp->getCacheDir(true);
+ std::string cache_location = gDirUtilp->getCacheDir(false);
gSavedSettings.setString("CacheLocation", cache_location);
std::string top_folder(gDirUtilp->getBaseFileName(cache_location));
gSavedSettings.setString("CacheLocationTopFolder", top_folder);
@@ -1266,6 +1287,14 @@ void LLFloaterPreference::onClickSetMiddleMouse()
p2t_line_editor->setValue(advanced_preferences->getString("middle_mouse"));
}
}
+
+void LLFloaterPreference::onClickSetSounds()
+{
+ // Disable Enable gesture sounds checkbox if the master sound is disabled
+ // or if sound effects are disabled.
+ getChild<LLCheckBoxCtrl>("gesture_audio_play_btn")->setEnabled(!gSavedSettings.getBOOL("MuteSounds"));
+}
+
/*
void LLFloaterPreference::onClickSkipDialogs()
{
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 5fe509fb37..61f2c78640 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -88,7 +88,8 @@ protected:
void onBtnCancel();
void onBtnApply();
- void onClickBrowserClearCache();
+ void onClickClearCache(); // Clear viewer texture cache, vfs, and VO cache on next startup
+ void onClickBrowserClearCache(); // Clear web history and caches as well as viewer caches above
void onLanguageChange();
void onNameTagOpacityChange(const LLSD& newvalue);
@@ -99,7 +100,7 @@ protected:
void onChangeCustom();
void updateMeterText(LLUICtrl* ctrl);
void onOpenHardwareSettings();
- /// callback for defaults
+ // callback for defaults
void setHardwareDefaults();
// callback for when client turns on shaders
void onVertexShaderEnable();
@@ -128,6 +129,7 @@ public:
void onClickSetKey();
void setKey(KEY key);
void onClickSetMiddleMouse();
+ void onClickSetSounds();
// void onClickSkipDialogs();
// void onClickResetDialogs();
void onClickEnablePopup();
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 34fda49375..bedc7ef704 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -40,6 +40,10 @@
#include "llxfermanager.h"
#include "indra_constants.h"
#include "message.h"
+#include "llloadingindicator.h"
+#include "llradiogroup.h"
+#include "llsd.h"
+#include "llsdserialize.h"
#include "llagent.h"
#include "llappviewer.h"
@@ -48,6 +52,8 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
+#include "lldaycyclemanager.h"
+#include "llenvmanager.h"
#include "llfilepicker.h"
#include "llfloatergodtools.h" // for send_sim_wide_deletes()
#include "llfloatertopobjects.h" // added to fix SL-32336
@@ -55,12 +61,12 @@
#include "llfloaterreg.h"
#include "llfloaterregiondebugconsole.h"
#include "llfloatertelehub.h"
-#include "llfloaterwindlight.h"
#include "llinventorymodel.h"
#include "lllineeditor.h"
#include "llnamelistctrl.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
+#include "llregioninfomodel.h"
#include "llscrolllistitem.h"
#include "llsliderctrl.h"
#include "llslurl.h"
@@ -80,12 +86,16 @@
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "llvlcomposition.h"
+#include "llwaterparammanager.h"
#include "lltrans.h"
#include "llagentui.h"
+#include "llmeshrepository.h"
const S32 TERRAIN_TEXTURE_COUNT = 4;
const S32 CORNER_COUNT = 4;
+#define TMP_DISABLE_WLES // STORM-1180
+
///----------------------------------------------------------------------------
/// Local class declaration
///----------------------------------------------------------------------------
@@ -189,24 +199,24 @@ LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
BOOL LLFloaterRegionInfo::postBuild()
{
mTab = getChild<LLTabContainer>("region_panels");
+ mTab->setCommitCallback(boost::bind(&LLFloaterRegionInfo::onTabSelected, this, _2));
// contruct the panels
LLPanelRegionInfo* panel;
- panel = new LLPanelRegionGeneralInfo;
+ panel = new LLPanelEstateInfo;
mInfoPanels.push_back(panel);
- panel->getCommitCallbackRegistrar().add("RegionInfo.ManageTelehub", boost::bind(&LLPanelRegionInfo::onClickManageTelehub, panel));
-
- panel->buildFromFile("panel_region_general.xml");
+ panel->buildFromFile("panel_region_estate.xml");
mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(true));
- panel = new LLPanelRegionDebugInfo;
+ panel = new LLPanelEstateCovenant;
mInfoPanels.push_back(panel);
- panel->buildFromFile("panel_region_debug.xml");
+ panel->buildFromFile("panel_region_covenant.xml");
mTab->addTabPanel(panel);
- panel = new LLPanelRegionTextureInfo;
+ panel = new LLPanelRegionGeneralInfo;
mInfoPanels.push_back(panel);
- panel->buildFromFile("panel_region_texture.xml");
+ panel->getCommitCallbackRegistrar().add("RegionInfo.ManageTelehub", boost::bind(&LLPanelRegionInfo::onClickManageTelehub, panel));
+ panel->buildFromFile("panel_region_general.xml");
mTab->addTabPanel(panel);
panel = new LLPanelRegionTerrainInfo;
@@ -214,20 +224,23 @@ BOOL LLFloaterRegionInfo::postBuild()
panel->buildFromFile("panel_region_terrain.xml");
mTab->addTabPanel(panel);
- panel = new LLPanelEstateInfo;
+ panel = new LLPanelEnvironmentInfo;
mInfoPanels.push_back(panel);
- panel->buildFromFile("panel_region_estate.xml");
+ panel->buildFromFile("panel_region_environment.xml");
mTab->addTabPanel(panel);
- panel = new LLPanelEstateCovenant;
+ panel = new LLPanelRegionDebugInfo;
mInfoPanels.push_back(panel);
- panel->buildFromFile("panel_region_covenant.xml");
+ panel->buildFromFile("panel_region_debug.xml");
mTab->addTabPanel(panel);
gMessageSystem->setHandlerFunc(
"EstateOwnerMessage",
&processEstateOwnerRequest);
+ // Request region info when agent region changes.
+ LLEnvManagerNew::instance().setRegionChangeCallback(boost::bind(&LLFloaterRegionInfo::requestRegionInfo, this));
+
return TRUE;
}
@@ -306,17 +319,25 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
{
LLPanel* panel;
LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
- llinfos << "LLFloaterRegionInfo::processRegionInfo" << llendl;
if(!floater)
{
return;
}
+
+ // We need to re-request environment setting here,
+ // otherwise after we apply (send) updated region settings we won't get them back,
+ // so our environment won't be updated.
+ // This is also the way to know about externally changed region environment.
+ LLEnvManagerNew::instance().requestRegionSettings();
LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
LLViewerRegion* region = gAgent.getRegion();
BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
+ // *TODO: Replace parcing msg with accessing the region info model.
+ LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
+
// extract message
std::string sim_name;
std::string sim_type = LLTrans::getString("land_type_unknown");
@@ -388,15 +409,10 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
panel = tab->getChild<LLPanel>("Terrain");
panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name));
- panel->getChild<LLUICtrl>("water_height_spin")->setValue(LLSD(water_height));
- panel->getChild<LLUICtrl>("terrain_raise_spin")->setValue(LLSD(terrain_raise_limit));
- panel->getChild<LLUICtrl>("terrain_lower_spin")->setValue(LLSD(terrain_lower_limit));
- panel->getChild<LLUICtrl>("use_estate_sun_check")->setValue(LLSD(use_estate_sun));
-
- panel->getChild<LLUICtrl>("fixed_sun_check")->setValue(LLSD((BOOL)(region_flags & REGION_FLAGS_SUN_FIXED)));
- panel->getChildView("fixed_sun_check")->setEnabled(allow_modify && !use_estate_sun);
- panel->getChild<LLUICtrl>("sun_hour_slider")->setValue(LLSD(sun_hour));
- panel->getChildView("sun_hour_slider")->setEnabled(allow_modify && !use_estate_sun);
+ panel->getChild<LLUICtrl>("water_height_spin")->setValue(region_info.mWaterHeight);
+ panel->getChild<LLUICtrl>("terrain_raise_spin")->setValue(region_info.mTerrainRaiseLimit);
+ panel->getChild<LLUICtrl>("terrain_lower_spin")->setValue(region_info.mTerrainLowerLimit);
+
panel->setCtrlsEnabled(allow_modify);
floater->refreshFromRegion( gAgent.getRegion() );
@@ -422,6 +438,29 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant()
return panel;
}
+// static
+LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain()
+{
+ LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
+ if (!floater)
+ {
+ llassert(floater);
+ return NULL;
+ }
+
+ LLTabContainer* tab_container = floater->getChild<LLTabContainer>("region_panels");
+ LLPanelRegionTerrainInfo* panel =
+ dynamic_cast<LLPanelRegionTerrainInfo*>(tab_container->getChild<LLPanel>("Terrain"));
+ llassert(panel);
+ return panel;
+}
+
+void LLFloaterRegionInfo::onTabSelected(const LLSD& param)
+{
+ LLPanel* active_panel = getChild<LLPanel>(param.asString());
+ active_panel->onOpen(LLSD());
+}
+
void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region)
{
if (!region)
@@ -502,8 +541,13 @@ void LLPanelRegionInfo::onChangeText(LLLineEditor* caller, void* user_data)
// virtual
BOOL LLPanelRegionInfo::postBuild()
{
- getChild<LLUICtrl>("apply_btn")->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this));
- getChildView("apply_btn")->setEnabled(FALSE);
+ // If the panel has an Apply button, set a callback for it.
+ LLUICtrl* apply_btn = findChild<LLUICtrl>("apply_btn");
+ if (apply_btn)
+ {
+ apply_btn->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this));
+ }
+
refresh();
return TRUE;
}
@@ -555,12 +599,14 @@ void LLPanelRegionInfo::sendEstateOwnerMessage(
void LLPanelRegionInfo::enableButton(const std::string& btn_name, BOOL enable)
{
- getChildView(btn_name)->setEnabled(enable);
+ LLView* button = findChildView(btn_name);
+ if (button) button->setEnabled(enable);
}
void LLPanelRegionInfo::disableButton(const std::string& btn_name)
{
- getChildView(btn_name)->setEnabled(FALSE);
+ LLView* button = findChildView(btn_name);
+ if (button) button->setEnabled(FALSE);
}
void LLPanelRegionInfo::initCtrl(const std::string& name)
@@ -590,6 +636,9 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region)
getChildView("im_btn")->setEnabled(allow_modify);
getChildView("manage_telehub_btn")->setEnabled(allow_modify);
+ const bool enable_mesh = gMeshRepo.meshRezEnabled();
+ getChildView("mesh_rez_enabled_check")->setVisible(enable_mesh);
+ getChildView("mesh_rez_enabled_check")->setEnabled(getChildView("mesh_rez_enabled_check")->getEnabled() && enable_mesh);
// Data gets filled in by processRegionInfo
return LLPanelRegionInfo::refreshFromRegion(region);
@@ -1048,131 +1097,7 @@ void LLPanelRegionDebugInfo::onClickCancelRestart(void* data)
}
-/////////////////////////////////////////////////////////////////////////////
-// LLPanelRegionTextureInfo
-//
-LLPanelRegionTextureInfo::LLPanelRegionTextureInfo() : LLPanelRegionInfo()
-{
- // nothing.
-}
-
-bool LLPanelRegionTextureInfo::refreshFromRegion(LLViewerRegion* region)
-{
- BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate());
- setCtrlsEnabled(allow_modify);
- getChildView("apply_btn")->setEnabled(FALSE);
-
- if (region)
- {
- getChild<LLUICtrl>("region_text")->setValue(LLSD(region->getName()));
- }
- else
- {
- getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
- }
-
- if (!region) return LLPanelRegionInfo::refreshFromRegion(region);
-
- LLVLComposition* compp = region->getComposition();
- LLTextureCtrl* texture_ctrl;
- std::string buffer;
- for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
- {
- buffer = llformat("texture_detail_%d", i);
- texture_ctrl = getChild<LLTextureCtrl>(buffer);
- if(texture_ctrl)
- {
- lldebugs << "Detail Texture " << i << ": "
- << compp->getDetailTextureID(i) << llendl;
- LLUUID tmp_id(compp->getDetailTextureID(i));
- texture_ctrl->setImageAssetID(tmp_id);
- }
- }
-
- for(S32 i = 0; i < CORNER_COUNT; ++i)
- {
- buffer = llformat("height_start_spin_%d", i);
- getChild<LLUICtrl>(buffer)->setValue(LLSD(compp->getStartHeight(i)));
- buffer = llformat("height_range_spin_%d", i);
- getChild<LLUICtrl>(buffer)->setValue(LLSD(compp->getHeightRange(i)));
- }
-
- // Call the parent for common book-keeping
- return LLPanelRegionInfo::refreshFromRegion(region);
-}
-
-
-BOOL LLPanelRegionTextureInfo::postBuild()
-{
- LLPanelRegionInfo::postBuild();
- std::string buffer;
- for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
- {
- buffer = llformat("texture_detail_%d", i);
- initCtrl(buffer);
- }
-
- for(S32 i = 0; i < CORNER_COUNT; ++i)
- {
- buffer = llformat("height_start_spin_%d", i);
- initCtrl(buffer);
- buffer = llformat("height_range_spin_%d", i);
- initCtrl(buffer);
- }
-
-// LLButton* btn = ("dump", LLRect(0, 20, 100, 0), "", onClickDump, this);
-// btn->setFollows(FOLLOWS_TOP|FOLLOWS_LEFT);
-// addChild(btn);
-
- return LLPanelRegionInfo::postBuild();
-}
-
-BOOL LLPanelRegionTextureInfo::sendUpdate()
-{
- llinfos << "LLPanelRegionTextureInfo::sendUpdate()" << llendl;
-
- // Make sure user hasn't chosen wacky textures.
- if (!validateTextureSizes())
- {
- return FALSE;
- }
-
- LLTextureCtrl* texture_ctrl;
- std::string buffer;
- std::string id_str;
- LLMessageSystem* msg = gMessageSystem;
- strings_t strings;
-
- LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-
- for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
- {
- buffer = llformat("texture_detail_%d", i);
- texture_ctrl = getChild<LLTextureCtrl>(buffer);
- if(texture_ctrl)
- {
- LLUUID tmp_id(texture_ctrl->getImageAssetID());
- tmp_id.toString(id_str);
- buffer = llformat("%d %s", i, id_str.c_str());
- strings.push_back(buffer);
- }
- }
- sendEstateOwnerMessage(msg, "texturedetail", invoice, strings);
- strings.clear();
- for(S32 i = 0; i < CORNER_COUNT; ++i)
- {
- buffer = llformat("height_start_spin_%d", i);
- std::string buffer2 = llformat("height_range_spin_%d", i);
- std::string buffer3 = llformat("%d %f %f", i, (F32)getChild<LLUICtrl>(buffer)->getValue().asReal(), (F32)getChild<LLUICtrl>(buffer2)->getValue().asReal());
- strings.push_back(buffer3);
- }
- sendEstateOwnerMessage(msg, "textureheights", invoice, strings);
- strings.clear();
- sendEstateOwnerMessage(msg, "texturecommit", invoice, strings);
- return TRUE;
-}
-
-BOOL LLPanelRegionTextureInfo::validateTextureSizes()
+BOOL LLPanelRegionTerrainInfo::validateTextureSizes()
{
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
@@ -1215,49 +1140,86 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes()
return TRUE;
}
-
-// static
-void LLPanelRegionTextureInfo::onClickDump(void* data)
-{
- llinfos << "LLPanelRegionTextureInfo::onClickDump()" << llendl;
-}
-
-
/////////////////////////////////////////////////////////////////////////////
// LLPanelRegionTerrainInfo
/////////////////////////////////////////////////////////////////////////////
+// Initialize statics
+
BOOL LLPanelRegionTerrainInfo::postBuild()
{
LLPanelRegionInfo::postBuild();
-
+
initCtrl("water_height_spin");
initCtrl("terrain_raise_spin");
initCtrl("terrain_lower_spin");
- initCtrl("fixed_sun_check");
- getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeFixedSun, this));
- getChild<LLUICtrl>("use_estate_sun_check")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeUseEstateTime, this));
- getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onChangeSunHour, this));
+ std::string buffer;
+ for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
+ {
+ buffer = llformat("texture_detail_%d", i);
+ initCtrl(buffer);
+ }
+
+ for(S32 i = 0; i < CORNER_COUNT; ++i)
+ {
+ buffer = llformat("height_start_spin_%d", i);
+ initCtrl(buffer);
+ buffer = llformat("height_range_spin_%d", i);
+ initCtrl(buffer);
+ }
childSetAction("download_raw_btn", onClickDownloadRaw, this);
childSetAction("upload_raw_btn", onClickUploadRaw, this);
childSetAction("bake_terrain_btn", onClickBakeTerrain, this);
- return TRUE;
+ return LLPanelRegionInfo::postBuild();
}
// virtual
bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
{
- llinfos << "LLPanelRegionTerrainInfo::refreshFromRegion" << llendl;
-
BOOL owner_or_god = gAgent.isGodlike()
|| (region && (region->getOwner() == gAgent.getID()));
BOOL owner_or_god_or_manager = owner_or_god
|| (region && region->isEstateManager());
setCtrlsEnabled(owner_or_god_or_manager);
+
getChildView("apply_btn")->setEnabled(FALSE);
+ if (region)
+ {
+ getChild<LLUICtrl>("region_text")->setValue(LLSD(region->getName()));
+
+ LLVLComposition* compp = region->getComposition();
+ LLTextureCtrl* texture_ctrl;
+ std::string buffer;
+ for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
+ {
+ buffer = llformat("texture_detail_%d", i);
+ texture_ctrl = getChild<LLTextureCtrl>(buffer);
+ if(texture_ctrl)
+ {
+ lldebugs << "Detail Texture " << i << ": "
+ << compp->getDetailTextureID(i) << llendl;
+ LLUUID tmp_id(compp->getDetailTextureID(i));
+ texture_ctrl->setImageAssetID(tmp_id);
+ }
+ }
+
+ for(S32 i = 0; i < CORNER_COUNT; ++i)
+ {
+ buffer = llformat("height_start_spin_%d", i);
+ getChild<LLUICtrl>(buffer)->setValue(LLSD(compp->getStartHeight(i)));
+ buffer = llformat("height_range_spin_%d", i);
+ getChild<LLUICtrl>(buffer)->setValue(LLSD(compp->getHeightRange(i)));
+ }
+ }
+ else
+ {
+ lldebugs << "no region set" << llendl;
+ getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
+ }
+
getChildView("download_raw_btn")->setEnabled(owner_or_god);
getChildView("upload_raw_btn")->setEnabled(owner_or_god);
getChildView("bake_terrain_btn")->setEnabled(owner_or_god);
@@ -1265,6 +1227,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
return LLPanelRegionInfo::refreshFromRegion(region);
}
+
// virtual
BOOL LLPanelRegionTerrainInfo::sendUpdate()
{
@@ -1273,76 +1236,62 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
strings_t strings;
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- buffer = llformat("%f", (F32)getChild<LLUICtrl>("water_height_spin")->getValue().asReal());
- strings.push_back(buffer);
- buffer = llformat("%f", (F32)getChild<LLUICtrl>("terrain_raise_spin")->getValue().asReal());
- strings.push_back(buffer);
- buffer = llformat("%f", (F32)getChild<LLUICtrl>("terrain_lower_spin")->getValue().asReal());
- strings.push_back(buffer);
- buffer = llformat("%s", (getChild<LLUICtrl>("use_estate_sun_check")->getValue().asBoolean() ? "Y" : "N"));
- strings.push_back(buffer);
- buffer = llformat("%s", (getChild<LLUICtrl>("fixed_sun_check")->getValue().asBoolean() ? "Y" : "N"));
- strings.push_back(buffer);
- buffer = llformat("%f", (F32)getChild<LLUICtrl>("sun_hour_slider")->getValue().asReal() );
- strings.push_back(buffer);
-
- // Grab estate information in case the user decided to set the
- // region back to estate time. JC
- LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
- if (!floater) return true;
-
- LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
- if (!tab) return true;
+ // update the model
+ LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
+ region_info.mWaterHeight = (F32) getChild<LLUICtrl>("water_height_spin")->getValue().asReal();
+ region_info.mTerrainRaiseLimit = (F32) getChild<LLUICtrl>("terrain_raise_spin")->getValue().asReal();
+ region_info.mTerrainLowerLimit = (F32) getChild<LLUICtrl>("terrain_lower_spin")->getValue().asReal();
- LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate");
- if (!panel) return true;
+ // and sync the region with it
+ region_info.sendRegionTerrain(invoice);
+
+ // =======================================
+ // Assemble and send texturedetail message
- BOOL estate_global_time = panel->getGlobalTime();
- BOOL estate_fixed_sun = panel->getFixedSun();
- F32 estate_sun_hour;
- if (estate_global_time)
+ // Make sure user hasn't chosen wacky textures.
+ if (!validateTextureSizes())
{
- estate_sun_hour = 0.f;
+ return FALSE;
}
- else
+
+ LLTextureCtrl* texture_ctrl;
+ std::string id_str;
+ LLMessageSystem* msg = gMessageSystem;
+
+ for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
{
- estate_sun_hour = panel->getSunHour();
+ buffer = llformat("texture_detail_%d", i);
+ texture_ctrl = getChild<LLTextureCtrl>(buffer);
+ if(texture_ctrl)
+ {
+ LLUUID tmp_id(texture_ctrl->getImageAssetID());
+ tmp_id.toString(id_str);
+ buffer = llformat("%d %s", i, id_str.c_str());
+ strings.push_back(buffer);
+ }
}
+ sendEstateOwnerMessage(msg, "texturedetail", invoice, strings);
+ strings.clear();
- buffer = llformat("%s", (estate_global_time ? "Y" : "N") );
- strings.push_back(buffer);
- buffer = llformat("%s", (estate_fixed_sun ? "Y" : "N") );
- strings.push_back(buffer);
- buffer = llformat("%f", estate_sun_hour);
- strings.push_back(buffer);
-
- sendEstateOwnerMessage(gMessageSystem, "setregionterrain", invoice, strings);
- return TRUE;
-}
+ // ========================================
+ // Assemble and send textureheights message
-void LLPanelRegionTerrainInfo::onChangeUseEstateTime()
-{
- BOOL use_estate_sun = getChild<LLUICtrl>("use_estate_sun_check")->getValue().asBoolean();
- getChildView("fixed_sun_check")->setEnabled(!use_estate_sun);
- getChildView("sun_hour_slider")->setEnabled(!use_estate_sun);
- if (use_estate_sun)
+ for(S32 i = 0; i < CORNER_COUNT; ++i)
{
- getChild<LLUICtrl>("fixed_sun_check")->setValue(LLSD(FALSE));
- getChild<LLUICtrl>("sun_hour_slider")->setValue(LLSD(0.f));
+ buffer = llformat("height_start_spin_%d", i);
+ std::string buffer2 = llformat("height_range_spin_%d", i);
+ std::string buffer3 = llformat("%d %f %f", i, (F32)getChild<LLUICtrl>(buffer)->getValue().asReal(), (F32)getChild<LLUICtrl>(buffer2)->getValue().asReal());
+ strings.push_back(buffer3);
}
- getChildView("apply_btn")->setEnabled(TRUE);
-}
+ sendEstateOwnerMessage(msg, "textureheights", invoice, strings);
+ strings.clear();
-void LLPanelRegionTerrainInfo::onChangeFixedSun()
-{
- // Just enable the apply button. We let the sun-hour slider be enabled
- // for both fixed-sun and non-fixed-sun. JC
- getChildView("apply_btn")->setEnabled(TRUE);
-}
+ // ========================================
+ // Send texturecommit message
-void LLPanelRegionTerrainInfo::onChangeSunHour()
-{
- getChildView("apply_btn")->setEnabled(TRUE);
+ sendEstateOwnerMessage(msg, "texturecommit", invoice, strings);
+
+ return TRUE;
}
// static
@@ -1402,6 +1351,7 @@ bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, con
strings.push_back("bake");
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
+
return false;
}
@@ -1435,6 +1385,7 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch)
estate_dispatch_initialized = true;
}
+#ifndef TMP_DISABLE_WLES
// Disables the sun-hour slider and the use fixed time check if the use global time is check
void LLPanelEstateInfo::onChangeUseGlobalTime()
{
@@ -1453,23 +1404,13 @@ void LLPanelEstateInfo::onChangeFixedSun()
getChild<LLUICtrl>("use_global_time_check")->setValue(LLSD(FALSE));
enableButton("apply_btn");
}
-
+#endif // TMP_DISABLE_WLES
//---------------------------------------------------------------------------
// Add/Remove estate access button callbacks
//---------------------------------------------------------------------------
-void LLPanelEstateInfo::onClickEditSky()
-{
- LLFloaterReg::showInstance("env_windlight");
-}
-
-void LLPanelEstateInfo::onClickEditDayCycle()
-{
- LLFloaterReg::showInstance("env_day_cycle");
-}
-
void LLPanelEstateInfo::onClickAddAllowedAgent()
{
LLCtrlListInterface *list = childGetListInterface("allowed_avatar_name_list");
@@ -2026,7 +1967,6 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
BOOL manager = (region && region->isEstateManager());
setCtrlsEnabled(god || owner || manager);
- getChildView("apply_btn")->setEnabled(FALSE);
getChildView("add_allowed_avatar_btn")->setEnabled(god || owner || manager);
getChildView("remove_allowed_avatar_btn")->setEnabled(god || owner || manager);
getChildView("add_allowed_group_btn")->setEnabled(god || owner || manager);
@@ -2084,10 +2024,6 @@ void LLPanelEstateInfo::updateChild(LLUICtrl* child_ctrl)
{
// do nothing
}
- else if (checkSunHourSlider(child_ctrl))
- {
- // do nothing
- }
}
bool LLPanelEstateInfo::estateUpdate(LLMessageSystem* msg)
@@ -2101,18 +2037,11 @@ BOOL LLPanelEstateInfo::postBuild()
{
// set up the callbacks for the generic controls
initCtrl("externally_visible_check");
- initCtrl("use_global_time_check");
- initCtrl("fixed_sun_check");
initCtrl("allow_direct_teleport");
initCtrl("limit_payment");
initCtrl("limit_age_verified");
initCtrl("voice_chat_check");
- // set up the use global time checkbox
- getChild<LLUICtrl>("use_global_time_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeUseGlobalTime, this));
- getChild<LLUICtrl>("fixed_sun_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeFixedSun, this));
- getChild<LLUICtrl>("sun_hour_slider")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
-
getChild<LLUICtrl>("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1));
LLNameListCtrl *avatar_name_list = getChild<LLNameListCtrl>("allowed_avatar_name_list");
if (avatar_name_list)
@@ -2159,9 +2088,6 @@ BOOL LLPanelEstateInfo::postBuild()
childSetAction("message_estate_btn", boost::bind(&LLPanelEstateInfo::onClickMessageEstate, this));
childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this));
- childSetAction("WLEditSky", boost::bind(&LLPanelEstateInfo::onClickEditSky, this));
- childSetAction("WLEditDayCycle", boost::bind(&LLPanelEstateInfo::onClickEditDayCycle, this));
-
return LLPanelRegionInfo::postBuild();
}
@@ -2300,7 +2226,6 @@ bool LLPanelEstateInfo::commitEstateInfoCaps()
body["is_externally_visible"] = getChild<LLUICtrl>("externally_visible_check")->getValue().asBoolean();
body["allow_direct_teleport"] = getChild<LLUICtrl>("allow_direct_teleport")->getValue().asBoolean();
- body["is_sun_fixed" ] = getChild<LLUICtrl>("fixed_sun_check")->getValue().asBoolean();
body["deny_anonymous" ] = getChild<LLUICtrl>("limit_payment")->getValue().asBoolean();
body["deny_age_unverified" ] = getChild<LLUICtrl>("limit_age_verified")->getValue().asBoolean();
body["allow_voice_chat" ] = getChild<LLUICtrl>("voice_chat_check")->getValue().asBoolean();
@@ -2365,7 +2290,6 @@ void LLPanelEstateInfo::commitEstateInfoDataserver()
void LLPanelEstateInfo::setEstateFlags(U32 flags)
{
getChild<LLUICtrl>("externally_visible_check")->setValue(LLSD(flags & REGION_FLAGS_EXTERNALLY_VISIBLE ? TRUE : FALSE) );
- getChild<LLUICtrl>("fixed_sun_check")->setValue(LLSD(flags & REGION_FLAGS_SUN_FIXED ? TRUE : FALSE) );
getChild<LLUICtrl>("voice_chat_check")->setValue(
LLSD(flags & REGION_FLAGS_ALLOW_VOICE ? TRUE : FALSE));
getChild<LLUICtrl>("allow_direct_teleport")->setValue(LLSD(flags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT ? TRUE : FALSE) );
@@ -2394,11 +2318,6 @@ U32 LLPanelEstateInfo::computeEstateFlags()
flags |= REGION_FLAGS_ALLOW_DIRECT_TELEPORT;
}
- if (getChild<LLUICtrl>("fixed_sun_check")->getValue().asBoolean())
- {
- flags |= REGION_FLAGS_SUN_FIXED;
- }
-
if (getChild<LLUICtrl>("limit_payment")->getValue().asBoolean())
{
flags |= REGION_FLAGS_DENY_ANONYMOUS;
@@ -2562,17 +2481,6 @@ BOOL LLPanelEstateInfo::checkRemovalButton(std::string name)
return (btn_name != "");
}
-BOOL LLPanelEstateInfo::checkSunHourSlider(LLUICtrl* child_ctrl)
-{
- BOOL found_child_ctrl = FALSE;
- if (child_ctrl->getName() == "sun_hour_slider")
- {
- enableButton("apply_btn");
- found_child_ctrl = TRUE;
- }
- return found_child_ctrl;
-}
-
// static
void LLPanelEstateInfo::onClickMessageEstate(void* userdata)
{
@@ -2974,6 +2882,8 @@ bool LLDispatchEstateUpdateInfo::operator()(
const LLUUID& invoice,
const sparam_t& strings)
{
+ lldebugs << "Received estate update" << llendl;
+
LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
if (!panel) return true;
@@ -3000,10 +2910,12 @@ bool LLDispatchEstateUpdateInfo::operator()(
F32 sun_hour = ((F32)(strtod(strings[4].c_str(), NULL)))/1024.0f;
if(sun_hour == 0 && (flags & REGION_FLAGS_SUN_FIXED ? FALSE : TRUE))
{
+ lldebugs << "Estate uses global time" << llendl;
panel->setGlobalTime(TRUE);
}
else
{
+ lldebugs << "Estate sun hour: " << sun_hour << llendl;
panel->setGlobalTime(FALSE);
panel->setSunHour(sun_hour);
}
@@ -3194,3 +3106,578 @@ bool LLDispatchSetEstateAccess::operator()(
return true;
}
+
+LLPanelEnvironmentInfo::LLPanelEnvironmentInfo()
+: mEnableEditing(false),
+ mRegionSettingsRadioGroup(NULL),
+ mDayCycleSettingsRadioGroup(NULL),
+ mWaterPresetCombo(NULL),
+ mSkyPresetCombo(NULL),
+ mDayCyclePresetCombo(NULL)
+{
+}
+
+// virtual
+BOOL LLPanelEnvironmentInfo::postBuild()
+{
+ mRegionSettingsRadioGroup = getChild<LLRadioGroup>("region_settings_radio_group");
+ mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchRegionSettings, this));
+
+ mDayCycleSettingsRadioGroup = getChild<LLRadioGroup>("sky_dayc_settings_radio_group");
+ mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchDayCycle, this));
+
+ mWaterPresetCombo = getChild<LLComboBox>("water_settings_preset_combo");
+ mWaterPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectWaterPreset, this));
+
+ mSkyPresetCombo = getChild<LLComboBox>("sky_settings_preset_combo");
+ mSkyPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectSkyPreset, this));
+
+ mDayCyclePresetCombo = getChild<LLComboBox>("dayc_settings_preset_combo");
+ mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectDayCycle, this));
+
+ childSetCommitCallback("apply_btn", boost::bind(&LLPanelEnvironmentInfo::onBtnApply, this), NULL);
+ getChild<LLButton>("apply_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance()));
+ childSetCommitCallback("cancel_btn", boost::bind(&LLPanelEnvironmentInfo::onBtnCancel, this), NULL);
+ getChild<LLButton>("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance()));
+
+ LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingschange, this));
+ LLEnvManagerNew::instance().setRegionSettingsAppliedCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingsApplied, this, _1));
+
+ LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLPanelEnvironmentInfo::populateDayCyclesList, this));
+ LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateSkyPresetsList, this));
+ LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateWaterPresetsList, this));
+
+ return TRUE;
+}
+
+// virtual
+void LLPanelEnvironmentInfo::onOpen(const LLSD& key)
+{
+ LL_DEBUGS("Windlight") << "Panel opened, refreshing" << LL_ENDL;
+ refresh();
+}
+
+// virtual
+void LLPanelEnvironmentInfo::handleVisibilityChange(BOOL new_visibility)
+{
+ // If hiding (user switched to another tab or closed the floater),
+ // display user's preferred environment.
+ if (!new_visibility)
+ {
+ LLEnvManagerNew::instance().usePrefs();
+ }
+}
+
+// virtual
+bool LLPanelEnvironmentInfo::refreshFromRegion(LLViewerRegion* region)
+{
+ LL_DEBUGS("Windlight") << "Region updated, enabling/disabling controls" << LL_ENDL;
+ BOOL owner_or_god = gAgent.isGodlike() || (region && (region->getOwner() == gAgent.getID()));
+ BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
+
+ // Don't refresh from region settings to avoid flicker after applying new region settings.
+ mEnableEditing = owner_or_god_or_manager;
+ setControlsEnabled(mEnableEditing);
+
+ return LLPanelRegionInfo::refreshFromRegion(region);
+}
+
+void LLPanelEnvironmentInfo::refresh()
+{
+ populateWaterPresetsList();
+ populateSkyPresetsList();
+ populateDayCyclesList();
+
+ // Init radio groups.
+ const LLEnvironmentSettings& settings = LLEnvManagerNew::instance().getRegionSettings();
+ const LLSD& dc = settings.getWLDayCycle();
+ LLSD::Real first_frame_time = dc.size() > 0 ? dc[0][0].asReal() : 0.0f;
+ const bool use_fixed_sky = dc.size() == 1 && first_frame_time < 0;
+ mRegionSettingsRadioGroup->setSelectedIndex(settings.getSkyMap().size() == 0 ? 0 : 1);
+ mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1);
+
+ setControlsEnabled(mEnableEditing);
+
+ setDirty(false);
+}
+
+void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled)
+{
+ mRegionSettingsRadioGroup->setEnabled(enabled);
+ mDayCycleSettingsRadioGroup->setEnabled(enabled);
+
+ mWaterPresetCombo->setEnabled(enabled);
+ mSkyPresetCombo->setEnabled(enabled);
+ mDayCyclePresetCombo->setEnabled(enabled);
+
+ getChildView("apply_btn")->setEnabled(enabled);
+ getChildView("cancel_btn")->setEnabled(enabled);
+
+ if (enabled)
+ {
+ // Enable/disable some controls based on currently selected radio buttons.
+ bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
+ getChild<LLView>("user_environment_settings")->setEnabled(!use_defaults);
+
+ bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
+ mSkyPresetCombo->setEnabled(is_fixed_sky);
+ mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
+ }
+}
+
+void LLPanelEnvironmentInfo::setApplyProgress(bool started)
+{
+ LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("progress_indicator");
+
+ indicator->setVisible(started);
+
+ if (started)
+ {
+ indicator->start();
+ }
+ else
+ {
+ indicator->stop();
+ }
+}
+
+void LLPanelEnvironmentInfo::setDirty(bool dirty)
+{
+ getChildView("apply_btn")->setEnabled(dirty);
+ getChildView("cancel_btn")->setEnabled(dirty);
+}
+
+void LLPanelEnvironmentInfo::sendRegionSunUpdate()
+{
+ LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
+
+ // If the region is being switched to fixed sky,
+ // change the region's sun hour according to the (fixed) sun position.
+ // This is needed for llGetSunDirection() LSL function to work properly (STORM-1330).
+ const LLSD& sky_map = mNewRegionSettings.getSkyMap();
+ bool region_use_fixed_sky = sky_map.size() == 1;
+ if (region_use_fixed_sky)
+ {
+ LLWLParamSet param_set;
+ llassert(sky_map.isMap());
+ param_set.setAll(sky_map.beginMap()->second);
+ F32 sun_angle = param_set.getSunAngle();
+
+ LL_DEBUGS("Windlight Sync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL;
+ // convert value range from 0..2pi to 6..30
+ region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f;
+ }
+
+ region_info.setUseFixedSun(region_use_fixed_sky);
+ region_info.mUseEstateSun = !region_use_fixed_sky;
+ LL_DEBUGS("Windlight Sync") << "Sun hour: " << region_info.mSunHour << LL_ENDL;
+
+ region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice());
+}
+
+void LLPanelEnvironmentInfo::populateWaterPresetsList()
+{
+ mWaterPresetCombo->removeall();
+
+ // If the region already has water params, add them to the list.
+ const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings();
+ if (region_settings.getWaterParams().size() != 0)
+ {
+ const std::string& region_name = gAgent.getRegion()->getName();
+ mWaterPresetCombo->add(region_name, LLWLParamKey(region_name, LLEnvKey::SCOPE_REGION).toLLSD());
+ mWaterPresetCombo->addSeparator();
+ }
+
+ std::list<std::string> user_presets, system_presets;
+ LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
+
+ // Add local user presets first.
+ for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
+ }
+
+ if (user_presets.size() > 0)
+ {
+ mWaterPresetCombo->addSeparator();
+ }
+
+ // Add local system presets.
+ for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
+ {
+ mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
+ }
+
+ // There's no way to select current preset because its name is not stored on server.
+}
+
+void LLPanelEnvironmentInfo::populateSkyPresetsList()
+{
+ mSkyPresetCombo->removeall();
+
+ LLWLParamManager::preset_name_list_t region_presets;
+ LLWLParamManager::preset_name_list_t user_presets, sys_presets;
+ LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
+
+ // Add region presets.
+ std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
+ {
+ std::string preset_name = *it;
+ std::string item_title = preset_name + " (" + region_name + ")";
+ mSkyPresetCombo->add(item_title, LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal());
+ }
+
+ if (!region_presets.empty())
+ {
+ mSkyPresetCombo->addSeparator();
+ }
+
+ // Add user presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
+ {
+ mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
+ }
+
+ if (!user_presets.empty())
+ {
+ mSkyPresetCombo->addSeparator();
+ }
+
+ // Add system presets.
+ for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
+ {
+ mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
+ }
+
+ // Select current preset.
+ LLSD sky_map = LLEnvManagerNew::instance().getRegionSettings().getSkyMap();
+ if (sky_map.size() == 1) // if the region is set to fixed sky
+ {
+ std::string preset_name = sky_map.beginMap()->first;
+ mSkyPresetCombo->selectByValue(LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal());
+ }
+}
+
+void LLPanelEnvironmentInfo::populateDayCyclesList()
+{
+ mDayCyclePresetCombo->removeall();
+
+ // If the region already has env. settings, add its day cycle to the list.
+ const LLSD& cur_region_dc = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
+ if (cur_region_dc.size() != 0)
+ {
+ LLViewerRegion* region = gAgent.getRegion();
+ llassert(region != NULL);
+
+ LLWLParamKey key(region->getName(), LLEnvKey::SCOPE_REGION);
+ mDayCyclePresetCombo->add(region->getName(), key.toStringVal());
+ mDayCyclePresetCombo->addSeparator();
+ }
+
+ // Add local user day cycles.
+ LLDayCycleManager::preset_name_list_t user_days, sys_days;
+ LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
+ {
+ mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
+ }
+
+ if (user_days.size() > 0)
+ {
+ mDayCyclePresetCombo->addSeparator();
+ }
+
+ // Add local system day cycles.
+ for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
+ {
+ mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
+ }
+
+ // Current day cycle is already selected.
+}
+
+bool LLPanelEnvironmentInfo::getSelectedWaterParams(LLSD& water_params)
+{
+ LLWLParamKey water_key(mWaterPresetCombo->getSelectedValue());
+
+ if (water_key.scope == LLEnvKey::SCOPE_REGION)
+ {
+ water_params = LLEnvManagerNew::instance().getRegionSettings().getWaterParams();
+ }
+ else
+ {
+ LLWaterParamSet param_set;
+ if (!LLWaterParamManager::instance().getParamSet(water_key.name, param_set))
+ {
+ llwarns << "Error getting water preset: " << water_key.name << llendl;
+ return false;
+ }
+
+ water_params = param_set.getAll();
+ }
+
+ return true;
+}
+
+bool LLPanelEnvironmentInfo::getSelectedSkyParams(LLSD& sky_params, std::string& preset_name)
+{
+ std::string preset_key(mSkyPresetCombo->getValue().asString());
+ LLWLParamKey preset(preset_key);
+
+ // Get the preset sky params.
+ LLWLParamSet param_set;
+ if (!LLWLParamManager::instance().getParamSet(preset, param_set))
+ {
+ llwarns << "Error getting sky params: " << preset.toLLSD() << llendl;
+ return false;
+ }
+
+ sky_params = param_set.getAll();
+ preset_name = preset.name;
+ return true;
+}
+
+bool LLPanelEnvironmentInfo::getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope)
+{
+ std::string preset_key(mDayCyclePresetCombo->getValue().asString());
+ LLWLParamKey dc(preset_key);
+ LL_DEBUGS("Windlight") << "Use day cycle: " << dc.toLLSD() << LL_ENDL;
+
+ if (dc.scope == LLEnvKey::SCOPE_REGION) // current region day cycle
+ {
+ const LLEnvironmentSettings& cur_region_settings = LLEnvManagerNew::instance().getRegionSettings();
+ day_cycle = cur_region_settings.getWLDayCycle();
+ sky_map = cur_region_settings.getSkyMap();
+ }
+ else // a local day cycle
+ {
+ if (!LLDayCycleManager::instance().getPreset(dc.name, day_cycle))
+ {
+ llwarns << "Error getting day cycle " << dc.name << llendl;
+ return false;
+ }
+
+ // Create sky map from the day cycle.
+ {
+ LLWLDayCycle tmp_day;
+ tmp_day.loadDayCycle(day_cycle, dc.scope);
+ tmp_day.getSkyMap(sky_map);
+ }
+ }
+
+ scope = dc.scope;
+
+ return true;
+}
+void LLPanelEnvironmentInfo::onSwitchRegionSettings()
+{
+ bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
+ getChild<LLView>("user_environment_settings")->setEnabled(!use_defaults);
+
+ if (use_defaults)
+ {
+ LLEnvManagerNew::instance().useDefaults();
+ }
+ else
+ {
+ onSelectWaterPreset();
+ onSwitchDayCycle();
+ }
+
+ setDirty(true);
+}
+
+void LLPanelEnvironmentInfo::onSwitchDayCycle()
+{
+ bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
+
+ mSkyPresetCombo->setEnabled(is_fixed_sky);
+ mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
+
+ if (is_fixed_sky)
+ {
+ onSelectSkyPreset();
+ }
+ else
+ {
+ onSelectDayCycle();
+ }
+
+ setDirty(true);
+}
+
+void LLPanelEnvironmentInfo::onSelectWaterPreset()
+{
+ LLSD water_params;
+
+ if (getSelectedWaterParams(water_params))
+ {
+ LLEnvManagerNew::instance().useWaterParams(water_params);
+ }
+
+ setDirty(true);
+}
+
+void LLPanelEnvironmentInfo::onSelectSkyPreset()
+{
+ LLSD params;
+ std::string dummy;
+
+ if (getSelectedSkyParams(params, dummy))
+ {
+ LLEnvManagerNew::instance().useSkyParams(params);
+ }
+
+ setDirty(true);
+}
+
+void LLPanelEnvironmentInfo::onSelectDayCycle()
+{
+ LLSD day_cycle;
+ LLSD sky_map; // unused
+ short scope;
+
+ if (getSelectedDayCycleParams(day_cycle, sky_map, scope))
+ {
+ LLEnvManagerNew::instance().useDayCycleParams(day_cycle, (LLEnvKey::EScope) scope);
+ }
+
+ setDirty(true);
+}
+
+void LLPanelEnvironmentInfo::onBtnApply()
+{
+ const bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
+ const bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
+
+ LLSD day_cycle;
+ LLSD sky_map;
+ LLSD water_params;
+
+ if (use_defaults)
+ {
+ // settings will be empty
+ LL_DEBUGS("Windlight") << "Defaults" << LL_ENDL;
+ }
+ else // use custom region settings
+ {
+ if (use_fixed_sky)
+ {
+ LL_DEBUGS("Windlight") << "Use fixed sky" << LL_ENDL;
+
+ // Get selected sky params.
+ LLSD params;
+ std::string preset_name;
+ if (!getSelectedSkyParams(params, preset_name))
+ {
+ return;
+ }
+
+ // Create a day cycle consisting of a single sky preset.
+ LLSD key(LLSD::emptyArray());
+ key.append(-1.0f); // indicate that user preference is actually fixed sky, not a day cycle
+ key.append(preset_name);
+ day_cycle.append(key);
+
+ // Create a sky map consisting of only the sky preset.
+ std::map<LLWLParamKey, LLWLParamSet> refs;
+ LLWLParamSet param_set;
+ param_set.setAll(params);
+ refs[LLWLParamKey(preset_name, LLEnvKey::SCOPE_LOCAL)] = param_set; // scope doesn't matter here
+ sky_map = LLWLParamManager::createSkyMap(refs);
+ }
+ else // use day cycle
+ {
+ LL_DEBUGS("Windlight") << "Use day cycle" << LL_ENDL;
+
+ short scope; // unused
+ if (!getSelectedDayCycleParams(day_cycle, sky_map, scope))
+ {
+ return;
+ }
+
+ // If it's a special single-preset day cycle meaning using a fixed sky,
+ // reset the frame time to a non-negative value,
+ // so that the region setting is displayed in the floater as
+ // a day cycle, not a preset. (STORM-1289)
+ if (day_cycle.size() == 1 && day_cycle[0][0].asReal() < 0.0f)
+ {
+ LL_DEBUGS("Windlight") << "Fixing negative time" << LL_ENDL;
+ day_cycle[0][0] = 0.0f;
+ }
+ }
+
+ // Get water params.
+ if (!getSelectedWaterParams(water_params))
+ {
+ // *TODO: show a notification?
+ return;
+ }
+ }
+
+ // Send settings apply request.
+ LLEnvironmentSettings new_region_settings;
+ new_region_settings.saveParams(day_cycle, sky_map, water_params, 0.0f);
+ if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings))
+ {
+ llwarns << "Error applying region environment settings" << llendl;
+ return;
+ }
+
+ // When the settings get applied, we'll also send the region sun position update.
+ // To determine the sun angle we're going to need the new settings.
+ mNewRegionSettings = new_region_settings;
+
+ // Start spinning the progress indicator.
+ setApplyProgress(true);
+}
+
+void LLPanelEnvironmentInfo::onBtnCancel()
+{
+ // Reload last saved region settings.
+ refresh();
+
+ // Apply them.
+ LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
+ const LLEnvironmentSettings& cur_settings = env_mgr.getRegionSettings();
+ const LLSD& region_day_cycle = cur_settings.getWLDayCycle();
+ const LLSD& region_water = cur_settings.getWaterParams();
+ env_mgr.useWaterParams(region_water);
+ env_mgr.useDayCycleParams(region_day_cycle, LLEnvKey::SCOPE_REGION);
+}
+
+void LLPanelEnvironmentInfo::onRegionSettingschange()
+{
+ LL_DEBUGS("Windlight") << "Region settings changed, refreshing" << LL_ENDL;
+ refresh();
+
+ // Stop applying progress indicator (it may be running if it's us who initiated settings update).
+ setApplyProgress(false);
+}
+
+void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok)
+{
+ // If applying new settings has failed, stop the indicator right away.
+ // Otherwise it will be stopped when we receive the updated settings from server.
+ if (ok)
+ {
+ // Set the region sun phase/flags according to the chosen new preferences.
+ //
+ // If we do this earlier we may get jerky transition from fixed sky to a day cycle (STORM-1481).
+ // That is caused by the simulator re-sending the region info, which in turn makes us
+ // re-request and display old region environment settings while the new ones haven't been applied yet.
+ sendRegionSunUpdate();
+ }
+ else
+ {
+ setApplyProgress(false);
+
+ // We need to re-request environment setting here,
+ // otherwise our subsequent attempts to change region settings will fail with the following error:
+ // "Unable to update environment settings because the last update your viewer saw was not the same
+ // as the last update sent from the simulator. Try sending your update again, and if this
+ // does not work, try leaving and returning to the region."
+ LLEnvManagerNew::instance().requestRegionSettings();
+ }
+}
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 2b87c27fcf..e7917c382c 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -34,6 +34,8 @@
#include "llhost.h"
#include "llpanel.h"
+#include "llenvmanager.h" // for LLEnvironmentSettings
+
class LLAvatarName;
class LLDispatcher;
class LLLineEditor;
@@ -46,6 +48,7 @@ class LLInventoryItem;
class LLCheckBoxCtrl;
class LLComboBox;
class LLNameListCtrl;
+class LLRadioGroup;
class LLSliderCtrl;
class LLSpinCtrl;
class LLTextBox;
@@ -53,11 +56,17 @@ class LLVFS;
class LLPanelRegionGeneralInfo;
class LLPanelRegionDebugInfo;
-class LLPanelRegionTextureInfo;
class LLPanelRegionTerrainInfo;
class LLPanelEstateInfo;
class LLPanelEstateCovenant;
+class LLEventTimer;
+class LLEnvironmentSettings;
+class LLWLParamManager;
+class LLWaterParamManager;
+class LLWLParamSet;
+class LLWaterParamSet;
+
class LLFloaterRegionInfo : public LLFloater
{
friend class LLFloaterReg;
@@ -79,6 +88,7 @@ public:
static LLPanelEstateInfo* getPanelEstate();
static LLPanelEstateCovenant* getPanelCovenant();
+ static LLPanelRegionTerrainInfo* getPanelRegionTerrain();
// from LLPanel
virtual void refresh();
@@ -96,6 +106,7 @@ private:
boost::signals2::connection mConsoleReplySignalConnection;;
protected:
+ void onTabSelected(const LLSD& param);
void refreshFromRegion(LLViewerRegion* region);
// member data
@@ -208,44 +219,25 @@ private:
/////////////////////////////////////////////////////////////////////////////
-class LLPanelRegionTextureInfo : public LLPanelRegionInfo
+class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
{
+ LOG_CLASS(LLPanelRegionTerrainInfo);
+
public:
- LLPanelRegionTextureInfo();
- ~LLPanelRegionTextureInfo() {}
-
- virtual bool refreshFromRegion(LLViewerRegion* region);
-
- // LLPanel && LLView
- virtual BOOL postBuild();
+ LLPanelRegionTerrainInfo() : LLPanelRegionInfo() {}
+ ~LLPanelRegionTerrainInfo() {}
-protected:
- virtual BOOL sendUpdate();
+ virtual BOOL postBuild(); // LLPanel
- static void onClickDump(void* data);
- BOOL validateTextureSizes();
-};
+ virtual bool refreshFromRegion(LLViewerRegion* region); // refresh local settings from region update from simulator
+ void setEnvControls(bool available); // Whether environment settings are available for this region
-/////////////////////////////////////////////////////////////////////////////
+ BOOL validateTextureSizes();
-class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
-{
-public:
- LLPanelRegionTerrainInfo()
- : LLPanelRegionInfo() {}
- ~LLPanelRegionTerrainInfo() {}
- // LLPanel
- virtual BOOL postBuild();
+ //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button
- virtual bool refreshFromRegion(LLViewerRegion* region);
-
-protected:
virtual BOOL sendUpdate();
- void onChangeUseEstateTime();
- void onChangeFixedSun();
- void onChangeSunHour();
-
static void onClickDownloadRaw(void*);
static void onClickUploadRaw(void*);
static void onClickBakeTerrain(void*);
@@ -319,10 +311,10 @@ public:
BOOL getGlobalTime();
void setGlobalTime(bool b);
- BOOL getFixedSun();
+ BOOL getFixedSun(); // *TODO: deprecated
- F32 getSunHour();
- void setSunHour(F32 sun_hour);
+ F32 getSunHour(); // *TODO: deprecated
+ void setSunHour(F32 sun_hour); // *TODO: deprecated
const std::string getEstateName() const;
void setEstateName(const std::string& name);
@@ -337,7 +329,6 @@ public:
// If visible from mainland, allowed agent and allowed groups
// are ignored, so must disable UI.
void setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban);
-
protected:
virtual BOOL sendUpdate();
// confirmation dialog callback
@@ -417,4 +408,65 @@ protected:
EAssetStatus mAssetStatus;
};
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelEnvironmentInfo : public LLPanelRegionInfo
+{
+ LOG_CLASS(LLPanelEnvironmentInfo);
+
+public:
+ LLPanelEnvironmentInfo();
+
+ // LLPanel
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ // LLView
+ /*virtual*/ void handleVisibilityChange(BOOL new_visibility);
+
+ // LLPanelRegionInfo
+ /*virtual*/ bool refreshFromRegion(LLViewerRegion* region);
+
+private:
+ void refresh();
+ void setControlsEnabled(bool enabled);
+ void setApplyProgress(bool started);
+ void setDirty(bool dirty);
+
+ void sendRegionSunUpdate();
+
+ void populateWaterPresetsList();
+ void populateSkyPresetsList();
+ void populateDayCyclesList();
+
+ bool getSelectedWaterParams(LLSD& water_params);
+ bool getSelectedSkyParams(LLSD& sky_params, std::string& preset_name);
+ bool getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope);
+
+ void onSwitchRegionSettings();
+ void onSwitchDayCycle();
+
+ void onSelectWaterPreset();
+ void onSelectSkyPreset();
+ void onSelectDayCycle();
+
+ void onBtnApply();
+ void onBtnCancel();
+
+ void onRegionSettingschange();
+ void onRegionSettingsApplied(bool ok);
+
+ /// New environment settings that are being applied to the region.
+ LLEnvironmentSettings mNewRegionSettings;
+
+ bool mEnableEditing;
+
+ LLRadioGroup* mRegionSettingsRadioGroup;
+ LLRadioGroup* mDayCycleSettingsRadioGroup;
+
+ LLComboBox* mWaterPresetCombo;
+ LLComboBox* mSkyPresetCombo;
+ LLComboBox* mDayCyclePresetCombo;
+};
+
#endif
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 8558a1277c..3434841d09 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -41,6 +41,7 @@
#include "llviewerparcelmgr.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
+#include "lltrans.h"
class LLAvatarName;
@@ -451,7 +452,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata)
// Do a confirmation
S32 sale_price = self->getChild<LLUICtrl>("price")->getValue();
S32 area = parcel->getArea();
- std::string authorizedBuyerName = "Anyone";
+ std::string authorizedBuyerName = LLTrans::getString("Anyone");
bool sell_to_anyone = true;
if ("user" == self->getChild<LLUICtrl>("sell_to")->getValue().asString())
{
diff --git a/indra/newview/llfloatersounddevices.cpp b/indra/newview/llfloatersounddevices.cpp
index 9fe7c7f9dd..e692f1735a 100644
--- a/indra/newview/llfloatersounddevices.cpp
+++ b/indra/newview/llfloatersounddevices.cpp
@@ -68,6 +68,9 @@ BOOL LLFloaterSoundDevices::postBuild()
if (panel)
{
panel->setUseTuningMode(false);
+ getChild<LLUICtrl>("voice_input_device")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel));
+ getChild<LLUICtrl>("voice_output_device")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel));
+ getChild<LLUICtrl>("mic_volume_slider")->setCommitCallback(boost::bind(&LLPanelVoiceDeviceSettings::apply, panel));
}
return TRUE;
}
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 73c1f99fa0..33b7777d2e 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -85,6 +85,8 @@
#include "llviewerwindow.h"
#include "llvovolume.h"
#include "lluictrlfactory.h"
+#include "llaccountingquotamanager.h"
+#include "llmeshrepository.h"
// Globals
LLFloaterTools *gFloaterTools = NULL;
@@ -422,7 +424,7 @@ void LLFloaterTools::refresh()
// Refresh object and prim count labels
LLLocale locale(LLLocale::USER_LOCALE);
- if ((gAgent.getRegion() && gAgent.getRegion()->getCapability("GetMesh").empty()) || !gSavedSettings.getBOOL("MeshEnabled"))
+ if (!gMeshRepo.meshRezEnabled())
{
std::string obj_count_string;
LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount());
@@ -787,9 +789,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
getChildView("Strength:")->setVisible( land_visible);
}
- bool show_mesh_cost = gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty() &&
- gSavedSettings.getBOOL("MeshEnabled");
+ bool show_mesh_cost = gMeshRepo.meshRezEnabled();
getChildView("obj_count")->setVisible( !land_visible && !show_mesh_cost);
getChildView("prim_count")->setVisible( !land_visible && !show_mesh_cost);
diff --git a/indra/newview/llfloaterwater.cpp b/indra/newview/llfloaterwater.cpp
deleted file mode 100644
index be4b144f41..0000000000
--- a/indra/newview/llfloaterwater.cpp
+++ /dev/null
@@ -1,625 +0,0 @@
-/**
- * @file llfloaterwater.cpp
- * @brief LLFloaterWater class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterwater.h"
-
-#include "pipeline.h"
-#include "llsky.h"
-
-#include "llfloaterreg.h"
-#include "llsliderctrl.h"
-#include "llspinctrl.h"
-#include "llcolorswatch.h"
-#include "llcheckboxctrl.h"
-#include "lltexturectrl.h"
-#include "lluictrlfactory.h"
-#include "llviewercamera.h"
-#include "llcombobox.h"
-#include "lllineeditor.h"
-#include "llnotificationsutil.h"
-#include "llfloaterdaycycle.h"
-#include "llboost.h"
-#include "llmultisliderctrl.h"
-
-#include "v4math.h"
-#include "llviewerdisplay.h"
-#include "llviewercontrol.h"
-#include "llviewerwindow.h"
-#include "llsavedsettingsglue.h"
-
-#include "llwaterparamset.h"
-#include "llwaterparammanager.h"
-#include "llpostprocess.h"
-
-#undef max
-
-std::set<std::string> LLFloaterWater::sDefaultPresets;
-
-LLFloaterWater::LLFloaterWater(const LLSD& key)
- : LLFloater(key)
-{
-}
-
-LLFloaterWater::~LLFloaterWater()
-{
-}
-BOOL LLFloaterWater::postBuild()
-{
-
- std::string def_water = getString("WLDefaultWaterNames");
-
- // no editing or deleting of the blank string
- sDefaultPresets.insert("");
- boost_tokenizer tokens(def_water, boost::char_separator<char>(":"));
- for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- std::string tok(*token_iter);
- sDefaultPresets.insert(tok);
- }
-
- // add the combo boxes
- LLComboBox* comboBox = getChild<LLComboBox>("WaterPresetsCombo");
-
- if(comboBox != NULL) {
-
- std::map<std::string, LLWaterParamSet>::iterator mIt =
- LLWaterParamManager::instance()->mParamList.begin();
- for(; mIt != LLWaterParamManager::instance()->mParamList.end(); mIt++)
- {
- comboBox->add(mIt->first);
- }
-
- // set defaults on combo boxes
- comboBox->selectByValue(LLSD("Default"));
- }
- // load it up
- initCallbacks();
- syncMenu();
- return TRUE;
-}
-void LLFloaterWater::initCallbacks(void) {
-
- LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
-
- getChild<LLUICtrl>("WaterFogColor")->setCommitCallback(boost::bind(&LLFloaterWater::onWaterFogColorMoved, this, _1, &param_mgr->mFogColor));
-
- //
- getChild<LLUICtrl>("WaterGlow")->setCommitCallback(boost::bind(&LLFloaterWater::onColorControlAMoved, this, _1, &param_mgr->mFogColor));
-
- // fog density
- getChild<LLUICtrl>("WaterFogDensity")->setCommitCallback(boost::bind(&LLFloaterWater::onExpFloatControlMoved, this, _1, &param_mgr->mFogDensity));
- getChild<LLUICtrl>("WaterUnderWaterFogMod")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mUnderWaterFogMod));
-
- // blue density
- getChild<LLUICtrl>("WaterNormalScaleX")->setCommitCallback(boost::bind(&LLFloaterWater::onVector3ControlXMoved, this, _1, &param_mgr->mNormalScale));
- getChild<LLUICtrl>("WaterNormalScaleY")->setCommitCallback(boost::bind(&LLFloaterWater::onVector3ControlYMoved, this, _1, &param_mgr->mNormalScale));
- getChild<LLUICtrl>("WaterNormalScaleZ")->setCommitCallback(boost::bind(&LLFloaterWater::onVector3ControlZMoved, this, _1, &param_mgr->mNormalScale));
-
- // fresnel
- getChild<LLUICtrl>("WaterFresnelScale")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mFresnelScale));
- getChild<LLUICtrl>("WaterFresnelOffset")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mFresnelOffset));
-
- // scale above/below
- getChild<LLUICtrl>("WaterScaleAbove")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mScaleAbove));
- getChild<LLUICtrl>("WaterScaleBelow")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mScaleBelow));
-
- // blur mult
- getChild<LLUICtrl>("WaterBlurMult")->setCommitCallback(boost::bind(&LLFloaterWater::onFloatControlMoved, this, _1, &param_mgr->mBlurMultiplier));
-
- // Load/save
-// getChild<LLUICtrl>("WaterLoadPreset")->setCommitCallback(boost::bind(&LLFloaterWater::onLoadPreset, this));
- getChild<LLUICtrl>("WaterNewPreset")->setCommitCallback(boost::bind(&LLFloaterWater::onNewPreset, this));
- getChild<LLUICtrl>("WaterSavePreset")->setCommitCallback(boost::bind(&LLFloaterWater::onSavePreset, this));
- getChild<LLUICtrl>("WaterDeletePreset")->setCommitCallback(boost::bind(&LLFloaterWater::onDeletePreset, this));
-
- // wave direction
- getChild<LLUICtrl>("WaterWave1DirX")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlXMoved, this, _1, &param_mgr->mWave1Dir));
- getChild<LLUICtrl>("WaterWave1DirY")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlYMoved, this, _1, &param_mgr->mWave1Dir));
- getChild<LLUICtrl>("WaterWave2DirX")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlXMoved, this, _1, &param_mgr->mWave2Dir));
- getChild<LLUICtrl>("WaterWave2DirY")->setCommitCallback(boost::bind(&LLFloaterWater::onVector2ControlYMoved, this, _1, &param_mgr->mWave2Dir));
-
- getChild<LLUICtrl>("WaterPresetsCombo")->setCommitCallback(boost::bind(&LLFloaterWater::onChangePresetName, this, _1));
-
- LLTextureCtrl* textCtrl = getChild<LLTextureCtrl>("WaterNormalMap");
- textCtrl->setDefaultImageAssetID(DEFAULT_WATER_NORMAL);
- getChild<LLUICtrl>("WaterNormalMap")->setCommitCallback(boost::bind(&LLFloaterWater::onNormalMapPicked, this, _1));
-}
-
-bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& response)
-{
- std::string text = response["message"].asString();
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- if(text == "")
- {
- return false;
- }
-
- if(option == 0) {
- LLComboBox* comboBox = getChild<LLComboBox>( "WaterPresetsCombo");
-
- LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
-
- // add the current parameters to the list
- // see if it's there first
- std::map<std::string, LLWaterParamSet>::iterator mIt =
- param_mgr->mParamList.find(text);
-
- // if not there, add a new one
- if(mIt == param_mgr->mParamList.end())
- {
- param_mgr->addParamSet(text, param_mgr->mCurParams);
- comboBox->add(text);
- comboBox->sortByName();
-
- comboBox->setSelectedByValue(text, true);
-
- param_mgr->savePreset(text);
-
- // otherwise, send a message to the user
- }
- else
- {
- LLNotificationsUtil::add("ExistsWaterPresetAlert");
- }
- }
- return false;
-}
-
-void LLFloaterWater::syncMenu()
-{
- bool err;
-
- LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
-
- LLWaterParamSet & current_params = param_mgr->mCurParams;
-
- // blue horizon
- param_mgr->mFogColor = current_params.getVector4(param_mgr->mFogColor.mName, err);
-
- LLColor4 col = param_mgr->getFogColor();
- getChild<LLUICtrl>("WaterGlow")->setValue(col.mV[3]);
- col.mV[3] = 1.0f;
- LLColorSwatchCtrl* colCtrl = getChild<LLColorSwatchCtrl>("WaterFogColor");
-
- colCtrl->set(col);
-
- // fog and wavelets
- param_mgr->mFogDensity.mExp =
- log(current_params.getFloat(param_mgr->mFogDensity.mName, err)) /
- log(param_mgr->mFogDensity.mBase);
- param_mgr->setDensitySliderValue(param_mgr->mFogDensity.mExp);
- getChild<LLUICtrl>("WaterFogDensity")->setValue(param_mgr->mFogDensity.mExp);
-
- param_mgr->mUnderWaterFogMod.mX =
- current_params.getFloat(param_mgr->mUnderWaterFogMod.mName, err);
- getChild<LLUICtrl>("WaterUnderWaterFogMod")->setValue(param_mgr->mUnderWaterFogMod.mX);
-
- param_mgr->mNormalScale = current_params.getVector3(param_mgr->mNormalScale.mName, err);
- getChild<LLUICtrl>("WaterNormalScaleX")->setValue(param_mgr->mNormalScale.mX);
- getChild<LLUICtrl>("WaterNormalScaleY")->setValue(param_mgr->mNormalScale.mY);
- getChild<LLUICtrl>("WaterNormalScaleZ")->setValue(param_mgr->mNormalScale.mZ);
-
- // Fresnel
- param_mgr->mFresnelScale.mX = current_params.getFloat(param_mgr->mFresnelScale.mName, err);
- getChild<LLUICtrl>("WaterFresnelScale")->setValue(param_mgr->mFresnelScale.mX);
- param_mgr->mFresnelOffset.mX = current_params.getFloat(param_mgr->mFresnelOffset.mName, err);
- getChild<LLUICtrl>("WaterFresnelOffset")->setValue(param_mgr->mFresnelOffset.mX);
-
- // Scale Above/Below
- param_mgr->mScaleAbove.mX = current_params.getFloat(param_mgr->mScaleAbove.mName, err);
- getChild<LLUICtrl>("WaterScaleAbove")->setValue(param_mgr->mScaleAbove.mX);
- param_mgr->mScaleBelow.mX = current_params.getFloat(param_mgr->mScaleBelow.mName, err);
- getChild<LLUICtrl>("WaterScaleBelow")->setValue(param_mgr->mScaleBelow.mX);
-
- // blur mult
- param_mgr->mBlurMultiplier.mX = current_params.getFloat(param_mgr->mBlurMultiplier.mName, err);
- getChild<LLUICtrl>("WaterBlurMult")->setValue(param_mgr->mBlurMultiplier.mX);
-
- // wave directions
- param_mgr->mWave1Dir = current_params.getVector2(param_mgr->mWave1Dir.mName, err);
- getChild<LLUICtrl>("WaterWave1DirX")->setValue(param_mgr->mWave1Dir.mX);
- getChild<LLUICtrl>("WaterWave1DirY")->setValue(param_mgr->mWave1Dir.mY);
-
- param_mgr->mWave2Dir = current_params.getVector2(param_mgr->mWave2Dir.mName, err);
- getChild<LLUICtrl>("WaterWave2DirX")->setValue(param_mgr->mWave2Dir.mX);
- getChild<LLUICtrl>("WaterWave2DirY")->setValue(param_mgr->mWave2Dir.mY);
-
- LLTextureCtrl* textCtrl = getChild<LLTextureCtrl>("WaterNormalMap");
- textCtrl->setImageAssetID(param_mgr->getNormalMapID());
-}
-
-
-// vector control callbacks
-void LLFloaterWater::onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- vectorControl->mX = sldrCtrl->getValueF32();
-
- vectorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-// vector control callbacks
-void LLFloaterWater::onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- vectorControl->mY = sldrCtrl->getValueF32();
-
- vectorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-// vector control callbacks
-void LLFloaterWater::onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vectorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- vectorControl->mZ = sldrCtrl->getValueF32();
-
- vectorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-
-// vector control callbacks
-void LLFloaterWater::onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- vectorControl->mX = sldrCtrl->getValueF32();
-
- vectorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-// vector control callbacks
-void LLFloaterWater::onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vectorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- vectorControl->mY = sldrCtrl->getValueF32();
-
- vectorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-// color control callbacks
-void LLFloaterWater::onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->mR = sldrCtrl->getValueF32();
-
- // move i if it's the max
- if(colorControl->mR >= colorControl->mG
- && colorControl->mR >= colorControl->mB
- && colorControl->mHasSliderName)
- {
- colorControl->mI = colorControl->mR;
- std::string name = colorControl->mSliderName;
- name.append("I");
-
- getChild<LLUICtrl>(name)->setValue(colorControl->mR);
- }
-
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->mG = sldrCtrl->getValueF32();
-
- // move i if it's the max
- if(colorControl->mG >= colorControl->mR
- && colorControl->mG >= colorControl->mB
- && colorControl->mHasSliderName)
- {
- colorControl->mI = colorControl->mG;
- std::string name = colorControl->mSliderName;
- name.append("I");
-
- getChild<LLUICtrl>(name)->setValue(colorControl->mG);
-
- }
-
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->mB = sldrCtrl->getValueF32();
-
- // move i if it's the max
- if(colorControl->mB >= colorControl->mR
- && colorControl->mB >= colorControl->mG
- && colorControl->mHasSliderName)
- {
- colorControl->mI = colorControl->mB;
- std::string name = colorControl->mSliderName;
- name.append("I");
-
- getChild<LLUICtrl>(name)->setValue(colorControl->mB);
- }
-
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWater::onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->mA = sldrCtrl->getValueF32();
-
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
-
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-
-void LLFloaterWater::onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->mI = sldrCtrl->getValueF32();
-
- // only for sliders where we pass a name
- if(colorControl->mHasSliderName)
- {
- // set it to the top
- F32 maxVal = std::max(std::max(colorControl->mR, colorControl->mG), colorControl->mB);
- F32 iVal;
-
- iVal = colorControl->mI;
-
- // get the names of the other sliders
- std::string rName = colorControl->mSliderName;
- rName.append("R");
- std::string gName = colorControl->mSliderName;
- gName.append("G");
- std::string bName = colorControl->mSliderName;
- bName.append("B");
-
- // handle if at 0
- if(iVal == 0)
- {
- colorControl->mR = 0;
- colorControl->mG = 0;
- colorControl->mB = 0;
-
- // if all at the start
- // set them all to the intensity
- }
- else if (maxVal == 0)
- {
- colorControl->mR = iVal;
- colorControl->mG = iVal;
- colorControl->mB = iVal;
- }
- else
- {
- // add delta amounts to each
- F32 delta = (iVal - maxVal) / maxVal;
- colorControl->mR *= (1.0f + delta);
- colorControl->mG *= (1.0f + delta);
- colorControl->mB *= (1.0f + delta);
- }
-
- // set the sliders to the new vals
- getChild<LLUICtrl>(rName)->setValue(colorControl->mR);
- getChild<LLUICtrl>(gName)->setValue(colorControl->mG);
- getChild<LLUICtrl>(bName)->setValue(colorControl->mB);
- }
-
- // now update the current parameters and send them to shaders
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWater::onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- F32 val = sldrCtrl->getValueF32();
- expFloatControl->mExp = val;
- LLWaterParamManager::instance()->setDensitySliderValue(val);
-
- expFloatControl->update(LLWaterParamManager::instance()->mCurParams);
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWater::onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl)
-{
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- floatControl->mX = sldrCtrl->getValueF32() / floatControl->mMult;
-
- floatControl->update(LLWaterParamManager::instance()->mCurParams);
- LLWaterParamManager::instance()->propagateParameters();
-}
-void LLFloaterWater::onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* colorControl)
-{
- LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
- *colorControl = swatch->get();
-
- colorControl->update(LLWaterParamManager::instance()->mCurParams);
- LLWaterParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWater::onNormalMapPicked(LLUICtrl* ctrl)
-{
- LLTextureCtrl* textCtrl = static_cast<LLTextureCtrl*>(ctrl);
- LLUUID textID = textCtrl->getImageAssetID();
- LLWaterParamManager::instance()->setNormalMapID(textID);
-}
-
-void LLFloaterWater::onNewPreset()
-{
- LLNotificationsUtil::add("NewWaterPreset", LLSD(), LLSD(), boost::bind(&LLFloaterWater::newPromptCallback, this, _1, _2));
-}
-
-void LLFloaterWater::onSavePreset()
-{
- // get the name
- LLComboBox* comboBox = getChild<LLComboBox>("WaterPresetsCombo");
-
- // don't save the empty name
- if(comboBox->getSelectedItemLabel() == "")
- {
- return;
- }
-
- LLWaterParamManager::instance()->mCurParams.mName =
- comboBox->getSelectedItemLabel();
-
- // check to see if it's a default and shouldn't be overwritten
- std::set<std::string>::iterator sIt = sDefaultPresets.find(
- comboBox->getSelectedItemLabel());
- if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("WaterEditPresets"))
- {
- LLNotificationsUtil::add("WLNoEditDefault");
- return;
- }
-
- LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterWater::saveAlertCallback, this, _1, _2));
-}
-
-bool LLFloaterWater::saveAlertCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- // if they choose save, do it. Otherwise, don't do anything
- if(option == 0)
- {
- LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
-
- param_mgr->setParamSet(
- param_mgr->mCurParams.mName,
- param_mgr->mCurParams);
-
- // comment this back in to save to file
- param_mgr->savePreset(param_mgr->mCurParams.mName);
- }
- return false;
-}
-
-void LLFloaterWater::onDeletePreset()
-{
- LLComboBox* combo_box = getChild<LLComboBox>("WaterPresetsCombo");
-
- if(combo_box->getSelectedValue().asString() == "")
- {
- return;
- }
-
- LLSD args;
- args["SKY"] = combo_box->getSelectedValue().asString();
- LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(), boost::bind(&LLFloaterWater::deleteAlertCallback, this, _1, _2));
-}
-
-bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- // if they choose delete, do it. Otherwise, don't do anything
- if(option == 0)
- {
- LLComboBox* combo_box = getChild<LLComboBox>("WaterPresetsCombo");
- LLFloaterDayCycle* day_cycle = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
- LLComboBox* key_combo = NULL;
-
- if (day_cycle)
- {
- key_combo = day_cycle->getChild<LLComboBox>("WaterKeyPresets");
- }
-
- std::string name = combo_box->getSelectedValue().asString();
-
- // check to see if it's a default and shouldn't be deleted
- std::set<std::string>::iterator sIt = sDefaultPresets.find(name);
- if(sIt != sDefaultPresets.end())
- {
- LLNotificationsUtil::add("WaterNoEditDefault");
- return false;
- }
-
- LLWaterParamManager::instance()->removeParamSet(name, true);
-
- // remove and choose another
- S32 new_index = combo_box->getCurrentIndex();
-
- combo_box->remove(name);
-
- if(key_combo != NULL)
- {
- key_combo->remove(name);
-
- // remove from slider, as well
- day_cycle->deletePreset(name);
- }
-
- // pick the previously selected index after delete
- if(new_index > 0)
- {
- new_index--;
- }
-
- if(combo_box->getItemCount() > 0)
- {
- combo_box->setCurrentByIndex(new_index);
- }
- }
- return false;
-}
-
-
-void LLFloaterWater::onChangePresetName(LLUICtrl* ctrl)
-{
- std::string data = ctrl->getValue().asString();
- if(!data.empty())
- {
- LLWaterParamManager::instance()->loadPreset(data);
- syncMenu();
- }
-}
-
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 058567492b..43eecbf048 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -99,7 +99,7 @@ void LLFloaterWebContent::initializeURLHistory()
}
//static
-void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
+void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid, bool show_chrome, const LLRect& preferred_media_size)
{
lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
@@ -155,6 +155,20 @@ void LLFloaterWebContent::create( const std::string &url, const std::string& tar
// tell the browser instance to load the specified URL
browser->open_media(url, target);
LLViewerMedia::proxyWindowOpened(target, uuid);
+
+ browser->getChild<LLLayoutPanel>("status_bar")->setVisible(show_chrome);
+ browser->getChild<LLLayoutPanel>("nav_controls")->setVisible(show_chrome);
+
+ if (!show_chrome)
+ {
+ browser->setResizeLimits(100, 100);
+ }
+
+ if (!preferred_media_size.isEmpty())
+ {
+ //ignore x, y for now
+ browser->geometryChanged(browser->getRect().mLeft, browser->getRect().mBottom, preferred_media_size.getWidth(), preferred_media_size.getHeight());
+ }
}
}
@@ -210,7 +224,7 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
lldebugs << "geometry change: " << geom << llendl;
- handleReshape(geom,false);
+ setShape(geom);
}
void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index ecc7e970d8..56b6ef12c8 100644
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -46,7 +46,7 @@ public:
void initializeURLHistory();
- static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
+ static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null, bool show_chrome = true, const LLRect& preferred_media_size = LLRect() );
static void closeRequest(const std::string &uuid);
static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp
deleted file mode 100644
index ae98b2cf99..0000000000
--- a/indra/newview/llfloaterwindlight.cpp
+++ /dev/null
@@ -1,875 +0,0 @@
-/**
- * @file llfloaterwindlight.cpp
- * @brief LLFloaterWindLight class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterwindlight.h"
-
-#include "pipeline.h"
-#include "llsky.h"
-
-#include "llfloaterreg.h"
-#include "llsliderctrl.h"
-#include "llmultislider.h"
-#include "llmultisliderctrl.h"
-#include "llnotificationsutil.h"
-#include "llspinctrl.h"
-#include "llcheckboxctrl.h"
-#include "lluictrlfactory.h"
-#include "llviewercamera.h"
-#include "llcombobox.h"
-#include "lllineeditor.h"
-#include "llfloaterdaycycle.h"
-#include "llboost.h"
-
-#include "v4math.h"
-#include "llviewerdisplay.h"
-#include "llviewercontrol.h"
-#include "llviewerwindow.h"
-#include "llsavedsettingsglue.h"
-
-#include "llwlparamset.h"
-#include "llwlparammanager.h"
-#include "llpostprocess.h"
-#include "lltabcontainer.h"
-
-
-#undef max
-
-std::set<std::string> LLFloaterWindLight::sDefaultPresets;
-
-static const F32 WL_SUN_AMBIENT_SLIDER_SCALE = 3.0f;
-
-LLFloaterWindLight::LLFloaterWindLight(const LLSD& key)
- : LLFloater(key)
-{
-}
-
-LLFloaterWindLight::~LLFloaterWindLight()
-{
-}
-
-BOOL LLFloaterWindLight::postBuild()
-{
- // add the list of presets
- std::string def_days = getString("WLDefaultSkyNames");
-
- // no editing or deleting of the blank string
- sDefaultPresets.insert("");
- boost_tokenizer tokens(def_days, boost::char_separator<char>(":"));
- for (boost_tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- std::string tok(*token_iter);
- sDefaultPresets.insert(tok);
- }
-
- // add the combo boxes
- LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
-
- if(comboBox != NULL) {
-
- std::map<std::string, LLWLParamSet>::iterator mIt =
- LLWLParamManager::instance()->mParamList.begin();
- for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++)
- {
- comboBox->add(mIt->first);
- }
-
- // entry for when we're in estate time
- comboBox->add(LLStringUtil::null);
-
- // set defaults on combo boxes
- comboBox->selectByValue(LLSD("Default"));
- }
- // load it up
- initCallbacks();
-
- syncMenu();
-
- return TRUE;
-}
-void LLFloaterWindLight::initCallbacks(void) {
-
- LLWLParamManager * param_mgr = LLWLParamManager::instance();
-
- // blue horizon
- getChild<LLUICtrl>("WLBlueHorizonR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mBlueHorizon));
- getChild<LLUICtrl>("WLBlueHorizonG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mBlueHorizon));
- getChild<LLUICtrl>("WLBlueHorizonB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mBlueHorizon));
- getChild<LLUICtrl>("WLBlueHorizonI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mBlueHorizon));
-
- // haze density, horizon, mult, and altitude
- getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mHazeDensity));
- getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mHazeHorizon));
- getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mDensityMult));
- getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mMaxAlt));
-
- // blue density
- getChild<LLUICtrl>("WLBlueDensityR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mBlueDensity));
- getChild<LLUICtrl>("WLBlueDensityG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mBlueDensity));
- getChild<LLUICtrl>("WLBlueDensityB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mBlueDensity));
- getChild<LLUICtrl>("WLBlueDensityI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mBlueDensity));
-
- // Lighting
-
- // sunlight
- getChild<LLUICtrl>("WLSunlightR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mSunlight));
- getChild<LLUICtrl>("WLSunlightG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mSunlight));
- getChild<LLUICtrl>("WLSunlightB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mSunlight));
- getChild<LLUICtrl>("WLSunlightI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mSunlight));
-
- // glow
- getChild<LLUICtrl>("WLGlowR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onGlowRMoved, this, _1, &param_mgr->mGlow));
- getChild<LLUICtrl>("WLGlowB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onGlowBMoved, this, _1, &param_mgr->mGlow));
-
- // ambient
- getChild<LLUICtrl>("WLAmbientR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mAmbient));
- getChild<LLUICtrl>("WLAmbientG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mAmbient));
- getChild<LLUICtrl>("WLAmbientB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mAmbient));
- getChild<LLUICtrl>("WLAmbientI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mAmbient));
-
- // time of day
- getChild<LLUICtrl>("WLSunAngle")->setCommitCallback(boost::bind(&LLFloaterWindLight::onSunMoved, this, _1, &param_mgr->mLightnorm));
- getChild<LLUICtrl>("WLEastAngle")->setCommitCallback(boost::bind(&LLFloaterWindLight::onSunMoved, this, _1, &param_mgr->mLightnorm));
-
- // Clouds
-
- // Cloud Color
- getChild<LLUICtrl>("WLCloudColorR")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mCloudColor));
- getChild<LLUICtrl>("WLCloudColorG")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mCloudColor));
- getChild<LLUICtrl>("WLCloudColorB")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mCloudColor));
- getChild<LLUICtrl>("WLCloudColorI")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlIMoved, this, _1, &param_mgr->mCloudColor));
-
- // Cloud
- getChild<LLUICtrl>("WLCloudX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mCloudMain));
- getChild<LLUICtrl>("WLCloudY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mCloudMain));
- getChild<LLUICtrl>("WLCloudDensity")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mCloudMain));
-
- // Cloud Detail
- getChild<LLUICtrl>("WLCloudDetailX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlRMoved, this, _1, &param_mgr->mCloudDetail));
- getChild<LLUICtrl>("WLCloudDetailY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlGMoved, this, _1, &param_mgr->mCloudDetail));
- getChild<LLUICtrl>("WLCloudDetailDensity")->setCommitCallback(boost::bind(&LLFloaterWindLight::onColorControlBMoved, this, _1, &param_mgr->mCloudDetail));
-
- // Cloud extras
- getChild<LLUICtrl>("WLCloudCoverage")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mCloudCoverage));
- getChild<LLUICtrl>("WLCloudScale")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mCloudScale));
- getChild<LLUICtrl>("WLCloudLockX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollXToggled, this, _1));
- getChild<LLUICtrl>("WLCloudLockY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollYToggled, this, _1));
- getChild<LLUICtrl>("WLCloudScrollX")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollXMoved, this, _1));
- getChild<LLUICtrl>("WLCloudScrollY")->setCommitCallback(boost::bind(&LLFloaterWindLight::onCloudScrollYMoved, this, _1));
- getChild<LLUICtrl>("WLDistanceMult")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mDistanceMult));
- getChild<LLUICtrl>("DrawClassicClouds")->setCommitCallback(boost::bind(LLSavedSettingsGlue::setBOOL, _1, "SkyUseClassicClouds"));
-
- // WL Top
- getChild<LLUICtrl>("WLDayCycleMenuButton")->setCommitCallback(boost::bind(&LLFloaterWindLight::onOpenDayCycle, this));
- // Load/save
- LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
-
- //childSetAction("WLLoadPreset", onLoadPreset, comboBox);
- getChild<LLUICtrl>("WLNewPreset")->setCommitCallback(boost::bind(&LLFloaterWindLight::onNewPreset, this));
- getChild<LLUICtrl>("WLSavePreset")->setCommitCallback(boost::bind(&LLFloaterWindLight::onSavePreset, this));
- getChild<LLUICtrl>("WLDeletePreset")->setCommitCallback(boost::bind(&LLFloaterWindLight::onDeletePreset, this));
-
- comboBox->setCommitCallback(boost::bind(&LLFloaterWindLight::onChangePresetName, this, _1));
-
-
- // Dome
- getChild<LLUICtrl>("WLGamma")->setCommitCallback(boost::bind(&LLFloaterWindLight::onFloatControlMoved, this, _1, &param_mgr->mWLGamma));
- getChild<LLUICtrl>("WLStarAlpha")->setCommitCallback(boost::bind(&LLFloaterWindLight::onStarAlphaMoved, this, _1));
-}
-
-bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD& response)
-{
- std::string text = response["message"].asString();
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- if(text == "")
- {
- return false;
- }
-
- if(option == 0) {
- LLComboBox* comboBox = getChild<LLComboBox>("WLPresetsCombo");
-
- LLFloaterDayCycle* day_cycle = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
- LLComboBox* keyCombo = NULL;
- if(day_cycle)
- {
- keyCombo = day_cycle->getChild<LLComboBox>("WLKeyPresets");
- }
-
- // add the current parameters to the list
- // see if it's there first
- std::map<std::string, LLWLParamSet>::iterator mIt =
- LLWLParamManager::instance()->mParamList.find(text);
-
- // if not there, add a new one
- if(mIt == LLWLParamManager::instance()->mParamList.end())
- {
- LLWLParamManager::instance()->addParamSet(text,
- LLWLParamManager::instance()->mCurParams);
- comboBox->add(text);
- comboBox->sortByName();
-
- // add a blank to the bottom
- comboBox->selectFirstItem();
- if(comboBox->getSimple() == "")
- {
- comboBox->remove(0);
- }
- comboBox->add(LLStringUtil::null);
-
- comboBox->setSelectedByValue(text, true);
- if(keyCombo)
- {
- keyCombo->add(text);
- keyCombo->sortByName();
- }
- LLWLParamManager::instance()->savePreset(text);
-
- // otherwise, send a message to the user
- }
- else
- {
- LLNotificationsUtil::add("ExistsSkyPresetAlert");
- }
- }
- return false;
-}
-
-void LLFloaterWindLight::syncMenu()
-{
- bool err;
-
- LLWLParamManager * param_mgr = LLWLParamManager::instance();
-
- LLWLParamSet& currentParams = param_mgr->mCurParams;
- //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues;
-
- // blue horizon
- param_mgr->mBlueHorizon = currentParams.getVector(param_mgr->mBlueHorizon.mName, err);
- getChild<LLUICtrl>("WLBlueHorizonR")->setValue(param_mgr->mBlueHorizon.r / 2.0);
- getChild<LLUICtrl>("WLBlueHorizonG")->setValue(param_mgr->mBlueHorizon.g / 2.0);
- getChild<LLUICtrl>("WLBlueHorizonB")->setValue(param_mgr->mBlueHorizon.b / 2.0);
- getChild<LLUICtrl>("WLBlueHorizonI")->setValue(
- std::max(param_mgr->mBlueHorizon.r / 2.0,
- std::max(param_mgr->mBlueHorizon.g / 2.0,
- param_mgr->mBlueHorizon.b / 2.0)));
-
- // haze density, horizon, mult, and altitude
- param_mgr->mHazeDensity = currentParams.getVector(param_mgr->mHazeDensity.mName, err);
- getChild<LLUICtrl>("WLHazeDensity")->setValue(param_mgr->mHazeDensity.r);
- param_mgr->mHazeHorizon = currentParams.getVector(param_mgr->mHazeHorizon.mName, err);
- getChild<LLUICtrl>("WLHazeHorizon")->setValue(param_mgr->mHazeHorizon.r);
- param_mgr->mDensityMult = currentParams.getVector(param_mgr->mDensityMult.mName, err);
- getChild<LLUICtrl>("WLDensityMult")->setValue(param_mgr->mDensityMult.x *
- param_mgr->mDensityMult.mult);
- param_mgr->mMaxAlt = currentParams.getVector(param_mgr->mMaxAlt.mName, err);
- getChild<LLUICtrl>("WLMaxAltitude")->setValue(param_mgr->mMaxAlt.x);
-
- // blue density
- param_mgr->mBlueDensity = currentParams.getVector(param_mgr->mBlueDensity.mName, err);
- getChild<LLUICtrl>("WLBlueDensityR")->setValue(param_mgr->mBlueDensity.r / 2.0);
- getChild<LLUICtrl>("WLBlueDensityG")->setValue(param_mgr->mBlueDensity.g / 2.0);
- getChild<LLUICtrl>("WLBlueDensityB")->setValue(param_mgr->mBlueDensity.b / 2.0);
- getChild<LLUICtrl>("WLBlueDensityI")->setValue(
- std::max(param_mgr->mBlueDensity.r / 2.0,
- std::max(param_mgr->mBlueDensity.g / 2.0, param_mgr->mBlueDensity.b / 2.0)));
-
- // Lighting
-
- // sunlight
- param_mgr->mSunlight = currentParams.getVector(param_mgr->mSunlight.mName, err);
- getChild<LLUICtrl>("WLSunlightR")->setValue(param_mgr->mSunlight.r / WL_SUN_AMBIENT_SLIDER_SCALE);
- getChild<LLUICtrl>("WLSunlightG")->setValue(param_mgr->mSunlight.g / WL_SUN_AMBIENT_SLIDER_SCALE);
- getChild<LLUICtrl>("WLSunlightB")->setValue(param_mgr->mSunlight.b / WL_SUN_AMBIENT_SLIDER_SCALE);
- getChild<LLUICtrl>("WLSunlightI")->setValue(
- std::max(param_mgr->mSunlight.r / WL_SUN_AMBIENT_SLIDER_SCALE,
- std::max(param_mgr->mSunlight.g / WL_SUN_AMBIENT_SLIDER_SCALE, param_mgr->mSunlight.b / WL_SUN_AMBIENT_SLIDER_SCALE)));
-
- // glow
- param_mgr->mGlow = currentParams.getVector(param_mgr->mGlow.mName, err);
- getChild<LLUICtrl>("WLGlowR")->setValue(2 - param_mgr->mGlow.r / 20.0f);
- getChild<LLUICtrl>("WLGlowB")->setValue(-param_mgr->mGlow.b / 5.0f);
-
- // ambient
- param_mgr->mAmbient = currentParams.getVector(param_mgr->mAmbient.mName, err);
- getChild<LLUICtrl>("WLAmbientR")->setValue(param_mgr->mAmbient.r / WL_SUN_AMBIENT_SLIDER_SCALE);
- getChild<LLUICtrl>("WLAmbientG")->setValue(param_mgr->mAmbient.g / WL_SUN_AMBIENT_SLIDER_SCALE);
- getChild<LLUICtrl>("WLAmbientB")->setValue(param_mgr->mAmbient.b / WL_SUN_AMBIENT_SLIDER_SCALE);
- getChild<LLUICtrl>("WLAmbientI")->setValue(
- std::max(param_mgr->mAmbient.r / WL_SUN_AMBIENT_SLIDER_SCALE,
- std::max(param_mgr->mAmbient.g / WL_SUN_AMBIENT_SLIDER_SCALE, param_mgr->mAmbient.b / WL_SUN_AMBIENT_SLIDER_SCALE)));
-
- getChild<LLUICtrl>("WLSunAngle")->setValue(param_mgr->mCurParams.getFloat("sun_angle",err) / F_TWO_PI);
- getChild<LLUICtrl>("WLEastAngle")->setValue(param_mgr->mCurParams.getFloat("east_angle",err) / F_TWO_PI);
-
- // Clouds
-
- // Cloud Color
- param_mgr->mCloudColor = currentParams.getVector(param_mgr->mCloudColor.mName, err);
- getChild<LLUICtrl>("WLCloudColorR")->setValue(param_mgr->mCloudColor.r);
- getChild<LLUICtrl>("WLCloudColorG")->setValue(param_mgr->mCloudColor.g);
- getChild<LLUICtrl>("WLCloudColorB")->setValue(param_mgr->mCloudColor.b);
- getChild<LLUICtrl>("WLCloudColorI")->setValue(
- std::max(param_mgr->mCloudColor.r,
- std::max(param_mgr->mCloudColor.g, param_mgr->mCloudColor.b)));
-
- // Cloud
- param_mgr->mCloudMain = currentParams.getVector(param_mgr->mCloudMain.mName, err);
- getChild<LLUICtrl>("WLCloudX")->setValue(param_mgr->mCloudMain.r);
- getChild<LLUICtrl>("WLCloudY")->setValue(param_mgr->mCloudMain.g);
- getChild<LLUICtrl>("WLCloudDensity")->setValue(param_mgr->mCloudMain.b);
-
- // Cloud Detail
- param_mgr->mCloudDetail = currentParams.getVector(param_mgr->mCloudDetail.mName, err);
- getChild<LLUICtrl>("WLCloudDetailX")->setValue(param_mgr->mCloudDetail.r);
- getChild<LLUICtrl>("WLCloudDetailY")->setValue(param_mgr->mCloudDetail.g);
- getChild<LLUICtrl>("WLCloudDetailDensity")->setValue(param_mgr->mCloudDetail.b);
-
- // Cloud extras
- param_mgr->mCloudCoverage = currentParams.getVector(param_mgr->mCloudCoverage.mName, err);
- param_mgr->mCloudScale = currentParams.getVector(param_mgr->mCloudScale.mName, err);
- getChild<LLUICtrl>("WLCloudCoverage")->setValue(param_mgr->mCloudCoverage.x);
- getChild<LLUICtrl>("WLCloudScale")->setValue(param_mgr->mCloudScale.x);
-
- // cloud scrolling
- bool lockX = !param_mgr->mCurParams.getEnableCloudScrollX();
- bool lockY = !param_mgr->mCurParams.getEnableCloudScrollY();
- getChild<LLUICtrl>("WLCloudLockX")->setValue(lockX);
- getChild<LLUICtrl>("WLCloudLockY")->setValue(lockY);
- getChild<LLUICtrl>("DrawClassicClouds")->setValue(gSavedSettings.getBOOL("SkyUseClassicClouds"));
-
- // disable if locked, enable if not
- if(lockX)
- {
- getChildView("WLCloudScrollX")->setEnabled(FALSE);
- } else {
- getChildView("WLCloudScrollX")->setEnabled(TRUE);
- }
- if(lockY)
- {
- getChildView("WLCloudScrollY")->setEnabled(FALSE);
- } else {
- getChildView("WLCloudScrollY")->setEnabled(TRUE);
- }
-
- // *HACK cloud scrolling is off my an additive of 10
- getChild<LLUICtrl>("WLCloudScrollX")->setValue(param_mgr->mCurParams.getCloudScrollX() - 10.0f);
- getChild<LLUICtrl>("WLCloudScrollY")->setValue(param_mgr->mCurParams.getCloudScrollY() - 10.0f);
-
- param_mgr->mDistanceMult = currentParams.getVector(param_mgr->mDistanceMult.mName, err);
- getChild<LLUICtrl>("WLDistanceMult")->setValue(param_mgr->mDistanceMult.x);
-
- // Tweak extras
-
- param_mgr->mWLGamma = currentParams.getVector(param_mgr->mWLGamma.mName, err);
- getChild<LLUICtrl>("WLGamma")->setValue(param_mgr->mWLGamma.x);
-
- getChild<LLUICtrl>("WLStarAlpha")->setValue(param_mgr->mCurParams.getStarBrightness());
-
- LLTabContainer* tab = getChild<LLTabContainer>("WindLight Tabs");
- LLPanel* panel = getChild<LLPanel>("Scattering");
-
- tab->enableTabButton(tab->getIndexForPanel(panel), gSavedSettings.getBOOL("RenderDeferredGI"));
-}
-
-
-// color control callbacks
-void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->r = sldrCtrl->getValueF32();
- if(colorControl->isSunOrAmbientColor) {
- colorControl->r *= 3;
- }
- if(colorControl->isBlueHorizonOrDensity) {
- colorControl->r *= 2;
- }
-
- // move i if it's the max
- if(colorControl->r >= colorControl->g && colorControl->r >= colorControl->b
- && colorControl->hasSliderName) {
- colorControl->i = colorControl->r;
- std::string name = colorControl->mSliderName;
- name.append("I");
-
- if(colorControl->isSunOrAmbientColor) {
- getChild<LLUICtrl>(name)->setValue(colorControl->r / 3);
- } else if(colorControl->isBlueHorizonOrDensity) {
- getChild<LLUICtrl>(name)->setValue(colorControl->r / 2);
- } else {
- getChild<LLUICtrl>(name)->setValue(colorControl->r);
- }
- }
-
- colorControl->update(LLWLParamManager::instance()->mCurParams);
-
- LLWLParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->g = sldrCtrl->getValueF32();
- if(colorControl->isSunOrAmbientColor) {
- colorControl->g *= 3;
- }
- if(colorControl->isBlueHorizonOrDensity) {
- colorControl->g *= 2;
- }
-
- // move i if it's the max
- if(colorControl->g >= colorControl->r && colorControl->g >= colorControl->b
- && colorControl->hasSliderName) {
- colorControl->i = colorControl->g;
- std::string name = colorControl->mSliderName;
- name.append("I");
-
- if(colorControl->isSunOrAmbientColor) {
- getChild<LLUICtrl>(name)->setValue(colorControl->g / 3);
- } else if(colorControl->isBlueHorizonOrDensity) {
- getChild<LLUICtrl>(name)->setValue(colorControl->g / 2);
- } else {
- getChild<LLUICtrl>(name)->setValue(colorControl->g);
- }
- }
-
- colorControl->update(LLWLParamManager::instance()->mCurParams);
-
- LLWLParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->b = sldrCtrl->getValueF32();
- if(colorControl->isSunOrAmbientColor) {
- colorControl->b *= 3;
- }
- if(colorControl->isBlueHorizonOrDensity) {
- colorControl->b *= 2;
- }
-
- // move i if it's the max
- if(colorControl->b >= colorControl->r && colorControl->b >= colorControl->g
- && colorControl->hasSliderName) {
- colorControl->i = colorControl->b;
- std::string name = colorControl->mSliderName;
- name.append("I");
-
- if(colorControl->isSunOrAmbientColor) {
- getChild<LLUICtrl>(name)->setValue(colorControl->b / 3);
- } else if(colorControl->isBlueHorizonOrDensity) {
- getChild<LLUICtrl>(name)->setValue(colorControl->b / 2);
- } else {
- getChild<LLUICtrl>(name)->setValue(colorControl->b);
- }
- }
-
- colorControl->update(LLWLParamManager::instance()->mCurParams);
-
- LLWLParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- colorControl->i = sldrCtrl->getValueF32();
-
- // only for sliders where we pass a name
- if(colorControl->hasSliderName) {
-
- // set it to the top
- F32 maxVal = std::max(std::max(colorControl->r, colorControl->g), colorControl->b);
- F32 iVal;
-
- if(colorControl->isSunOrAmbientColor)
- {
- iVal = colorControl->i * 3;
- }
- else if(colorControl->isBlueHorizonOrDensity)
- {
- iVal = colorControl->i * 2;
- }
- else
- {
- iVal = colorControl->i;
- }
-
- // get the names of the other sliders
- std::string rName = colorControl->mSliderName;
- rName.append("R");
- std::string gName = colorControl->mSliderName;
- gName.append("G");
- std::string bName = colorControl->mSliderName;
- bName.append("B");
-
- // handle if at 0
- if(iVal == 0) {
- colorControl->r = 0;
- colorControl->g = 0;
- colorControl->b = 0;
-
- // if all at the start
- // set them all to the intensity
- } else if (maxVal == 0) {
- colorControl->r = iVal;
- colorControl->g = iVal;
- colorControl->b = iVal;
-
- } else {
-
- // add delta amounts to each
- F32 delta = (iVal - maxVal) / maxVal;
- colorControl->r *= (1.0f + delta);
- colorControl->g *= (1.0f + delta);
- colorControl->b *= (1.0f + delta);
- }
-
- // divide sun color vals by three
- if(colorControl->isSunOrAmbientColor)
- {
- getChild<LLUICtrl>(rName)->setValue(colorControl->r/3);
- getChild<LLUICtrl>(gName)->setValue(colorControl->g/3);
- getChild<LLUICtrl>(bName)->setValue(colorControl->b/3);
-
- }
- else if(colorControl->isBlueHorizonOrDensity)
- {
- getChild<LLUICtrl>(rName)->setValue(colorControl->r/2);
- getChild<LLUICtrl>(gName)->setValue(colorControl->g/2);
- getChild<LLUICtrl>(bName)->setValue(colorControl->b/2);
-
- }
- else
- {
- // set the sliders to the new vals
- getChild<LLUICtrl>(rName)->setValue(colorControl->r);
- getChild<LLUICtrl>(gName)->setValue(colorControl->g);
- getChild<LLUICtrl>(bName)->setValue(colorControl->b);
- }
- }
-
- // now update the current parameters and send them to shaders
- colorControl->update(LLWLParamManager::instance()->mCurParams);
- LLWLParamManager::instance()->propagateParameters();
-}
-
-/// GLOW SPECIFIC CODE
-void LLFloaterWindLight::onGlowRMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- // scaled by 20
- colorControl->r = (2 - sldrCtrl->getValueF32()) * 20;
-
- colorControl->update(LLWLParamManager::instance()->mCurParams);
- LLWLParamManager::instance()->propagateParameters();
-}
-
-/// \NOTE that we want NEGATIVE (-) B
-void LLFloaterWindLight::onGlowBMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- /// \NOTE that we want NEGATIVE (-) B and NOT by 20 as 20 is too big
- colorControl->b = -sldrCtrl->getValueF32() * 5;
-
- colorControl->update(LLWLParamManager::instance()->mCurParams);
- LLWLParamManager::instance()->propagateParameters();
-}
-
-void LLFloaterWindLight::onFloatControlMoved(LLUICtrl* ctrl, WLFloatControl* floatControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- floatControl->x = sldrCtrl->getValueF32() / floatControl->mult;
-
- floatControl->update(LLWLParamManager::instance()->mCurParams);
- LLWLParamManager::instance()->propagateParameters();
-}
-
-// Lighting callbacks
-
-// time of day
-void LLFloaterWindLight::onSunMoved(LLUICtrl* ctrl, WLColorControl* colorControl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sunSldr = getChild<LLSliderCtrl>("WLSunAngle");
- LLSliderCtrl* eastSldr = getChild<LLSliderCtrl>("WLEastAngle");
-
- // get the two angles
- LLWLParamManager * param_mgr = LLWLParamManager::instance();
-
- param_mgr->mCurParams.setSunAngle(F_TWO_PI * sunSldr->getValueF32());
- param_mgr->mCurParams.setEastAngle(F_TWO_PI * eastSldr->getValueF32());
-
- // set the sun vector
- colorControl->r = -sin(param_mgr->mCurParams.getEastAngle()) *
- cos(param_mgr->mCurParams.getSunAngle());
- colorControl->g = sin(param_mgr->mCurParams.getSunAngle());
- colorControl->b = cos(param_mgr->mCurParams.getEastAngle()) *
- cos(param_mgr->mCurParams.getSunAngle());
- colorControl->i = 1.f;
-
- colorControl->update(param_mgr->mCurParams);
- param_mgr->propagateParameters();
-}
-
-void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- LLWLParamManager::instance()->mCurParams.setStarBrightness(sldrCtrl->getValueF32());
-}
-
-void LLFloaterWindLight::onNewPreset()
-{
- LLNotificationsUtil::add("NewSkyPreset", LLSD(), LLSD(), boost::bind(&LLFloaterWindLight::newPromptCallback, this, _1, _2));
-}
-
-void LLFloaterWindLight::onSavePreset()
-{
- // get the name
- LLComboBox* comboBox = getChild<LLComboBox>(
- "WLPresetsCombo");
-
- // don't save the empty name
- if(comboBox->getSelectedItemLabel() == "")
- {
- return;
- }
-
- // check to see if it's a default and shouldn't be overwritten
- std::set<std::string>::iterator sIt = sDefaultPresets.find(
- comboBox->getSelectedItemLabel());
- if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("SkyEditPresets"))
- {
- LLNotificationsUtil::add("WLNoEditDefault");
- return;
- }
-
- LLWLParamManager::instance()->mCurParams.mName =
- comboBox->getSelectedItemLabel();
-
- LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterWindLight::saveAlertCallback, this, _1, _2));
-}
-
-bool LLFloaterWindLight::saveAlertCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- // if they choose save, do it. Otherwise, don't do anything
- if(option == 0)
- {
- LLWLParamManager * param_mgr = LLWLParamManager::instance();
-
- param_mgr->setParamSet(param_mgr->mCurParams.mName, param_mgr->mCurParams);
-
- // comment this back in to save to file
- param_mgr->savePreset(param_mgr->mCurParams.mName);
- }
- return false;
-}
-
-void LLFloaterWindLight::onDeletePreset()
-{
- LLComboBox* combo_box = getChild<LLComboBox>(
- "WLPresetsCombo");
-
- if(combo_box->getSelectedValue().asString() == "")
- {
- return;
- }
-
- LLSD args;
- args["SKY"] = combo_box->getSelectedValue().asString();
- LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(),
- boost::bind(&LLFloaterWindLight::deleteAlertCallback, this, _1, _2));
-}
-
-bool LLFloaterWindLight::deleteAlertCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
- // if they choose delete, do it. Otherwise, don't do anything
- if(option == 0)
- {
- LLComboBox* combo_box = getChild<LLComboBox>("WLPresetsCombo");
- LLFloaterDayCycle* day_cycle = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
- LLComboBox* key_combo = NULL;
-
- if (day_cycle)
- {
- key_combo = day_cycle->getChild<LLComboBox>("WLKeyPresets");
- }
-
- std::string name(combo_box->getSelectedValue().asString());
-
- // check to see if it's a default and shouldn't be deleted
- std::set<std::string>::iterator sIt = sDefaultPresets.find(name);
- if(sIt != sDefaultPresets.end())
- {
- LLNotificationsUtil::add("WLNoEditDefault");
- return false;
- }
-
- LLWLParamManager::instance()->removeParamSet(name, true);
-
- // remove and choose another
- S32 new_index = combo_box->getCurrentIndex();
-
- combo_box->remove(name);
- if(key_combo != NULL)
- {
- key_combo->remove(name);
-
- // remove from slider, as well
- day_cycle->deletePreset(name);
- }
-
- // pick the previously selected index after delete
- if(new_index > 0)
- {
- new_index--;
- }
-
- if(combo_box->getItemCount() > 0)
- {
- combo_box->setCurrentByIndex(new_index);
- }
- }
- return false;
-}
-
-
-void LLFloaterWindLight::onChangePresetName(LLUICtrl* ctrl)
-{
- deactivateAnimator();
-
- std::string data = ctrl->getValue().asString();
- if(!data.empty())
- {
- LLWLParamManager::instance()->loadPreset( data);
- syncMenu();
- }
-}
-
-void LLFloaterWindLight::onOpenDayCycle()
-{
- LLFloaterReg::showInstance("env_day_cycle");
-}
-
-// Clouds
-void LLFloaterWindLight::onCloudScrollXMoved(LLUICtrl* ctrl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
- // *HACK all cloud scrolling is off by an additive of 10.
- LLWLParamManager::instance()->mCurParams.setCloudScrollX(sldrCtrl->getValueF32() + 10.0f);
-}
-
-void LLFloaterWindLight::onCloudScrollYMoved(LLUICtrl* ctrl)
-{
- deactivateAnimator();
-
- LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
-
- // *HACK all cloud scrolling is off by an additive of 10.
- LLWLParamManager::instance()->mCurParams.setCloudScrollY(sldrCtrl->getValueF32() + 10.0f);
-}
-
-void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl)
-{
- deactivateAnimator();
-
- LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl);
-
- bool lock = cbCtrl->get();
- LLWLParamManager::instance()->mCurParams.setEnableCloudScrollX(!lock);
-
- LLSliderCtrl* sldr = getChild<LLSliderCtrl>(
- "WLCloudScrollX");
-
- if(cbCtrl->get())
- {
- sldr->setEnabled(false);
- }
- else
- {
- sldr->setEnabled(true);
- }
-
-}
-
-void LLFloaterWindLight::onCloudScrollYToggled(LLUICtrl* ctrl)
-{
- deactivateAnimator();
-
- LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl);
- bool lock = cbCtrl->get();
- LLWLParamManager::instance()->mCurParams.setEnableCloudScrollY(!lock);
-
- LLSliderCtrl* sldr = getChild<LLSliderCtrl>(
- "WLCloudScrollY");
-
- if(cbCtrl->get())
- {
- sldr->setEnabled(false);
- }
- else
- {
- sldr->setEnabled(true);
- }
-}
-
-void LLFloaterWindLight::deactivateAnimator()
-{
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-}
diff --git a/indra/newview/llfloaterwindlight.h b/indra/newview/llfloaterwindlight.h
deleted file mode 100644
index b43edc2c11..0000000000
--- a/indra/newview/llfloaterwindlight.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * @file llfloaterwindlight.h
- * @brief LLFloaterWindLight class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-/*
- * Menu for adjusting the atmospheric settings of the world
- */
-
-#ifndef LL_LLFLOATERWINDLIGHT_H
-#define LL_LLFLOATERWINDLIGHT_H
-
-#include "llfloater.h"
-
-#include <vector>
-#include "llwlparamset.h"
-
-struct WLColorControl;
-struct WLFloatControl;
-
-
-/// Menuing system for all of windlight's functionality
-class LLFloaterWindLight : public LLFloater
-{
-public:
-
- LLFloaterWindLight(const LLSD& key);
- virtual ~LLFloaterWindLight();
- /*virtual*/ BOOL postBuild();
- /// initialize all
- void initCallbacks(void);
-
- bool newPromptCallback(const LLSD& notification, const LLSD& response);
-
- /// general purpose callbacks for dealing with color controllers
- void onColorControlRMoved(LLUICtrl* ctrl, WLColorControl* userData);
- void onColorControlGMoved(LLUICtrl* ctrl, WLColorControl* userData);
- void onColorControlBMoved(LLUICtrl* ctrl, WLColorControl* userData);
- void onColorControlIMoved(LLUICtrl* ctrl, WLColorControl* userData);
- void onFloatControlMoved(LLUICtrl* ctrl, WLFloatControl* userData);
-
- /// lighting callbacks for glow
- void onGlowRMoved(LLUICtrl* ctrl, WLColorControl* userData);
- //static void onGlowGMoved(LLUICtrl* ctrl, void* userData);
- void onGlowBMoved(LLUICtrl* ctrl, WLColorControl* userData);
-
- /// lighting callbacks for sun
- void onSunMoved(LLUICtrl* ctrl, WLColorControl* userData);
-
- /// for handling when the star slider is moved to adjust the alpha
- void onStarAlphaMoved(LLUICtrl* ctrl);
-
- /// when user hits the load preset button
- void onNewPreset();
-
- /// when user hits the save preset button
- void onSavePreset();
-
- /// prompts a user when overwriting a preset
- bool saveAlertCallback(const LLSD& notification, const LLSD& response);
-
- /// when user hits the save preset button
- void onDeletePreset();
-
- /// prompts a user when overwriting a preset
- bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
-
- /// what to do when you change the preset name
- void onChangePresetName(LLUICtrl* ctrl);
-
- /// when user hits the save preset button
- void onOpenDayCycle();
-
- /// handle cloud scrolling
- void onCloudScrollXMoved(LLUICtrl* ctrl);
- void onCloudScrollYMoved(LLUICtrl* ctrl);
- void onCloudScrollXToggled(LLUICtrl* ctrl);
- void onCloudScrollYToggled(LLUICtrl* ctrl);
-
- /// sync up sliders with parameters
- void syncMenu();
-
- /// turn off animated skies
- static void deactivateAnimator();
-
-private:
- static std::set<std::string> sDefaultPresets;
-};
-
-
-#endif
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index f8a4ce7ad0..eb3c7ee469 100644..100755
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -1070,7 +1070,7 @@ void LLFloaterWorldMap::onComboTextEntry()
// Reset the tracking whenever we start typing into any of the search fields,
// so that hitting <enter> does an auto-complete versus teleporting us to the
// previously selected landmark/friend.
- LLTracker::clearFocus();
+ LLTracker::stopTracking(NULL);
}
void LLFloaterWorldMap::onSearchTextEntry( )
@@ -1527,17 +1527,24 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
mCompletingRegionName = "";
}
- // if match found, highlight it and go
- if (!match.isUndefined())
+ if (num_results > 0)
{
- list->selectByValue(match);
+ // if match found, highlight it and go
+ if (!match.isUndefined())
+ {
+ list->selectByValue(match);
+ }
+ // else select first found item
+ else
+ {
+ list->selectFirstItem();
+ }
getChild<LLUICtrl>("search_results")->setFocus(TRUE);
onCommitSearchResult();
}
-
- // if we found nothing, say "none"
- if (num_results == 0)
+ else
{
+ // if we found nothing, say "none"
list->setCommentText(LLTrans::getString("worldmap_results_none_found"));
list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
}
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 3884b94b60..e90b6c1c3d 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -167,13 +167,23 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
///----------------------------------------------------------------------------
/// Class LLFolderView
///----------------------------------------------------------------------------
+LLFolderView::Params::Params()
+: task_id("task_id"),
+ title("title"),
+ use_label_suffix("use_label_suffix"),
+ allow_multiselect("allow_multiselect", true),
+ show_load_status("show_load_status", true),
+ use_ellipses("use_ellipses", false)
+{
+}
+
// Default constructor
LLFolderView::LLFolderView(const Params& p)
: LLFolderViewFolder(p),
mScrollContainer( NULL ),
mPopupMenuHandle(),
- mAllowMultiSelect(TRUE),
+ mAllowMultiSelect(p.allow_multiselect),
mShowFolderHierarchy(FALSE),
mSourceID(p.task_id),
mRenameItem( NULL ),
@@ -194,10 +204,14 @@ LLFolderView::LLFolderView(const Params& p)
mDragAndDropThisFrame(FALSE),
mCallbackRegistrar(NULL),
mParentPanel(p.parent_panel),
- mUseEllipses(false),
+ mUseEllipses(p.use_ellipses),
mDraggingOverItem(NULL),
mStatusTextBox(NULL)
{
+ mRoot = this;
+
+ mShowLoadStatus = p.show_load_status();
+
LLRect rect = p.rect;
LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
setRect( rect );
@@ -263,6 +277,7 @@ LLFolderView::LLFolderView(const Params& p)
menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
mPopupMenuHandle = menu->getHandle();
+ mListener->openItem();
}
// Destroys the object
@@ -308,15 +323,10 @@ void LLFolderView::setSortOrder(U32 order)
if (order != mSortOrder)
{
LLFastTimer t(FTM_SORT);
+
mSortOrder = order;
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->sortBy(order);
- }
-
+ sortBy(order);
arrangeAll();
}
}
@@ -342,7 +352,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
{
recursiveIncrementNumDescendantsSelected(folder->numSelected());
}
- folder->setShowLoadStatus(true);
+ folder->setShowLoadStatus(mShowLoadStatus);
folder->setOrigin(0, 0);
folder->reshape(getRect().getWidth(), 0);
folder->setVisible(FALSE);
@@ -424,11 +434,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
(folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
}
- // Need to call arrange regardless of visibility, since children's visibility
- // might need to be changed too (e.g. even though a folder is invisible, its
- // children also need to be set invisible for state-tracking purposes, e.g.
- // llfolderviewitem::filter).
- // if (folderp->getVisible())
+ if (folderp->getVisible())
{
S32 child_height = 0;
S32 child_width = 0;
@@ -764,7 +770,7 @@ void LLFolderView::sanitizeSelection()
}
// Don't allow invisible items (such as root folders) to be selected.
- if (item->getHidden())
+ if (item == getRoot())
{
items_to_remove.push_back(item);
}
@@ -787,7 +793,7 @@ void LLFolderView::sanitizeSelection()
parent_folder;
parent_folder = parent_folder->getParentFolder())
{
- if (parent_folder->potentiallyVisible() && !parent_folder->getHidden())
+ if (parent_folder->potentiallyVisible())
{
// give initial selection to first ancestor folder that potentially passes the filter
if (!new_selection)
@@ -806,13 +812,7 @@ void LLFolderView::sanitizeSelection()
}
else
{
- // nothing selected to start with, so pick "My Inventory" as best guess
- new_selection = getItemByID(gInventory.getRootFolderID());
- // ... except if it's hidden from the UI.
- if (new_selection && new_selection->getHidden())
- {
- new_selection = NULL;
- }
+ new_selection = NULL;
}
if (new_selection)
@@ -931,14 +931,15 @@ void LLFolderView::draw()
if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
{
mStatusText = LLTrans::getString("Searching");
- //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
else
{
- LLStringUtil::format_map_t args;
- args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig());
- mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);
- //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
+ if (getFilter())
+ {
+ LLStringUtil::format_map_t args;
+ args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig());
+ mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);
+ }
}
mStatusTextBox->setValue(mStatusText);
mStatusTextBox->setVisible( TRUE );
@@ -962,7 +963,9 @@ void LLFolderView::draw()
}
- LLFolderViewFolder::draw();
+ // skip over LLFolderViewFolder::draw since we don't want the folder icon, label,
+ // and arrow for the root folder
+ LLView::draw();
mDragAndDropThisFrame = FALSE;
}
@@ -1642,11 +1645,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
LLFolderViewItem* parent_folder = last_selected->getParentFolder();
if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder())
{
- // Don't change selectin to hidden folder. See EXT-5328.
- if (!parent_folder->getHidden())
- {
- setSelection(parent_folder, FALSE, TRUE);
- }
+ setSelection(parent_folder, FALSE, TRUE);
}
else
{
@@ -1911,7 +1910,14 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// by the folder which is the hierarchy root.
if (!handled && !hasVisibleChildren())
{
- handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ if (mFolders.empty())
+ {
+ handled = handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ }
+ else
+ {
+ handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ }
}
if (handled)
@@ -1927,8 +1933,11 @@ void LLFolderView::deleteAllChildren()
closeRenamer();
LLView::deleteViewByHandle(mPopupMenuHandle);
mPopupMenuHandle = LLHandle<LLView>();
- mRenamer = NULL;
+ mScrollContainer = NULL;
mRenameItem = NULL;
+ mRenamer = NULL;
+ mStatusTextBox = NULL;
+
clearSelection();
LLView::deleteAllChildren();
}
@@ -2031,7 +2040,7 @@ void LLFolderView::removeItemID(const LLUUID& id)
LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
{
- if (id.isNull())
+ if (id == getListener()->getUUID())
{
return this;
}
@@ -2048,7 +2057,7 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id)
{
- if (id.isNull())
+ if (id == getListener()->getUUID())
{
return this;
}
@@ -2173,7 +2182,7 @@ void LLFolderView::doIdle()
// filter to determine visiblity before arranging
filterFromRoot();
- // automatically show matching items, and select first one
+ // automatically show matching items, and select first one if we had a selection
// do this every frame until user puts keyboard focus into the inventory window
// signaling the end of the automatic update
// only do this when mNeedsFilter is set, meaning filtered items have
@@ -2183,7 +2192,7 @@ void LLFolderView::doIdle()
LLFastTimer t3(FTM_AUTO_SELECT);
// select new item only if a filtered item not currently selected
LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
- if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride)
+ if ((selected_itemp && !selected_itemp->getFiltered()) && !mAutoSelectOverride)
{
// select first filtered item
LLSelectFirstFilteredItem filter;
@@ -2496,11 +2505,6 @@ BOOL LLFolderView::isFilterModified()
return mFilter->isNotDefault();
}
-BOOL LLFolderView::getAllowMultiSelect()
-{
- return mAllowMultiSelect;
-}
-
void delete_selected_item(void* user_data)
{
if(user_data)
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 1464a058d8..0b92548fd0 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -59,22 +59,6 @@ class LLUICtrl;
class LLTextBox;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewFunctor
-//
-// Simple abstract base class for applying a functor to folders and
-// items in a folder view hierarchy. This is suboptimal for algorithms
-// that only work folders or only work on items, but I'll worry about
-// that later when it's determined to be too slow.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLFolderViewFunctor
-{
-public:
- virtual ~LLFolderViewFunctor() {}
- virtual void doFolder(LLFolderViewFolder* folder) = 0;
- virtual void doItem(LLFolderViewItem* item) = 0;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderView
//
// Th LLFolderView represents the root level folder view object. It
@@ -89,7 +73,12 @@ public:
Mandatory<LLPanel*> parent_panel;
Optional<LLUUID> task_id;
Optional<std::string> title;
- Optional<bool> use_label_suffix;
+ Optional<bool> use_label_suffix,
+ allow_multiselect,
+ show_load_status,
+ use_ellipses;
+
+ Params();
};
LLFolderView(const Params&);
virtual ~LLFolderView( void );
@@ -102,7 +91,6 @@ public:
// and resort the items if necessary.
void setSortOrder(U32 order);
void setFilterPermMask(PermissionMask filter_perm_mask);
- void setAllowMultiSelect(BOOL allow) { mAllowMultiSelect = allow; }
typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;
void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
@@ -117,7 +105,6 @@ public:
//LLInventoryFilter::EFolderShow getShowFolderState();
U32 getSortOrder() const;
BOOL isFilterModified();
- BOOL getAllowMultiSelect();
// Close all folders in the view
void closeAllFolders();
@@ -238,7 +225,6 @@ public:
void setShowSingleSelection(BOOL show);
BOOL getShowSingleSelection() { return mShowSingleSelection; }
F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
- void setUseEllipses(bool use_ellipses) { mUseEllipses = use_ellipses; }
bool getUseEllipses() { return mUseEllipses; }
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index e9d1ad3a9e..6e4f55fb2f 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -30,8 +30,10 @@
// viewer includes
#include "llfolderview.h" // Items depend extensively on LLFolderViews
#include "llfoldervieweventlistener.h"
+#include "llviewerfoldertype.h"
#include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator()
#include "llinventoryfilter.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llpanel.h"
#include "llviewercontrol.h" // gSavedSettings
@@ -130,10 +132,14 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mIconOpen(p.icon_open),
mIconOverlay(p.icon_overlay),
mListener(p.listener),
- mHidden(false),
mShowLoadStatus(false)
{
+}
+
+BOOL LLFolderViewItem::postBuild()
+{
refresh();
+ return TRUE;
}
// Destroys the object
@@ -195,7 +201,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
// Skip over items that are invisible or are hidden from the UI.
- while(itemp && (!itemp->getVisible() || itemp->getHidden()))
+ while(itemp && !itemp->getVisible())
{
LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
if (itemp == next_itemp)
@@ -351,7 +357,10 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,
BOOL take_keyboard_focus)
{
LLFolderView* root = getRoot();
+ if (getParentFolder())
+ {
getParentFolder()->requestArrange();
+ }
if(set_selection)
{
setSelectionFromRoot(this, TRUE, take_keyboard_focus);
@@ -442,23 +451,20 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
S32 LLFolderViewItem::getItemHeight()
{
- if (getHidden()) return 0;
-
return mItemHeight;
}
void LLFolderViewItem::filter( LLInventoryFilter& filter)
{
const BOOL previous_passed_filter = mPassedFilter;
- const BOOL passed_filter = mListener && filter.check(this);
+ const BOOL passed_filter = filter.check(this);
// If our visibility will change as a result of this filter, then
// we need to be rearranged in our parent folder
if (mParentFolder)
{
- if (getVisible() != passed_filter)
- mParentFolder->requestArrange();
- if (passed_filter != previous_passed_filter)
+ if (getVisible() != passed_filter
+ || previous_passed_filter != passed_filter )
mParentFolder->requestArrange();
}
@@ -863,11 +869,6 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
void LLFolderViewItem::draw()
{
- if (getHidden())
- {
- return;
- }
-
static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
@@ -891,8 +892,8 @@ void LLFolderViewItem::draw()
// Draw open folder arrow
//
const bool up_to_date = mListener && mListener->isUpToDate();
- const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) || // we fetched our children and some of them have passed the filter...
- (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter)
+ const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter...
+ || (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter)
if (possibly_has_children)
{
LLUIImage* arrow_image = default_params.folder_arrow_image;
@@ -1054,8 +1055,11 @@ void LLFolderViewItem::draw()
{
root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress();
}
- if ((mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) ||
- (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && root_is_loading && (mShowLoadStatus || mHidden)))
+ if ((mIsLoading
+ && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
+ || (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
+ && root_is_loading
+ && mShowLoadStatus))
{
std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";
font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor,
@@ -1119,7 +1123,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mLastCalculatedWidth(0),
mCompletedFilterGeneration(-1),
mMostFilteredDescendantGeneration(-1),
- mNeedsSort(false)
+ mNeedsSort(false),
+ mPassedFolderFilter(FALSE)
{
}
@@ -1131,6 +1136,17 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
}
+void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation)
+{
+ mPassedFolderFilter = filtered;
+ mLastFilterGeneration = filter_generation;
+}
+
+bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation)
+{
+ return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();
+}
+
// addToFolder() returns TRUE if it succeeds. FALSE otherwise
BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
{
@@ -1157,8 +1173,6 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
mHasVisibleChildren = hasFilteredDescendants(filter_generation);
- LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getFilter()->getShowFolderState();
-
// calculate height as a single item (without any children), and reshapes rectangle to match
LLFolderViewItem::arrange( width, height, filter_generation );
@@ -1190,8 +1204,10 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
}
else
{
- folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders?
- (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
+ folderp->setVisible( folderp->getListener()
+ && (folderp->getFiltered(filter_generation)
+ || (folderp->getFilteredFolder(filter_generation)
+ && folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter
}
if (folderp->getVisible())
@@ -1311,7 +1327,9 @@ void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recur
mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
mCompletedFilterGeneration = generation;
// only aggregate up if we are a lower (older) value
- if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration())
+ if (recurse_up
+ && mParentFolder
+ && generation < mParentFolder->getCompletedFilterGeneration())
{
mParentFolder->setCompletedFilterGeneration(generation, TRUE);
}
@@ -1336,21 +1354,19 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
// filter folder itself
if (getLastFilterGeneration() < filter_generation)
{
- if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter
- !mPassedFilter) // and did not pass the filter
+ if (getLastFilterGeneration() >= must_pass_generation // folder has been compared to a valid precursor filter
+ && !mPassedFilter) // and did not pass the filter
{
// go ahead and flag this folder as done
mLastFilterGeneration = filter_generation;
}
- else
+ else // filter self only on first pass through
{
- // filter self only on first pass through
+ // filter against folder rules
+ filterFolder(filter);
+ // and then item rules
LLFolderViewItem::filter( filter );
}
- if (mHidden)
- {
- setOpen();
- }
}
if (getRoot()->getDebugFilters())
@@ -1377,7 +1393,10 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
}
// when applying a filter, matching folders get their contents downloaded first
- if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
+ if (filter.isNotDefault()
+ && getFiltered(filter.getMinRequiredGeneration())
+ && (mListener
+ && !gInventory.isCategoryComplete(mListener->getUUID())))
{
LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID());
}
@@ -1403,6 +1422,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration()))
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
}
// just skip it, it has already been filtered
continue;
@@ -1415,6 +1435,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation))
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
if (getRoot()->needsAutoSelect() && autoopen_folders)
{
folder->setOpenArrangeRecursively(TRUE);
@@ -1436,6 +1457,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (item->getFiltered())
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
}
continue;
}
@@ -1454,6 +1476,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (item->getFiltered(filter.getMinRequiredGeneration()))
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
}
}
@@ -1467,6 +1490,31 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
}
}
+void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter)
+{
+ const BOOL previous_passed_filter = mPassedFolderFilter;
+ const BOOL passed_filter = filter.checkFolder(this);
+
+ // If our visibility will change as a result of this filter, then
+ // we need to be rearranged in our parent folder
+ if (mParentFolder)
+ {
+ if (getVisible() != passed_filter
+ || previous_passed_filter != passed_filter )
+ {
+ mParentFolder->requestArrange();
+ }
+ }
+
+ setFilteredFolder(passed_filter, filter.getCurrentGeneration());
+ filter.decrementFilterCount();
+
+ if (getRoot()->getDebugFilters())
+ {
+ mStatusText = llformat("%d", mLastFilterGeneration);
+ }
+}
+
void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation)
{
// if this folder is now filtered, but wasn't before
@@ -1488,6 +1536,23 @@ void LLFolderViewFolder::dirtyFilter()
LLFolderViewItem::dirtyFilter();
}
+BOOL LLFolderViewFolder::getFiltered()
+{
+ return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration())
+ && LLFolderViewItem::getFiltered();
+}
+
+BOOL LLFolderViewFolder::getFiltered(S32 filter_generation)
+{
+ return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation);
+}
+
+BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation)
+{
+ return mMostFilteredDescendantGeneration >= filter_generation;
+}
+
+
BOOL LLFolderViewFolder::hasFilteredDescendants()
{
return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration();
@@ -1743,7 +1808,7 @@ void LLFolderViewFolder::destroyView()
folderp->destroyView(); // removes entry from mFolders
}
- deleteAllChildren();
+ //deleteAllChildren();
if (mParentFolder)
{
@@ -1843,8 +1908,12 @@ void LLFolderViewFolder::sortBy(U32 order)
(*fit)->sortBy(order);
}
- mFolders.sort(mSortFunction);
- mItems.sort(mSortFunction);
+ // Don't sort the topmost folders (My Inventory and Library)
+ if (mListener->getUUID().notNull())
+ {
+ mFolders.sort(mSortFunction);
+ mItems.sort(mSortFunction);
+ }
if (order & LLInventoryFilter::SO_DATE)
{
@@ -1981,6 +2050,13 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
item->dirtyFilter();
requestArrange();
requestSort();
+ LLFolderViewFolder* parentp = getParentFolder();
+ while (parentp && parentp->mSortFunction.isByDate())
+ {
+ // parent folder doesn't have a time stamp yet, so get it from us
+ parentp->requestSort();
+ parentp = parentp->getParentFolder();
+ }
return TRUE;
}
@@ -2000,6 +2076,13 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
// rearrange all descendants too, as our indentation level might have changed
folder->requestArrange(TRUE);
requestSort();
+ LLFolderViewFolder* parentp = getParentFolder();
+ while (parentp && !parentp->mSortFunction.isByDate())
+ {
+ // parent folder doesn't have a time stamp yet, so get it from us
+ parentp->requestSort();
+ parentp = parentp->getParentFolder();
+ }
return TRUE;
}
@@ -2059,7 +2142,9 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r
(*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */
}
}
- if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN))
+ if (mParentFolder
+ && (recurse == RECURSE_UP
+ || recurse == RECURSE_UP_DOWN))
{
mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);
}
@@ -2301,13 +2386,16 @@ void LLFolderViewFolder::draw()
bool possibly_has_children = false;
bool up_to_date = mListener && mListener->isUpToDate();
- if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
+ if(!up_to_date
+ && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
{
possibly_has_children = true;
}
- BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date );
+ BOOL loading = (mIsOpen
+ && possibly_has_children
+ && !up_to_date );
if ( loading && !mIsLoading )
{
@@ -2330,6 +2418,41 @@ void LLFolderViewFolder::draw()
time_t LLFolderViewFolder::getCreationDate() const
{
+ // folders have no creation date try to create one from an item somewhere in our folder hierarchy
+ if (!mCreationDate)
+ {
+ for (items_t::const_iterator iit = mItems.begin();
+ iit != mItems.end(); ++iit)
+ {
+ LLFolderViewItem* itemp = (*iit);
+
+ const time_t item_creation_date = itemp->getCreationDate();
+
+ if (item_creation_date)
+ {
+ mCreationDate = item_creation_date;
+ break;
+ }
+ }
+
+ if (!mCreationDate)
+ {
+ for (folders_t::const_iterator fit = mFolders.begin();
+ fit != mFolders.end(); ++fit)
+ {
+ LLFolderViewFolder* folderp = (*fit);
+
+ const time_t folder_creation_date = folderp->getCreationDate();
+
+ if (folder_creation_date)
+ {
+ mCreationDate = folder_creation_date;
+ break;
+ }
+ }
+ }
+ }
+
return llmax<time_t>(mCreationDate, mSubtreeCreationDate);
}
@@ -2573,7 +2696,8 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde
{
// ignore sort order for landmarks in the Favorites folder.
// they should be always sorted as in Favorites bar. See EXT-719
- if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM
+ if (a->getSortGroup() == SG_ITEM
+ && b->getSortGroup() == SG_ITEM
&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK
&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
{
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index fc941510ab..e2f94a2b63 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -66,6 +66,7 @@ public:
// Returns true if order has changed
bool updateSort(U32 order);
U32 getSort() { return mSortOrder; }
+ bool isByDate() { return mByDate; }
bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b);
private:
@@ -94,7 +95,7 @@ public:
Optional<LLUIImage*> icon_open; // used for folders
Optional<LLUIImage*> icon_overlay; // for links
Optional<LLFolderView*> root;
- Optional<LLFolderViewEventListener*> listener;
+ Mandatory<LLFolderViewEventListener*> listener;
Optional<LLUIImage*> folder_arrow_image;
Optional<S32> folder_indentation; // pixels
@@ -135,7 +136,7 @@ protected:
std::string mSearchableLabel;
S32 mLabelWidth;
bool mLabelWidthDirty;
- time_t mCreationDate;
+ mutable time_t mCreationDate;
LLFolderViewFolder* mParentFolder;
LLFolderViewEventListener* mListener;
BOOL mIsCurSelection;
@@ -157,7 +158,6 @@ protected:
BOOL mDragAndDropTarget;
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
- bool mHidden;
bool mShowLoadStatus;
// helper function to change the selection from the root.
@@ -167,13 +167,15 @@ protected:
void extendSelectionFromRoot(LLFolderViewItem* selection);
// this is an internal method used for adding items to folders. A
- // no-op at this leve, but reimplemented in derived classes.
+ // no-op at this level, but reimplemented in derived classes.
virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
static LLFontGL* getLabelFontForStyle(U8 style);
public:
+ BOOL postBuild();
+
// This function clears the currently selected item, and records
// the specified selected item appropriately for display and use
// in the UI. If open is TRUE, then folders are opened up along
@@ -202,11 +204,6 @@ public:
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 getItemHeight();
- // Hide the folder from the UI, such as if you want to hide the root
- // folder in an inventory panel.
- void setHidden(bool hidden) { mHidden = hidden; }
- bool getHidden() const { return mHidden; }
-
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
@@ -366,6 +363,9 @@ public:
UNKNOWN, TRASH, NOT_TRASH
} ETrash;
+ typedef std::list<LLFolderViewItem*> items_t;
+ typedef std::list<LLFolderViewFolder*> folders_t;
+
private:
S32 mNumDescendantsSelected;
@@ -374,8 +374,6 @@ public: // Accessed needed by LLFolderViewItem
S32 numSelected(void) const { return mNumDescendantsSelected + (isSelected() ? 1 : 0); }
protected:
- typedef std::list<LLFolderViewItem*> items_t;
- typedef std::list<LLFolderViewFolder*> folders_t;
items_t mItems;
folders_t mFolders;
LLInventorySort mSortFunction;
@@ -392,6 +390,8 @@ protected:
S32 mCompletedFilterGeneration;
S32 mMostFilteredDescendantGeneration;
bool mNeedsSort;
+ bool mPassedFolderFilter;
+
public:
typedef enum e_recurse_type
{
@@ -425,13 +425,21 @@ public:
virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
- BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; }
+ BOOL hasFilteredDescendants(S32 filter_generation);
BOOL hasFilteredDescendants();
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
virtual void setFiltered(BOOL filtered, S32 filter_generation);
+ virtual BOOL getFiltered();
+ virtual BOOL getFiltered(S32 filter_generation);
+
virtual void dirtyFilter();
+
+ // folder-specific filtering (filter status propagates top down instead of bottom up)
+ void filterFolder(LLInventoryFilter& filter);
+ void setFilteredFolder(bool filtered, S32 filter_generation);
+ bool getFilteredFolder(S32 filter_generation);
// Passes selection information on to children and record
// selection information if necessary.
@@ -537,6 +545,10 @@ public:
time_t getCreationDate() const;
bool isTrash() const;
S32 getNumSelectedDescendants(void) const { return mNumDescendantsSelected; }
+
+ folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); }
+ folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); }
+ folders_t::size_type getFoldersCount() const { return mFolders.size(); }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/newview/llgesturelistener.cpp b/indra/newview/llgesturelistener.cpp
new file mode 100644
index 0000000000..2fff506681
--- /dev/null
+++ b/indra/newview/llgesturelistener.cpp
@@ -0,0 +1,159 @@
+/**
+ * @file llgesturelistener.cpp
+ * @author Dave Simmons
+ * @date 2011-03-28
+ * @brief Implementation for LLGestureListener.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgesturelistener.h"
+#include "llgesturemgr.h"
+#include "llmultigesture.h"
+
+
+LLGestureListener::LLGestureListener()
+ : LLEventAPI("LLGesture",
+ "LLGesture listener interface to control gestures")
+{
+ add("getActiveGestures",
+ "Return information about the agent's available gestures [\"reply\"]:\n"
+ "[\"gestures\"]: a dictionary with UUID strings as keys\n"
+ " and the following dict values for each entry:\n"
+ " [\"name\"]: name of the gesture, may be empty\n"
+ " [\"trigger\"]: trigger string used to invoke via user chat, may be empty\n"
+ " [\"playing\"]: true or false indicating the playing state",
+ &LLGestureListener::getActiveGestures,
+ LLSDMap("reply", LLSD()));
+ add("isGesturePlaying",
+ "[\"id\"]: UUID of the gesture to query. Returns True or False in [\"playing\"] value of the result",
+ &LLGestureListener::isGesturePlaying);
+ add("startGesture",
+ "[\"id\"]: UUID of the gesture to start playing",
+ &LLGestureListener::startGesture);
+ add("stopGesture",
+ "[\"id\"]: UUID of the gesture to stop",
+ &LLGestureListener::stopGesture);
+}
+
+
+// "getActiveGestures" command
+void LLGestureListener::getActiveGestures(const LLSD& event_data) const
+{
+ LLSD reply = LLSD::emptyMap();
+ LLSD gesture_map = LLSD::emptyMap();
+
+ const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures();
+
+ // Scan active gesture map and get all the names
+ LLGestureMgr::item_map_t::const_iterator it;
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
+ {
+ LLMultiGesture* gesture = (*it).second;
+ if (gesture)
+ { // Add an entry to the result map with the LLUUID as key with a map containing data
+ LLSD info = LLSD::emptyMap();
+ info["name"] = (LLSD::String) gesture->mName;
+ info["trigger"] = (LLSD::String) gesture->mTrigger;
+ info["playing"] = (LLSD::Boolean) gesture->mPlaying;
+
+ gesture_map[(*it).first.asString()] = info;
+ }
+ }
+
+ reply["gestures"] = gesture_map;
+ sendReply(reply, event_data);
+}
+
+
+
+// "isGesturePlaying" command
+void LLGestureListener::isGesturePlaying(const LLSD& event_data) const
+{
+ bool is_playing = false;
+ if (event_data.has("id"))
+ {
+ LLUUID gesture_id = event_data["id"].asUUID();
+ if (gesture_id.notNull())
+ {
+ is_playing = LLGestureMgr::instance().isGesturePlaying(gesture_id);
+ }
+ else
+ {
+ llwarns << "isGesturePlaying did not find a gesture object for " << gesture_id << llendl;
+ }
+ }
+ else
+ {
+ llwarns << "isGesturePlaying didn't have 'id' value passed in" << llendl;
+ }
+
+ LLSD reply = LLSD::emptyMap();
+ reply["playing"] = (LLSD::Boolean) is_playing;
+ sendReply(reply, event_data);
+}
+
+
+// "startGesture" command
+void LLGestureListener::startGesture(LLSD const & event_data) const
+{
+ startOrStopGesture(event_data, true);
+}
+
+
+// "stopGesture" command
+void LLGestureListener::stopGesture(LLSD const & event_data) const
+{
+ startOrStopGesture(event_data, false);
+}
+
+
+// Real code for "startGesture" or "stopGesture"
+void LLGestureListener::startOrStopGesture(LLSD const & event_data, bool start) const
+{
+ if (event_data.has("id"))
+ {
+ LLUUID gesture_id = event_data["id"].asUUID();
+ if (gesture_id.notNull())
+ {
+ if (start)
+ {
+ LLGestureMgr::instance().playGesture(gesture_id);
+ }
+ else
+ {
+ LLGestureMgr::instance().stopGesture(gesture_id);
+ }
+ }
+ else
+ {
+ llwarns << "startOrStopGesture did not find a gesture object for " << gesture_id << llendl;
+ }
+ }
+ else
+ {
+ llwarns << "startOrStopGesture didn't have 'id' value passed in" << llendl;
+ }
+}
+
diff --git a/indra/newview/llgesturelistener.h b/indra/newview/llgesturelistener.h
new file mode 100644
index 0000000000..6f59698ed1
--- /dev/null
+++ b/indra/newview/llgesturelistener.h
@@ -0,0 +1,52 @@
+/**
+ * @file llgesturelistener.h
+ * @author Dave Simmons
+ * @date 2011-03-15
+ * @brief Class definition for LLGestureListener.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLGESTURELISTENER_H
+#define LL_LLGESTURELISTENER_H
+
+#include "lleventapi.h"
+
+class LLSD;
+
+class LLGestureListener : public LLEventAPI
+{
+public:
+ LLGestureListener();
+
+private:
+ void getActiveGestures(LLSD const & gesture_data) const;
+ void isGesturePlaying(LLSD const & gesture_data) const;
+ void startGesture(LLSD const & gesture_data) const;
+ void stopGesture(LLSD const & gesture_data) const;
+
+ void startOrStopGesture(LLSD const & event_data, bool start) const;
+};
+
+#endif // LL_LLGESTURELISTENER_H
+
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 2f9856c650..66ca76bfb0 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -53,6 +53,7 @@
#include "llviewerstats.h"
#include "llnearbychatbar.h"
#include "llappearancemgr.h"
+#include "llgesturelistener.h"
// Longest time, in seconds, to wait for all animations to stop playing
const F32 MAX_WAIT_ANIM_SECS = 30.f;
@@ -70,6 +71,7 @@ LLGestureMgr::LLGestureMgr()
mLoadingCount(0)
{
gInventory.addObserver(this);
+ mListener.reset(new LLGestureListener());
}
diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h
index 5930841cbc..26a5924ec3 100644
--- a/indra/newview/llgesturemgr.h
+++ b/indra/newview/llgesturemgr.h
@@ -37,6 +37,7 @@
#include "llviewerinventory.h"
class LLMultiGesture;
+class LLGestureListener;
class LLGestureStep;
class LLUUID;
class LLVFS;
@@ -154,9 +155,9 @@ protected:
// Used by loadGesture
static void onLoadComplete(LLVFS *vfs,
- const LLUUID& asset_uuid,
- LLAssetType::EType type,
- void* user_data, S32 status, LLExtStat ext_status);
+ const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status);
// Used by playGesture to load an asset file
// required to play a gesture step
@@ -185,6 +186,9 @@ private:
BOOL mValid;
std::set<LLUUID> mLoadingAssets;
+
+ // LLEventHost interface
+ boost::shared_ptr<LLGestureListener> mListener;
};
#endif
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 86c8a1a9b5..75d4c4e80d 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -40,6 +40,7 @@
#include "llfloateropenobject.h"
#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
+#include "llfolderview.h"
#include "llfriendcard.h"
#include "llgesturemgr.h"
#include "llgiveinventory.h"
@@ -571,8 +572,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
}
- // Don't allow items to be pasted directly into the COF.
- if (!isCOFFolder())
+ // Don't allow items to be pasted directly into the COF or the inbox
+ if (!isCOFFolder() && !isInboxFolder())
{
items.push_back(std::string("Paste"));
}
@@ -781,6 +782,18 @@ BOOL LLInvFVBridge::isCOFFolder() const
return LLAppearanceMgr::instance().getIsInCOF(mUUID);
}
+BOOL LLInvFVBridge::isInboxFolder() const
+{
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false);
+
+ if (inbox_id.isNull())
+ {
+ return FALSE;
+ }
+
+ return gInventory.isObjectDescendentOf(mUUID, inbox_id);
+}
+
BOOL LLInvFVBridge::isItemPermissive() const
{
return FALSE;
@@ -1786,6 +1799,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else
{
+ if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+ {
+ set_dad_inbox_object(inv_cat->getUUID());
+ }
// Reparent the folder and restamp children if it's moving
// into trash.
@@ -2525,6 +2542,7 @@ void LLFolderBridge::folderOptionsMenu()
{
mItems.push_back(std::string("Add To Outfit"));
}
+
mItems.push_back(std::string("Replace Outfit"));
}
if (is_ensemble)
@@ -2614,15 +2632,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// Not sure what the right thing is to do here.
if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
{
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
-
+ if (!isInboxFolder()) // don't allow creation in inbox
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ }
#if SUPPORT_ENSEMBLES
// Changing folder types is an unfinished unsupported feature
// and can lead to unexpected behavior if enabled.
@@ -3161,6 +3181,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// (move the item, restamp if into trash)
else
{
+ // set up observer to select item once drag and drop from inbox is complete
+ if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+ {
+ set_dad_inbox_object(inv_item->getUUID());
+ }
+
LLInvFVBridge::changeItemParent(
model,
(LLViewerInventoryItem*)inv_item,
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 1e849c8812..15629c0c75 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -139,6 +139,7 @@ protected:
BOOL isAgentInventory() const; // false if lost or in the inventory library
BOOL isCOFFolder() const; // true if COF or descendent of
+ BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox
virtual BOOL isItemPermissive() const;
static void changeItemParent(LLInventoryModel* model,
LLViewerInventoryItem* item,
@@ -584,6 +585,9 @@ protected:
};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Recent Inventory Panel related classes
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Overridden version of the Inventory-Folder-View-Bridge for Folders
class LLRecentItemsFolderBridge : public LLFolderBridge
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index dee15a1efd..d6278a5fda 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -107,6 +107,32 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item)
return passed;
}
+bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
+{
+ // we're showing all folders, overriding filter
+ if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ {
+ return true;
+ }
+
+ const LLFolderViewEventListener* listener = folder->getListener();
+ const LLUUID folder_id = listener->getUUID();
+
+ if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
+ {
+ // Can only filter categories for items in your inventory
+ // (e.g. versus in-world object contents).
+ const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
+ if (!cat)
+ return false;
+ LLFolderType::EType cat_type = cat->getPreferredType();
+ if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))
+ return false;
+ }
+
+ return true;
+}
+
BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
{
const LLFolderViewEventListener* listener = item->getListener();
@@ -137,30 +163,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
}
}
-
- ////////////////////////////////////////////////////////////////////////////////
- // FILTERTYPE_CATEGORY
- // Pass if this item is a category of the filter type, or
- // if its parent is a category of the filter type.
- if (filterTypes & FILTERTYPE_CATEGORY)
- {
- // Can only filter categories for items in your inventory
- // (e.g. versus in-world object contents).
- if (!object) return FALSE;
-
- LLUUID cat_id = object_id;
- if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)
- {
- cat_id = object->getParentUUID();
- }
- const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
- if (!cat)
- return FALSE;
- if ((1LL << cat->getPreferredType() & mFilterOps.mFilterCategoryTypes) == U64(0))
- return FALSE;
- }
-
-
////////////////////////////////////////////////////////////////////////////////
// FILTERTYPE_UUID
// Pass if this item is the target UUID or if it links to the target UUID
@@ -172,7 +174,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
return FALSE;
}
-
////////////////////////////////////////////////////////////////////////////////
// FILTERTYPE_DATE
// Pass if this item is within the date range.
@@ -293,15 +294,15 @@ BOOL LLInventoryFilter::isModifiedAndClear()
return ret;
}
-void LLInventoryFilter::setFilterObjectTypes(U64 types)
+void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
{
- if (mFilterOps.mFilterObjectTypes != types)
+ if (current_types != types)
{
// keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterObjectTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterObjectTypes & types);
+ bool fewer_bits_set = (current_types & ~types) != 0;
+ bool more_bits_set = (~current_types & types) != 0;
- mFilterOps.mFilterObjectTypes = types;
+ current_types = types;
if (more_bits_set && fewer_bits_set)
{
// neither less or more restrive, both simultaneously
@@ -318,62 +319,23 @@ void LLInventoryFilter::setFilterObjectTypes(U64 types)
setModified(FILTER_MORE_RESTRICTIVE);
}
}
+}
+
+void LLInventoryFilter::setFilterObjectTypes(U64 types)
+{
+ updateFilterTypes(types, mFilterOps.mFilterObjectTypes);
mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
}
void LLInventoryFilter::setFilterCategoryTypes(U64 types)
{
- if (mFilterOps.mFilterCategoryTypes != types)
- {
- // keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterCategoryTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterCategoryTypes & types);
-
- mFilterOps.mFilterCategoryTypes = types;
- if (more_bits_set && fewer_bits_set)
- {
- // neither less or more restrive, both simultaneously
- // so we need to filter from scratch
- setModified(FILTER_RESTART);
- }
- else if (more_bits_set)
- {
- // target is only one of all requested types so more type bits == less restrictive
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (fewer_bits_set)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- }
- mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
+ updateFilterTypes(types, mFilterOps.mFilterCategoryTypes);
+ mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY;
}
void LLInventoryFilter::setFilterWearableTypes(U64 types)
{
- if (mFilterOps.mFilterWearableTypes != types)
- {
- // keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterWearableTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterWearableTypes & types);
-
- mFilterOps.mFilterWearableTypes = types;
- if (more_bits_set && fewer_bits_set)
- {
- // neither less or more restrive, both simultaneously
- // so we need to filter from scratch
- setModified(FILTER_RESTART);
- }
- else if (more_bits_set)
- {
- // target is only one of all requested types so more type bits == less restrictive
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (fewer_bits_set)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- }
+ updateFilterTypes(types, mFilterOps.mFilterWearableTypes);
mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;
}
@@ -898,11 +860,16 @@ void LLInventoryFilter::fromLLSD(LLSD& data)
}
}
-U32 LLInventoryFilter::getFilterObjectTypes() const
+U64 LLInventoryFilter::getFilterObjectTypes() const
{
return mFilterOps.mFilterObjectTypes;
}
+U64 LLInventoryFilter::getFilterCategoryTypes() const
+{
+ return mFilterOps.mFilterCategoryTypes;
+}
+
BOOL LLInventoryFilter::hasFilterString() const
{
return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 39e6f797a2..f9460822f7 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -31,6 +31,7 @@
#include "llpermissionsflags.h"
class LLFolderViewItem;
+class LLFolderViewFolder;
class LLInventoryFilter
{
@@ -81,11 +82,13 @@ public:
// + Parameters
// +-------------------------------------------------------------------+
void setFilterObjectTypes(U64 types);
- U32 getFilterObjectTypes() const;
+ U64 getFilterObjectTypes() const;
+ U64 getFilterCategoryTypes() const;
BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const;
void setFilterCategoryTypes(U64 types);
void setFilterUUID(const LLUUID &object_id);
void setFilterWearableTypes(U64 types);
+ void updateFilterTypes(U64 types, U64& current_types);
void setFilterSubString(const std::string& string);
const std::string& getFilterSubString(BOOL trim = FALSE) const;
@@ -110,6 +113,7 @@ public:
// + Execution And Results
// +-------------------------------------------------------------------+
BOOL check(const LLFolderViewItem* item);
+ bool checkFolder(const LLFolderViewFolder* folder);
BOOL checkAgainstFilterType(const LLFolderViewItem* item) const;
BOOL checkAgainstPermissions(const LLFolderViewItem* item) const;
BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const;
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index cfe1747fd4..2016b92666 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -28,9 +28,9 @@
#ifndef LL_LLINVENTORYFUNCTIONS_H
#define LL_LLINVENTORYFUNCTIONS_H
-#include "llinventorytype.h"
-#include "llfolderview.h"
-#include "llfolderviewitem.h"
+#include "llinventorymodel.h"
+#include "llinventory.h"
+#include "llwearabletype.h"
/********************************************************************************
** **
@@ -417,6 +417,24 @@ public:
/** Inventory Collector Functions
** **
*******************************************************************************/
+class LLFolderViewItem;
+class LLFolderViewFolder;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFolderViewFunctor
+//
+// Simple abstract base class for applying a functor to folders and
+// items in a folder view hierarchy. This is suboptimal for algorithms
+// that only work folders or only work on items, but I'll worry about
+// that later when it's determined to be too slow.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFolderViewFunctor
+{
+public:
+ virtual ~LLFolderViewFunctor() {}
+ virtual void doFolder(LLFolderViewFolder* folder) = 0;
+ virtual void doItem(LLFolderViewItem* item) = 0;
+};
class LLInventoryState
{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b5180854ef..21d5de9a5b 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -632,10 +632,12 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
}
// We're hiding mesh types
+#if 0
if (item->getType() == LLAssetType::AT_MESH)
{
return mask;
}
+#endif
LLViewerInventoryItem* old_item = getItem(item->getUUID());
LLPointer<LLViewerInventoryItem> new_item;
@@ -2587,7 +2589,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
LLInventoryState::sWearNewClothing = FALSE;
}
- if (tid == LLInventoryState::sWearNewClothingTransactionID)
+ if (tid.notNull() && tid == LLInventoryState::sWearNewClothingTransactionID)
{
count = wearable_ids.size();
for (i = 0; i < count; ++i)
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 7b1ff102e7..afaf660cb7 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -31,7 +31,9 @@
#include "llappviewer.h"
#include "llcallbacklist.h"
#include "llinventorypanel.h"
+#include "llinventorymodel.h"
#include "llviewercontrol.h"
+#include "llviewerinventory.h"
#include "llviewermessage.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 6bf19e346d..ceba4a0191 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -601,6 +601,34 @@ void LLInventoryAddedObserver::changed(U32 mask)
}
}
+void LLInventoryCategoryAddedObserver::changed(U32 mask)
+{
+ if (!(mask & LLInventoryObserver::ADD))
+ {
+ return;
+ }
+
+ const LLInventoryModel::changed_items_t& changed_ids = gInventory.getChangedIDs();
+
+ for (LLInventoryModel::changed_items_t::const_iterator cit = changed_ids.begin(); cit != changed_ids.end(); ++cit)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*cit);
+
+ if (cat)
+ {
+ mAddedCategories.push_back(cat);
+ }
+ }
+
+ if (!mAddedCategories.empty())
+ {
+ done();
+
+ mAddedCategories.clear();
+ }
+}
+
+
LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) :
mTransactionID(transaction_id)
{
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index 2d9021961e..aa1eae84d7 100644
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -219,6 +219,28 @@ protected:
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryCategoryAddedObserver
+//
+// Base class for doing something when a new category is created in the
+// inventory.
+// It does not watch for a certain UUID, rather it acts when anything is added
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryCategoryAddedObserver : public LLInventoryObserver
+{
+public:
+
+ typedef std::vector<LLViewerInventoryCategory*> cat_vec_t;
+
+ LLInventoryCategoryAddedObserver() : mAddedCategories() {}
+ /*virtual*/ void changed(U32 mask);
+
+protected:
+ virtual void done() = 0;
+
+ cat_vec_t mAddedCategories;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryTransactionObserver
//
// Base class for doing something when an inventory transaction completes.
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 1dcb91ad4d..702e8d5a1f 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -35,6 +35,7 @@
#include "llavataractions.h"
#include "llfloaterinventory.h"
#include "llfloaterreg.h"
+#include "llfolderview.h"
#include "llimfloater.h"
#include "llimview.h"
#include "llinventorybridge.h"
@@ -42,7 +43,6 @@
#include "llinventorymodelbackgroundfetch.h"
#include "llsidepanelinventory.h"
#include "llsidetray.h"
-#include "llscrollcontainer.h"
#include "llviewerattachmenu.h"
#include "llviewerfoldertype.h"
#include "llvoavatarself.h"
@@ -131,9 +131,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mInventory(p.inventory),
mAllowMultiSelect(p.allow_multi_select),
mShowItemLinkOverlays(p.show_item_link_overlays),
+ mShowLoadStatus(p.show_load_status),
mViewsInitialized(false),
- mStartFolderString(p.start_folder),
- mBuildDefaultHierarchy(true),
mInvFVBridgeBuilder(NULL)
{
mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
@@ -146,11 +145,88 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars));
+
+}
+
+void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
+{
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+
+ std::string start_folder_name(params.start_folder());
+
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(start_folder_name);
+
+ LLUUID root_id;
+
+ if ("LIBRARY" == params.start_folder())
+ {
+ root_id = gInventory.getLibraryRootFolderID();
+ }
+ // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+ else if (preferred_type == LLFolderType::FT_INBOX)
+ {
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+
+ gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+ {
+ LLInventoryCategory* cat = *cat_it;
+
+ if (cat->getName() == "Received Items")
+ {
+ root_id = cat->getUUID();
+ }
+ }
+ }
+ }
+ // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+ else if (preferred_type == LLFolderType::FT_OUTBOX)
+ {
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+
+ gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+ {
+ LLInventoryCategory* cat = *cat_it;
+
+ if (cat->getName() == "Merchant Outbox")
+ {
+ root_id = cat->getUUID();
+ }
+ }
+ }
+ }
+ // leslie -- end temporary HACK
+ else
+ {
+ root_id = (preferred_type != LLFolderType::FT_NONE)
+ ? gInventory.findCategoryUUIDForType(preferred_type, false, false)
+ : LLUUID::null;
+ }
- if (mStartFolderString != "")
+ if ((root_id == LLUUID::null) && !start_folder_name.empty())
{
- mBuildDefaultHierarchy = false;
+ llwarns << "No category found that matches start_folder: " << start_folder_name << llendl;
+ root_id = LLUUID::generateNewID();
}
+
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+ LLAssetType::AT_CATEGORY,
+ LLInventoryType::IT_CATEGORY,
+ this,
+ NULL,
+ root_id);
+
+ mFolderRoot = createFolderView(new_listener, params.use_label_suffix());
}
void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
@@ -159,22 +235,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
- // Create root folder
- {
- LLRect folder_rect(0,
- 0,
- getRect().getWidth(),
- 0);
- LLFolderView::Params p;
- p.name = getName();
- p.title = getLabel();
- p.rect = folder_rect;
- p.parent_panel = this;
- p.tool_tip = p.name;
- p.use_label_suffix = params.use_label_suffix;
- mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p);
- mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
- }
+ buildFolderView(params);
mCommitCallbackRegistrar.popScope();
@@ -184,13 +245,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
{
LLRect scroller_view_rect = getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
- LLScrollContainer::Params p;
- p.name("Inventory Scroller");
- p.rect(scroller_view_rect);
- p.follows.flags(FOLLOWS_ALL);
- p.reserve_scroll_corner(true);
- p.tab_stop(true);
- mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ LLScrollContainer::Params scroller_params(params.scroll());
+ scroller_params.rect(scroller_view_rect);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroller_params);
addChild(mScroller);
mScroller->addChild(mFolderRoot);
mFolderRoot->setScrollContainer(mScroller);
@@ -206,7 +263,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
// Build view of inventory if we need default full hierarchy and inventory ready,
// otherwise wait for idle callback.
- if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mViewsInitialized)
+ if (mInventory->isInventoryUsable() && !mViewsInitialized)
{
initializeViews();
}
@@ -222,6 +279,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
}
mFolderRoot->setSortOrder(getFilter()->getSortOrder());
+ // hide inbox
+ getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX));
+
// Initialize base class params.
LLPanel::initFromParams(params);
}
@@ -264,6 +324,15 @@ LLInventoryFilter* LLInventoryPanel::getFilter()
return NULL;
}
+const LLInventoryFilter* LLInventoryPanel::getFilter() const
+{
+ if (mFolderRoot)
+ {
+ return mFolderRoot->getFilter();
+ }
+ return NULL;
+}
+
void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)
{
if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT)
@@ -272,6 +341,17 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType
getFilter()->setFilterCategoryTypes(types);
}
+U32 LLInventoryPanel::getFilterObjectTypes() const
+{
+ return mFolderRoot->getFilterObjectTypes();
+}
+
+U32 LLInventoryPanel::getFilterPermMask() const
+{
+ return mFolderRoot->getFilterPermissions();
+}
+
+
void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
{
getFilter()->setFilterPermissions(filter_perm_mask);
@@ -287,6 +367,12 @@ void LLInventoryPanel::setFilterSubString(const std::string& string)
getFilter()->setFilterSubString(string);
}
+const std::string LLInventoryPanel::getFilterSubString()
+{
+ return mFolderRoot->getFilterSubString();
+}
+
+
void LLInventoryPanel::setSortOrder(U32 order)
{
getFilter()->setSortOrder(order);
@@ -298,6 +384,12 @@ void LLInventoryPanel::setSortOrder(U32 order)
}
}
+U32 LLInventoryPanel::getSortOrder() const
+{
+ return mFolderRoot->getSortOrder();
+}
+
+
void LLInventoryPanel::setSinceLogoff(BOOL sl)
{
getFilter()->setDateRangeLastLogoff(sl);
@@ -379,7 +471,8 @@ void LLInventoryPanel::modelChanged(U32 mask)
{
view_item->destroyView();
}
- buildNewViews(item_id);
+ view_item = buildNewViews(item_id);
+ view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
}
//////////////////////////////
@@ -432,11 +525,10 @@ void LLInventoryPanel::modelChanged(U32 mask)
//////////////////////////////
// STRUCTURE Operation
// This item already exists in both memory and UI. It was probably reparented.
- if (model_item && view_item)
+ else if (model_item && view_item)
{
- // Don't process the item if it's hanging from the root, since its
- // model_item's parent will be NULL.
- if (view_item->getRoot() != view_item->getParent())
+ // Don't process the item if it is the root
+ if (view_item->getRoot() != view_item)
{
LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID());
// Item has been moved.
@@ -461,7 +553,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
//////////////////////////////
// REMOVE Operation
// This item has been removed from memory, but its associated UI element still exists.
- if (!model_item && view_item)
+ else if (!model_item && view_item)
{
// Remove the item's UI.
view_item->destroyView();
@@ -470,6 +562,12 @@ void LLInventoryPanel::modelChanged(U32 mask)
}
}
+LLFolderView* LLInventoryPanel::getRootFolder()
+{
+ return mFolderRoot;
+}
+
+
// static
void LLInventoryPanel::onIdle(void *userdata)
{
@@ -488,23 +586,16 @@ void LLInventoryPanel::onIdle(void *userdata)
}
}
+const LLUUID& LLInventoryPanel::getRootFolderID() const
+{
+ return mFolderRoot->getListener()->getUUID();
+}
+
void LLInventoryPanel::initializeViews()
{
if (!gInventory.isInventoryUsable()) return;
- // Determine the root folder in case specified, and
- // build the views starting with that folder.
- const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
-
- if ("LIBRARY" == mStartFolderString)
- {
- mStartFolderID = gInventory.getLibraryRootFolderID();
- }
- else
- {
- mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
- }
- rebuildViewsFor(mStartFolderID);
+ rebuildViewsFor(getRootFolderID());
mViewsInitialized = true;
@@ -529,132 +620,155 @@ void LLInventoryPanel::initializeViews()
}
}
-void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
{
// Destroy the old view for this ID so we can rebuild it.
LLFolderViewItem* old_view = mFolderRoot->getItemByID(id);
- if (old_view && id.notNull())
+ if (old_view)
{
old_view->destroyView();
}
- buildNewViews(id);
+ return buildNewViews(id);
}
-void LLInventoryPanel::buildNewViews(const LLUUID& id)
+LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix)
{
- LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
- LLFolderViewItem* itemp = NULL;
- LLInventoryObject* objectp = gInventory.getObject(id);
- if (objectp)
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+
+ LLFolderView::Params p;
+
+ p.name = getName();
+ p.title = getLabel();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ p.tool_tip = p.name;
+ p.listener = bridge;
+ p.use_label_suffix = useLabelSuffix;
+ p.allow_multiselect = mAllowMultiSelect;
+ p.show_load_status = mShowLoadStatus;
+
+ return LLUICtrlFactory::create<LLFolderView>(p);
+}
+
+LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
+{
+ LLFolderViewFolder::Params params;
+
+ params.name = bridge->getDisplayName();
+ params.icon = bridge->getIcon();
+ params.icon_open = bridge->getOpenIcon();
+
+ if (mShowItemLinkOverlays) // if false, then links show up just like normal items
{
- const LLUUID &parent_id = objectp->getParentUUID();
- LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id);
- if (id == mStartFolderID)
- {
- parent_folder = mFolderRoot;
- }
- else if ((mStartFolderID != LLUUID::null) && (!gInventory.isObjectDescendentOf(id, mStartFolderID)))
- {
- // This item exists outside the inventory's hierarchy, so don't add it.
- return;
- }
-
- if (objectp->getType() <= LLAssetType::AT_NONE ||
- objectp->getType() >= LLAssetType::AT_COUNT)
- {
- llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
- << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
- << llendl;
- return;
- }
-
- if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
- (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
- {
- LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
- objectp->getType(),
- LLInventoryType::IT_CATEGORY,
- this,
- mFolderRoot,
- objectp->getUUID());
- if (new_listener)
- {
- LLFolderViewFolder::Params params;
- params.name = new_listener->getDisplayName();
- params.icon = new_listener->getIcon();
- params.icon_open = new_listener->getOpenIcon();
- if (mShowItemLinkOverlays) // if false, then links show up just like normal items
- {
- params.icon_overlay = LLUI::getUIImage("Inv_Link");
- }
- params.root = mFolderRoot;
- params.listener = new_listener;
- params.tool_tip = params.name;
- LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(params);
- folderp->setItemSortOrder(mFolderRoot->getSortOrder());
- itemp = folderp;
-
- // Hide the root folder, so we can show the contents of a folder flat
- // but still have the parent folder present for listener-related operations.
- if (id == mStartFolderID)
- {
- folderp->setHidden(TRUE);
- }
- const LLViewerInventoryCategory *cat = dynamic_cast<LLViewerInventoryCategory *>(objectp);
- if (cat && getIsHiddenFolderType(cat->getPreferredType()))
- {
- folderp->setHidden(TRUE);
- }
- }
- }
- else
- {
- // Build new view for item.
- LLInventoryItem* item = (LLInventoryItem*)objectp;
- LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
- item->getActualType(),
- item->getInventoryType(),
- this,
- mFolderRoot,
- item->getUUID(),
- item->getFlags());
-
- if (new_listener)
- {
- LLFolderViewItem::Params params;
- params.name = new_listener->getDisplayName();
- params.icon = new_listener->getIcon();
- params.icon_open = new_listener->getOpenIcon();
- if (mShowItemLinkOverlays) // if false, then links show up just like normal items
- {
- params.icon_overlay = LLUI::getUIImage("Inv_Link");
- }
- params.creation_date = new_listener->getCreationDate();
- params.root = mFolderRoot;
- params.listener = new_listener;
- params.rect = LLRect (0, 0, 0, 0);
- params.tool_tip = params.name;
- itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
- }
- }
+ params.icon_overlay = LLUI::getUIImage("Inv_Link");
+ }
+
+ params.root = mFolderRoot;
+ params.listener = bridge;
+ params.tool_tip = params.name;
- if (itemp)
- {
- itemp->addToFolder(parent_folder, mFolderRoot);
+ return LLUICtrlFactory::create<LLFolderViewFolder>(params);
+}
- // Don't add children of hidden folders unless this is the panel's root folder.
- if (itemp->getHidden() && (id != mStartFolderID))
- {
- return;
- }
+LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge)
+{
+ LLFolderViewItem::Params params;
+
+ params.name = bridge->getDisplayName();
+ params.icon = bridge->getIcon();
+ params.icon_open = bridge->getOpenIcon();
+
+ if (mShowItemLinkOverlays) // if false, then links show up just like normal items
+ {
+ params.icon_overlay = LLUI::getUIImage("Inv_Link");
+ }
+
+ params.creation_date = bridge->getCreationDate();
+ params.root = mFolderRoot;
+ params.listener = bridge;
+ params.rect = LLRect (0, 0, 0, 0);
+ params.tool_tip = params.name;
+
+ return LLUICtrlFactory::create<LLFolderViewItem>(params);
+}
+
+LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
+{
+ LLInventoryObject const* objectp = gInventory.getObject(id);
+ LLUUID root_id = mFolderRoot->getListener()->getUUID();
+ LLFolderViewFolder* parent_folder = NULL;
+ LLFolderViewItem* itemp = NULL;
+
+ if (id == root_id)
+ {
+ parent_folder = mFolderRoot;
+ }
+ else if (objectp)
+ {
+ const LLUUID &parent_id = objectp->getParentUUID();
+ parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id);
+
+ if (parent_folder)
+ {
+ if (objectp->getType() <= LLAssetType::AT_NONE ||
+ objectp->getType() >= LLAssetType::AT_COUNT)
+ {
+ llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
+ << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
+ << llendl;
+ return NULL;
+ }
+
+ if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
+ (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
+ {
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ mFolderRoot,
+ objectp->getUUID());
+ if (new_listener)
+ {
+ LLFolderViewFolder* folderp = createFolderViewFolder(new_listener);
+ folderp->setItemSortOrder(mFolderRoot->getSortOrder());
+ itemp = folderp;
+ }
+ }
+ else
+ {
+ // Build new view for item.
+ LLInventoryItem* item = (LLInventoryItem*)objectp;
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ mFolderRoot,
+ item->getUUID(),
+ item->getFlags());
+
+ if (new_listener)
+ {
+ itemp = createFolderViewItem(new_listener);
+ }
+ }
+
+ if (itemp)
+ {
+ itemp->addToFolder(parent_folder, mFolderRoot);
+ }
}
}
// If this is a folder, add the children of the folder and recursively add any
// child folders.
- if ((id == mStartFolderID) ||
- (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
+ if (id.isNull()
+ || (objectp
+ && objectp->getType() == LLAssetType::AT_CATEGORY))
{
LLViewerInventoryCategory::cat_array_t* categories;
LLViewerInventoryItem::item_array_t* items;
@@ -671,7 +785,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
}
- if(items)
+ if(items && parent_folder)
{
for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();
item_iter != items->end();
@@ -683,28 +797,25 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
mInventory->unlockDirectDescendentArrays(id);
}
+
+ return itemp;
}
// bit of a hack to make sure the inventory is open.
void LLInventoryPanel::openStartFolderOrMyInventory()
{
- if (mStartFolderString != "")
+ // Find My Inventory folder and open it up by name
+ for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
{
- mFolderRoot->openFolder(mStartFolderString);
- }
- else
- {
- // Find My Inventory folder and open it up by name
- for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
+ LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
+ if (fchild
+ && fchild->getListener()
+ && fchild->getListener()->getUUID() == gInventory.getRootFolderID())
{
- LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
- if (fchild && fchild->getListener() &&
- (fchild->getListener()->getUUID() == gInventory.getRootFolderID()))
- {
- const std::string& child_name = child->getName();
- mFolderRoot->openFolder(child_name);
- break;
- }
+ const std::string& child_name = child->getName();
+ mFolderRoot->openFolder(child_name);
+ mFolderRoot->clearSelection(); // No need to keep it selected though!
+ break;
}
}
}
@@ -723,6 +834,12 @@ void LLInventoryPanel::openSelected()
bridge->openItem();
}
+void LLInventoryPanel::unSelectAll()
+{
+ mFolderRoot->setSelection(NULL, FALSE, FALSE);
+}
+
+
BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = LLView::handleHover(x, y, mask);
@@ -802,7 +919,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc
mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus);
}
-void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
+void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)
{
if (mFolderRoot)
{
@@ -1067,15 +1184,12 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type)
{
- if (!getIsHiddenFolderType(folder_type))
- {
- mHiddenFolderTypes.push_back(folder_type);
- }
+ getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type));
}
BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const
{
- return (std::find(mHiddenFolderTypes.begin(), mHiddenFolderTypes.end(), folder_type) != mHiddenFolderTypes.end());
+ return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type));
}
@@ -1092,6 +1206,13 @@ public:
struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
{};
+ void initFromParams(const Params& p)
+ {
+ LLInventoryPanel::initFromParams(p);
+ // turn on inbox for recent items
+ getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX));
+ }
+
protected:
LLInventoryRecentItemsPanel (const Params&);
friend class LLUICtrlFactory;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 9da9f7d8ba..a4287a438e 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -33,11 +33,13 @@
#include "llfloater.h"
#include "llinventory.h"
#include "llinventoryfilter.h"
-#include "llfolderview.h"
#include "llinventorymodel.h"
+#include "llscrollcontainer.h"
#include "lluictrlfactory.h"
#include <set>
+class LLFolderView;
+class LLFolderViewFolder;
class LLFolderViewItem;
class LLInventoryFilter;
class LLInventoryModel;
@@ -46,7 +48,6 @@ class LLInventoryFVBridgeBuilder;
class LLMenuBarGL;
class LLCheckBoxCtrl;
class LLSpinCtrl;
-class LLScrollContainer;
class LLTextBox;
class LLIconCtrl;
class LLSaveFolderState;
@@ -83,6 +84,8 @@ public:
Optional<Filter> filter;
Optional<std::string> start_folder;
Optional<bool> use_label_suffix;
+ Optional<bool> show_load_status;
+ Optional<LLScrollContainer::Params> scroll;
Params()
: sort_order_setting("sort_order_setting"),
@@ -91,7 +94,9 @@ public:
show_item_link_overlays("show_item_link_overlays", false),
filter("filter"),
start_folder("start_folder"),
- use_label_suffix("use_label_suffix", true)
+ use_label_suffix("use_label_suffix", true),
+ show_load_status("show_load_status"),
+ scroll("scroll")
{}
};
@@ -123,16 +128,17 @@ public:
// Call this method to set the selection.
void openAllFolders();
void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
- void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+ void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
void clearSelection();
LLInventoryFilter* getFilter();
+ const LLInventoryFilter* getFilter() const;
void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);
- U32 getFilterObjectTypes() const { return mFolderRoot->getFilterObjectTypes(); }
+ U32 getFilterObjectTypes() const;
void setFilterPermMask(PermissionMask filter_perm_mask);
- U32 getFilterPermMask() const { return mFolderRoot->getFilterPermissions(); }
+ U32 getFilterPermMask() const;
void setFilterWearableTypes(U64 filter);
void setFilterSubString(const std::string& string);
- const std::string getFilterSubString() { return mFolderRoot->getFilterSubString(); }
+ const std::string getFilterSubString();
void setSinceLogoff(BOOL sl);
void setHoursAgo(U32 hours);
BOOL getSinceLogoff();
@@ -140,10 +146,9 @@ public:
void setShowFolderState(LLInventoryFilter::EFolderShow show);
LLInventoryFilter::EFolderShow getShowFolderState();
- void setAllowMultiSelect(BOOL allow) { mFolderRoot->setAllowMultiSelect(allow); }
// This method is called when something has changed about the inventory.
void modelChanged(U32 mask);
- LLFolderView* getRootFolder() { return mFolderRoot; }
+ LLFolderView* getRootFolder();
LLScrollContainer* getScrollableContainer() { return mScroller; }
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
@@ -158,7 +163,7 @@ public:
static void dumpSelectionInformation(void* user_data);
void openSelected();
- void unSelectAll() { mFolderRoot->setSelection(NULL, FALSE, FALSE); }
+ void unSelectAll();
static void onIdle(void* user_data);
@@ -175,6 +180,7 @@ protected:
LLInvPanelComplObserver* mCompletionObserver;
BOOL mAllowMultiSelect;
BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons
+ BOOL mShowLoadStatus;
LLFolderView* mFolderRoot;
LLScrollContainer* mScroller;
@@ -198,7 +204,7 @@ public:
static const std::string INHERIT_SORT_ORDER;
void setSortOrder(U32 order);
- U32 getSortOrder() const { return mFolderRoot->getSortOrder(); }
+ U32 getSortOrder() const;
private:
std::string mSortOrderSetting;
@@ -207,29 +213,27 @@ private:
//--------------------------------------------------------------------
public:
void addHideFolderType(LLFolderType::EType folder_type);
-protected:
- BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const;
-private:
- std::vector<LLFolderType::EType> mHiddenFolderTypes;
- //--------------------------------------------------------------------
- // Initialization routines for building up the UI ("views")
- //--------------------------------------------------------------------
public:
BOOL getIsViewsInitialized() const { return mViewsInitialized; }
- const LLUUID& getStartFolderID() const { return mStartFolderID; }
- const std::string& getStartFolderString() { return mStartFolderString; }
+ const LLUUID& getRootFolderID() const;
protected:
// Builds the UI. Call this once the inventory is usable.
void initializeViews();
- void rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
- virtual void buildNewViews(const LLUUID& id);
+ LLFolderViewItem* rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
+
+ virtual void buildFolderView(const LLInventoryPanel::Params& params);
+ LLFolderViewItem* buildNewViews(const LLUUID& id);
+ BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const;
+
+ virtual LLFolderView* createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix);
+ virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge);
+ virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge);
private:
BOOL mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild()
BOOL mViewsInitialized; // Views have been generated
// UUID of category from which hierarchy should be built. Set with the
// "start_folder" xml property. Default is LLUUID::null that means total Inventory hierarchy.
- std::string mStartFolderString;
LLUUID mStartFolderID;
};
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 5c65dcec34..1c8f6b6c98 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -190,6 +190,7 @@ LLLocationInputCtrl::Params::Params()
scripts_icon("scripts_icon"),
damage_icon("damage_icon"),
damage_text("damage_text"),
+ see_avatars_icon("see_avatars_icon"),
maturity_help_topic("maturity_help_topic")
{
}
@@ -342,6 +343,13 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
mDamageText = LLUICtrlFactory::create<LLTextBox>(damage_text);
addChild(mDamageText);
+ LLIconCtrl::Params see_avatars_icon = p.see_avatars_icon;
+ see_avatars_icon.tool_tip = LLTrans::getString("LocationCtrlSeeAVsTooltip");
+ see_avatars_icon.mouse_opaque = true;
+ mParcelIcon[SEE_AVATARS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(see_avatars_icon);
+ mParcelIcon[SEE_AVATARS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SEE_AVATARS_ICON));
+ addChild(mParcelIcon[SEE_AVATARS_ICON]);
+
// Register callbacks and load the location field context menu (NB: the order matters).
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Navbar.Action", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemClicked, this, _2));
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Navbar.EnableMenuItem", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemEnabled, this, _2));
@@ -810,6 +818,7 @@ void LLLocationInputCtrl::refreshParcelIcons()
bool allow_build = vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610.
bool allow_scripts = vpm->allowAgentScripts(agent_region, current_parcel);
bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel);
+ bool see_avs = current_parcel->getSeeAVs();
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
@@ -819,6 +828,7 @@ void LLLocationInputCtrl::refreshParcelIcons()
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mDamageText->setVisible(allow_damage);
+ mParcelIcon[SEE_AVATARS_ICON]->setVisible( !see_avs );
// Padding goes to left of both landmark star and for sale btn
x -= mAddLandmarkHPad;
@@ -1175,6 +1185,9 @@ void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
case DAMAGE_ICON:
LLNotificationsUtil::add("NotSafe");
break;
+ case SEE_AVATARS_ICON:
+ LLNotificationsUtil::add("SeeAvatars");
+ break;
case ICON_COUNT:
break;
// no default to get compiler warning when a new icon gets added
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index 6368bf5cf2..ed47ba73e3 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -77,7 +77,8 @@ public:
push_icon,
build_icon,
scripts_icon,
- damage_icon;
+ damage_icon,
+ see_avatars_icon;
Optional<LLTextBox::Params> damage_text;
Params();
};
@@ -109,12 +110,13 @@ private:
enum EParcelIcon
{
VOICE_ICON = 0,
- FLY_ICON,
- PUSH_ICON,
- BUILD_ICON,
- SCRIPTS_ICON,
- DAMAGE_ICON,
- ICON_COUNT
+ FLY_ICON, // 1
+ PUSH_ICON, // 2
+ BUILD_ICON, // 3
+ SCRIPTS_ICON, // 4
+ DAMAGE_ICON, // 5
+ SEE_AVATARS_ICON, // 6
+ ICON_COUNT // 7 total
};
friend class LLUICtrlFactory;
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index efc4e23838..ebb5912ace 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -230,7 +230,7 @@ std::string LLLogChat::makeLogFileName(std::string filename)
std::string LLLogChat::cleanFileName(std::string filename)
{
- std::string invalidChars = "\"\'\\/?*:.<>|";
+ std::string invalidChars = "\"\'\\/?*:.<>|[]{}~"; // Cannot match glob or illegal filename chars
std::string::size_type position = filename.find_first_of(invalidChars);
while (position != filename.npos)
{
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 738d82e732..4eb94dfb8e 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -58,6 +58,7 @@
#include "llworld.h"
#include "v2math.h"
#include "llvoavatar.h"
+#include "llmeshrepository.h"
const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
@@ -90,9 +91,7 @@ F32 get_default_max_prim_scale(bool is_flora)
{
// a bit of a hack, but if it's foilage, we don't want to use the
// new larger scale which would result in giant trees and grass
- if (gSavedSettings.getBOOL("MeshEnabled") &&
- gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty() &&
+ if (gMeshRepo.meshRezEnabled() &&
!is_flora)
{
return DEFAULT_MAX_PRIM_SCALE;
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index b3ad9efeb2..03ccabc994 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -38,6 +38,7 @@
#include "llviewermedia.h"
#include "llviewertexture.h"
#include "llviewerwindow.h"
+#include "lldebugmessagebox.h"
#include "llweb.h"
#include "llrender.h"
#include "llpluginclassmedia.h"
@@ -708,6 +709,8 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
//
void LLMediaCtrl::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
if ( gRestoreGL == 1 )
{
LLRect r = getRect();
@@ -746,21 +749,11 @@ void LLMediaCtrl::draw()
}
}
-// if(mHidingInitialLoad)
-// {
-// // If we're hiding loading, don't draw at all.
-// draw_media = false;
-// }
-
bool background_visible = isBackgroundVisible();
bool background_opaque = isBackgroundOpaque();
if(draw_media)
{
- // alpha off for this
- LLGLSUIDefault gls_ui;
- LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
-
gGL.pushUIMatrix();
{
if (mIgnoreUIScale)
@@ -775,7 +768,8 @@ void LLMediaCtrl::draw()
// scale texture to fit the space using texture coords
gGL.getTexUnit(0)->bind(media_texture);
- gGL.color4fv( LLColor4::white.mV );
+ LLColor4 media_color = LLColor4::white % alpha;
+ gGL.color4fv( media_color.mV );
F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
@@ -827,7 +821,6 @@ void LLMediaCtrl::draw()
}
// draw the browser
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
gGL.begin( LLRender::QUADS );
if (! media_plugin->getTextureCoordsOpenGL())
{
@@ -860,7 +853,6 @@ void LLMediaCtrl::draw()
gGL.vertex2i( x_offset + width, y_offset );
}
gGL.end();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
gGL.popUIMatrix();
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 0a1eadf4d0..6e0722bcf9 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -61,6 +61,9 @@
#include "pipeline.h"
#include "llinventorymodel.h"
#include "llfoldertype.h"
+#include "llviewerparcelmgr.h"
+
+#include "boost/lexical_cast.hpp"
#ifndef LL_WINDOWS
#include "netdb.h"
@@ -85,6 +88,15 @@ U32 LLMeshRepository::sPeakKbps = 0;
const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5;
+static S32 dump_num = 0;
+std::string make_dump_name(std::string prefix, S32 num)
+{
+ return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
+
+}
+void dump_llsd_to_file(const LLSD& content, std::string filename);
+LLSD llsd_from_file(std::string filename);
+
std::string header_lod[] =
{
"lowest_lod",
@@ -457,6 +469,55 @@ public:
};
+void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name)
+{
+ // Add notification popup.
+ LLSD args;
+ std::string message = content["error"]["message"];
+ std::string identifier = content["error"]["identifier"];
+ args["MESSAGE"] = message;
+ args["IDENTIFIER"] = identifier;
+ args["LABEL"] = model_name;
+ gMeshRepo.uploadError(args);
+
+ // Log details.
+ llwarns << "stage: " << stage << " http status: " << status << llendl;
+ if (content.has("error"))
+ {
+ const LLSD& err = content["error"];
+ llwarns << "err: " << err << llendl;
+ llwarns << "mesh upload failed, stage '" << stage
+ << "' error '" << err["error"].asString()
+ << "', message '" << err["message"].asString()
+ << "', id '" << err["identifier"].asString()
+ << "'" << llendl;
+ if (err.has("errors"))
+ {
+ S32 error_num = 0;
+ const LLSD& err_list = err["errors"];
+ for (LLSD::array_const_iterator it = err_list.beginArray();
+ it != err_list.endArray();
+ ++it)
+ {
+ const LLSD& err_entry = *it;
+ llwarns << "error[" << error_num << "]:" << llendl;
+ for (LLSD::map_const_iterator map_it = err_entry.beginMap();
+ map_it != err_entry.endMap();
+ ++map_it)
+ {
+ llwarns << "\t" << map_it->first << ": "
+ << map_it->second << llendl;
+ }
+ error_num++;
+ }
+ }
+ }
+ else
+ {
+ llwarns << "bad mesh, no error information available" << llendl;
+ }
+}
+
class LLModelObjectUploadResponder: public LLCurl::Responder
{
LLSD mObjectAsset;
@@ -484,20 +545,83 @@ public:
class LLWholeModelFeeResponder: public LLCurl::Responder
{
LLMeshUploadThread* mThread;
+ LLSD mModelData;
public:
- LLWholeModelFeeResponder(LLMeshUploadThread* thread):
- mThread(thread)
+ LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data):
+ mThread(thread),
+ mModelData(model_data)
{
}
- virtual void completedRaw(U32 status, const std::string& reason,
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
+ virtual void completed(U32 status,
+ const std::string& reason,
+ const LLSD& content)
{
- assert_main_thread();
+ LLSD cc = content;
+ if (gSavedSettings.getS32("MeshUploadFakeErrors")&1)
+ {
+ cc = llsd_from_file("fake_upload_error.xml");
+ }
+
llinfos << "completed" << llendl;
mThread->mPendingUploads--;
+ dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
+ if (isGoodStatus(status) &&
+ cc["state"].asString() == "upload")
+ {
+ llinfos << "fee request succeeded" << llendl;
+ mThread->mWholeModelUploadURL = cc["uploader"].asString();
+ }
+ else
+ {
+ llwarns << "fee request failed" << llendl;
+ log_upload_error(status,cc,"fee",mModelData["name"]);
+ mThread->mWholeModelUploadURL = "";
+ }
}
+
+};
+
+class LLWholeModelUploadResponder: public LLCurl::Responder
+{
+ LLMeshUploadThread* mThread;
+ LLSD mModelData;
+public:
+ LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data):
+ mThread(thread),
+ mModelData(model_data)
+ {
+ }
+ virtual void completed(U32 status,
+ const std::string& reason,
+ const LLSD& content)
+ {
+ LLSD cc = content;
+ if (gSavedSettings.getS32("MeshUploadFakeErrors")&2)
+ {
+ cc = llsd_from_file("fake_upload_error.xml");
+ }
+
+ //assert_main_thread();
+ mThread->mPendingUploads--;
+ dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
+ llinfos << "LLWholeModelUploadResponder content: " << cc << llendl;
+ // requested "mesh" asset type isn't actually the type
+ // of the resultant object, fix it up here.
+ if (isGoodStatus(status) &&
+ cc["state"].asString() == "complete")
+ {
+ llinfos << "upload succeeded" << llendl;
+ mModelData["asset_type"] = "object";
+ gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc));
+ }
+ else
+ {
+ llwarns << "upload failed" << llendl;
+ std::string model_name = mModelData["name"].asString();
+ log_upload_error(status,cc,"upload",model_name);
+ }
+ }
};
LLMeshRepoThread::LLMeshRepoThread()
@@ -671,10 +795,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
if (pending != mPendingLOD.end())
{ //append this lod request to existing header request
pending->second.push_back(lod);
- if (pending->second.size() > 4)
- {
- llerrs << "WTF?" << llendl;
- }
+ llassert(pending->second.size() <= LLModel::NUM_LODS)
}
else
{ //if no header request is pending, fetch header
@@ -794,8 +915,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (header_size > 0)
{
- S32 offset = header_size + mMeshHeader[mesh_id]["decomposition"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["decomposition"]["size"].asInteger();
+ S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
+ S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -866,8 +987,8 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (header_size > 0)
{
- S32 offset = header_size + mMeshHeader[mesh_id]["physics_shape"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["physics_shape"]["size"].asInteger();
+ S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
+ S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -1259,9 +1380,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mOrigin = gAgent.getPositionAgent();
mHost = gAgent.getRegionHost();
- mUploadObjectAssetCapability = gAgent.getRegion()->getCapability("UploadObjectAsset");
- mNewInventoryCapability = gAgent.getRegion()->getCapability("NewFileAgentInventoryVariablePrice");
- mWholeModelUploadCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
+ mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
mOrigin += gAgent.getAtAxis() * scale.magVec();
}
@@ -1280,35 +1399,7 @@ LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_mod
mThread = thread;
//copy out positions and indices
- if (mdl)
- {
- U16 index_offset = 0;
-
- mPositions.clear();
- mIndices.clear();
-
- //queue up vertex positions and indices
- for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
- {
- const LLVolumeFace& face = mdl->getVolumeFace(i);
- if (mPositions.size() + face.mNumVertices > 65535)
- {
- continue;
- }
-
- for (U32 j = 0; j < face.mNumVertices; ++j)
- {
- mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
- }
-
- for (U32 j = 0; j < face.mNumIndices; ++j)
- {
- mIndices.push_back(face.mIndices[j]+index_offset);
- }
-
- index_offset += face.mNumVertices;
- }
- }
+ assignData(mdl) ;
mThread->mFinalDecomp = this;
mThread->mPhysicsComplete = false;
@@ -1321,11 +1412,8 @@ void LLMeshUploadThread::DecompRequest::completed()
mThread->mPhysicsComplete = true;
}
- if (mHull.size() != 1)
- {
- llerrs << "WTF?" << llendl;
- }
-
+ llassert(mHull.size() == 1);
+
mThread->mHullMap[mBaseModel] = mHull[0];
}
@@ -1353,143 +1441,199 @@ BOOL LLMeshUploadThread::isDiscarded()
void LLMeshUploadThread::run()
{
- if (gSavedSettings.getBOOL("MeshUseWholeModelUpload"))
- {
- doWholeModelUpload();
- }
- else
+ doWholeModelUpload();
+}
+
+void dump_llsd_to_file(const LLSD& content, std::string filename)
+{
+ if (gSavedSettings.getBOOL("MeshUploadLogXML"))
{
- doIterativeUpload();
+ std::ofstream of(filename.c_str());
+ LLSDSerialize::toPrettyXML(content,of);
}
}
-#if 0
-void dumpLLSDToFile(LLSD& content, std::string& filename)
+LLSD llsd_from_file(std::string filename)
{
- std::ofstream of(filename);
- LLSDSerialize::toPrettyXML(content,of);
+ std::ifstream ifs(filename.c_str());
+ LLSD result;
+ LLSDSerialize::fromXML(result,ifs);
+ return result;
}
-#endif
void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
{
- // TODO where do textures go?
-
LLSD result;
+ LLSD res;
result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
result["asset_type"] = "mesh";
result["inventory_type"] = "object";
- result["name"] = "your name here";
+ result["name"] = "mesh model";
result["description"] = "your description here";
- // TODO "optional" fields from the spec
-
- LLSD res;
res["mesh_list"] = LLSD::emptyArray();
res["texture_list"] = LLSD::emptyArray();
+ res["instance_list"] = LLSD::emptyArray();
S32 mesh_num = 0;
S32 texture_num = 0;
std::set<LLViewerTexture* > textures;
+ std::map<LLViewerTexture*,S32> texture_index;
+ std::map<LLModel*,S32> mesh_index;
+
+ S32 instance_num = 0;
+
for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
{
LLMeshUploadData data;
data.mBaseModel = iter->first;
-
- LLModelInstance& instance = *(iter->second.begin());
-
+ LLModelInstance& first_instance = *(iter->second.begin());
for (S32 i = 0; i < 5; i++)
{
- data.mModel[i] = instance.mLOD[i];
+ data.mModel[i] = first_instance.mLOD[i];
}
- std::stringstream ostr;
-
- LLModel::Decomposition& decomp =
- data.mModel[LLModel::LOD_PHYSICS].notNull() ?
- data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
- data.mBaseModel->mPhysics;
-
- decomp.mBaseHull = mHullMap[data.mBaseModel];
-
- LLSD mesh_header = LLModel::writeModel(
- ostr,
- data.mModel[LLModel::LOD_PHYSICS],
- data.mModel[LLModel::LOD_HIGH],
- data.mModel[LLModel::LOD_MEDIUM],
- data.mModel[LLModel::LOD_LOW],
- data.mModel[LLModel::LOD_IMPOSTOR],
- decomp,
- mUploadSkin,
- mUploadJoints);
+ if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+ {
+ // Have not seen this model before - create a new mesh_list entry for it.
+ std::string model_name = data.mBaseModel->getName();
+ if (!model_name.empty())
+ {
+ result["name"] = model_name;
+ }
- data.mAssetData = ostr.str();
+ std::stringstream ostr;
+
+ LLModel::Decomposition& decomp =
+ data.mModel[LLModel::LOD_PHYSICS].notNull() ?
+ data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
+ data.mBaseModel->mPhysics;
- LLSD mesh_entry;
+ decomp.mBaseHull = mHullMap[data.mBaseModel];
- LLVector3 pos, scale;
- LLQuaternion rot;
- LLMatrix4 transformation = instance.mTransform;
- decomposeMeshMatrix(transformation,pos,rot,scale);
-
- mesh_entry["childpos"] = ll_sd_from_vector3(pos);
- mesh_entry["childrot"] = ll_sd_from_quaternion(rot);
- mesh_entry["scale"] = ll_sd_from_vector3(scale);
+ LLSD mesh_header = LLModel::writeModel(
+ ostr,
+ data.mModel[LLModel::LOD_PHYSICS],
+ data.mModel[LLModel::LOD_HIGH],
+ data.mModel[LLModel::LOD_MEDIUM],
+ data.mModel[LLModel::LOD_LOW],
+ data.mModel[LLModel::LOD_IMPOSTOR],
+ decomp,
+ mUploadSkin,
+ mUploadJoints);
- // TODO should be binary.
- std::string str = ostr.str();
- mesh_entry["mesh_data"] = LLSD::Binary(str.begin(),str.end());
+ data.mAssetData = ostr.str();
+ std::string str = ostr.str();
- res["mesh_list"][mesh_num] = mesh_entry;
+ res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
+ mesh_index[data.mBaseModel] = mesh_num;
+ mesh_num++;
+ }
- // TODO how do textures in the list map to textures in the meshes?
- if (mUploadTextures)
+ // For all instances that use this model
+ for (instance_list::iterator instance_iter = iter->second.begin();
+ instance_iter != iter->second.end();
+ ++instance_iter)
{
- for (std::vector<LLImportMaterial>::iterator material_iter = instance.mMaterial.begin();
- material_iter != instance.mMaterial.end(); ++material_iter)
- {
- if (textures.find(material_iter->mDiffuseMap.get()) == textures.end())
+ LLModelInstance& instance = *instance_iter;
+
+ LLSD instance_entry;
+
+ for (S32 i = 0; i < 5; i++)
+ {
+ data.mModel[i] = instance.mLOD[i];
+ }
+
+ LLVector3 pos, scale;
+ LLQuaternion rot;
+ LLMatrix4 transformation = instance.mTransform;
+ decomposeMeshMatrix(transformation,pos,rot,scale);
+ instance_entry["position"] = ll_sd_from_vector3(pos);
+ instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+ instance_entry["scale"] = ll_sd_from_vector3(scale);
+
+ instance_entry["material"] = LL_MCODE_WOOD;
+ LLPermissions perm;
+ perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
+ perm.setCreator(gAgent.getID());
+
+ perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base
+ PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner
+ LLFloaterPerms::getEveryonePerms(),
+ LLFloaterPerms::getGroupPerms(),
+ LLFloaterPerms::getNextOwnerPerms());
+ instance_entry["permissions"] = ll_create_sd_from_permissions(perm);
+ instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+ instance_entry["mesh"] = mesh_index[data.mBaseModel];
+
+ instance_entry["face_list"] = LLSD::emptyArray();
+
+ for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++)
+ {
+ LLImportMaterial& material = instance.mMaterial[face_num];
+ LLSD face_entry = LLSD::emptyMap();
+ LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
+
+ if ((texture != NULL) &&
+ (textures.find(texture) == textures.end()))
{
- textures.insert(material_iter->mDiffuseMap.get());
+ textures.insert(texture);
+ }
- std::stringstream ostr;
- if (include_textures) // otherwise data is blank.
- {
- LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel);
- if (!data.mTexture->isRawImageValid())
- {
- data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
- }
-
+ std::stringstream texture_str;
+ if (texture != NULL && include_textures && mUploadTextures)
+ {
+ if(texture->hasSavedRawImage())
+ {
LLPointer<LLImageJ2C> upload_file =
- LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage());
- ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
+ texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
}
- LLSD texture_entry;
- texture_entry["texture_data"] = ostr.str();
- res["texture_list"][texture_num] = texture_entry;
+ }
+
+ if (texture != NULL &&
+ mUploadTextures &&
+ texture_index.find(texture) == texture_index.end())
+ {
+ texture_index[texture] = texture_num;
+ std::string str = texture_str.str();
+ res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
texture_num++;
}
- }
- }
- mesh_num++;
+ // Subset of TextureEntry fields.
+ if (texture != NULL && mUploadTextures)
+ {
+ face_entry["image"] = texture_index[texture];
+ face_entry["scales"] = 1.0;
+ face_entry["scalet"] = 1.0;
+ face_entry["offsets"] = 0.0;
+ face_entry["offsett"] = 0.0;
+ face_entry["imagerot"] = 0.0;
+ }
+ face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
+ face_entry["fullbright"] = material.mFullbright;
+ instance_entry["face_list"][face_num] = face_entry;
+ }
+
+ res["instance_list"][instance_num] = instance_entry;
+ instance_num++;
+ }
}
result["asset_resources"] = res;
-#if 0
- std::string name("whole_model.xml");
- dumpLLSDToFile(result,name);
-#endif
+ dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num));
dest = result;
}
void LLMeshUploadThread::doWholeModelUpload()
{
+ dump_num++;
+
mCurlRequest = new LLCurlRequest();
// Queue up models for hull generation (viewer-side)
@@ -1521,13 +1665,13 @@ void LLMeshUploadThread::doWholeModelUpload()
physics = data.mModel[LLModel::LOD_HIGH];
}
- if (!physics)
- {
- llerrs << "WTF?" << llendl;
- }
-
+ llassert(physics != NULL);
+
DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
- gMeshRepo.mDecompThread->submitRequest(request);
+ if(request->isValid())
+ {
+ gMeshRepo.mDecompThread->submitRequest(request);
+ }
}
while (!mPhysicsComplete)
@@ -1535,168 +1679,44 @@ void LLMeshUploadThread::doWholeModelUpload()
apr_sleep(100);
}
- bool do_include_textures = false; // not needed for initial cost/validation check.
LLSD model_data;
- wholeModelToLLSD(model_data, do_include_textures);
+ wholeModelToLLSD(model_data,false);
+ dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
mPendingUploads++;
LLCurlRequest::headers_t headers;
- mCurlRequest->post(mWholeModelUploadCapability, headers, model_data.asString(),
- new LLWholeModelFeeResponder(this));
-
- // Currently a no-op.
- mFinished = true;
-}
-
-void LLMeshUploadThread::doIterativeUpload()
-{
- if(isDiscarded())
- {
- mFinished = true;
- return ;
- }
-
- mCurlRequest = new LLCurlRequest();
-
- std::set<LLViewerTexture* > textures;
-
- //populate upload queue with relevant models
- for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
- {
- LLMeshUploadData data;
- data.mBaseModel = iter->first;
-
- LLModelInstance& instance = *(iter->second.begin());
-
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = instance.mLOD[i];
- }
-
- uploadModel(data);
-
- if (mUploadTextures)
- {
- for (std::vector<LLImportMaterial>::iterator material_iter = instance.mMaterial.begin();
- material_iter != instance.mMaterial.end(); ++material_iter)
- {
-
- if (textures.find(material_iter->mDiffuseMap.get()) == textures.end())
- {
- textures.insert(material_iter->mDiffuseMap.get());
-
- LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel);
- uploadTexture(data);
- }
- }
- }
-
- //queue up models for hull generation
- DecompRequest* request = new DecompRequest(data.mModel[LLModel::LOD_HIGH], data.mBaseModel, this);
- gMeshRepo.mDecompThread->submitRequest(request);
- }
-
- while (!mPhysicsComplete)
- {
- apr_sleep(100);
- }
+ mCurlRequest->post(mWholeModelFeeCapability, headers, model_data,
+ new LLWholeModelFeeResponder(this,model_data));
- //upload textures
- bool done = false;
do
{
- if (!mTextureQ.empty())
- {
- sendCostRequest(mTextureQ.front());
- mTextureQ.pop();
- }
-
- if (!mConfirmedTextureQ.empty())
- {
- doUploadTexture(mConfirmedTextureQ.front());
- mConfirmedTextureQ.pop();
- }
-
mCurlRequest->process();
+ } while (mCurlRequest->getQueued() > 0);
- done = mTextureQ.empty() && mConfirmedTextureQ.empty();
- }
- while (!done || mCurlRequest->getQueued() > 0);
-
- LLSD object_asset;
- object_asset["objects"] = LLSD::emptyArray();
- done = false;
- do
+ if (mWholeModelUploadURL.empty())
{
- static S32 count = 0;
- static F32 last_hundred = gFrameTimeSeconds;
- if (gFrameTimeSeconds - last_hundred > 1.f)
+ llinfos << "unable to upload, fee request failed" << llendl;
+ }
+ else
+ {
+ LLSD full_model_data;
+ wholeModelToLLSD(full_model_data, true);
+ LLSD body = full_model_data["asset_resources"];
+ dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
+ mCurlRequest->post(mWholeModelUploadURL, headers, body,
+ new LLWholeModelUploadResponder(this, model_data));
+ do
{
- last_hundred = gFrameTimeSeconds;
- count = 0;
- }
-
- //how many requests to push before calling process
- const S32 PUSH_PER_PROCESS = 32;
-
- S32 tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
- while (!mUploadQ.empty() && count < tcount)
- { //send any pending upload requests
- mMutex->lock();
- LLMeshUploadData data = mUploadQ.front();
- mUploadQ.pop();
- mMutex->unlock();
- sendCostRequest(data);
- count++;
- }
-
- tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
- while (!mConfirmedQ.empty() && count < tcount)
- { //process any meshes that have been confirmed for upload
- LLMeshUploadData& data = mConfirmedQ.front();
- doUploadModel(data);
- mConfirmedQ.pop();
- count++;
- }
-
- tcount = llmin(count+PUSH_PER_PROCESS, 100);
-
- while (!mInstanceQ.empty() && count < tcount && !isDiscarded())
- { //create any objects waiting for upload
- count++;
- object_asset["objects"].append(createObject(mInstanceQ.front()));
- mInstanceQ.pop();
- }
-
- mCurlRequest->process();
-
- done = isDiscarded() || (mInstanceQ.empty() && mConfirmedQ.empty() && mUploadQ.empty());
+ mCurlRequest->process();
+ } while (mCurlRequest->getQueued() > 0);
}
- while (!done || mCurlRequest->getQueued() > 0);
delete mCurlRequest;
mCurlRequest = NULL;
- // now upload the object asset
- std::string url = mUploadObjectAssetCapability;
-
- if (object_asset["objects"][0].has("permissions"))
- { //copy permissions from first available object to be used for coalesced object
- object_asset["permissions"] = object_asset["objects"][0]["permissions"];
- }
-
- if(!isDiscarded())
- {
- mPendingUploads++;
- LLHTTPClient::post(url, object_asset, new LLModelObjectUploadResponder(this,object_asset));
- }
- else
- {
- mFinished = true;
- }
+ // Currently a no-op.
+ mFinished = true;
}
void LLMeshUploadThread::uploadModel(LLMeshUploadData& data)
@@ -2127,7 +2147,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
//just in case skin info or decomposition is at the end of the file (which it shouldn't be)
lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
- lod_bytes = llmax(lod_bytes, header["decomposition"]["offset"].asInteger() + header["decomposition"]["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];
S32 bytes = lod_bytes + header_bytes;
@@ -2344,10 +2364,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
group->derefLOD(lod);
}
}
- else
- {
- llerrs << "WTF?" << llendl;
- }
}
return detail;
@@ -2419,7 +2435,6 @@ void LLMeshRepository::notifyLoadedMeshes()
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
{
region_name = gAgent.getRegion()->getName();
-
mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh");
}
}
@@ -2527,6 +2542,20 @@ void LLMeshRepository::notifyLoadedMeshes()
void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
{
mSkinMap[info.mMeshID] = info;
+
+ skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID);
+ if (iter != mLoadingSkins.end())
+ {
+ for (std::set<LLUUID>::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id)
+ {
+ LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id);
+ if (vobj)
+ {
+ vobj->notifyMeshLoaded();
+ }
+ }
+ }
+
mLoadingSkins.erase(info.mMeshID);
}
@@ -2642,7 +2671,7 @@ U32 LLMeshRepository::getResourceCost(const LLUUID& mesh_id)
return mThread->getResourceCost(mesh_id);
}
-const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id)
+const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)
{
if (mesh_id.notNull())
{
@@ -2656,12 +2685,12 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id)
{
LLMutexLock lock(mMeshMutex);
//add volume to list of loading meshes
- std::set<LLUUID>::iterator iter = mLoadingSkins.find(mesh_id);
+ skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
if (iter == mLoadingSkins.end())
{ //no request pending for this skin info
- mLoadingSkins.insert(mesh_id);
mPendingSkinRequests.push(mesh_id);
}
+ mLoadingSkins[mesh_id].insert(requesting_obj->getID());
}
}
@@ -2743,7 +2772,18 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail)
bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
{
LLSD mesh = mThread->getMeshHeader(mesh_id);
- return mesh.has("physics_shape") && mesh["physics_shape"].has("size") && (mesh["physics_shape"]["size"].asInteger() > 0);
+ 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;
+ }
+
+ return false;
}
LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id)
@@ -2799,102 +2839,6 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
}
-void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data)
-{
- if(isDiscarded())
- {
- return ;
- }
-
- //write model file to memory buffer
- std::stringstream ostr;
-
- LLModel::Decomposition& decomp =
- data.mModel[LLModel::LOD_PHYSICS].notNull() ?
- data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
- data.mBaseModel->mPhysics;
-
- LLSD header = LLModel::writeModel(
- ostr,
- data.mModel[LLModel::LOD_PHYSICS],
- data.mModel[LLModel::LOD_HIGH],
- data.mModel[LLModel::LOD_MEDIUM],
- data.mModel[LLModel::LOD_LOW],
- data.mModel[LLModel::LOD_IMPOSTOR],
- decomp,
- mUploadSkin,
- mUploadJoints,
- true);
-
- std::string desc = data.mBaseModel->mLabel;
-
- // Grab the total vertex count of the model
- // along with other information for the "asset_resources" map
- // to send to the server.
- LLSD asset_resources = LLSD::emptyMap();
-
-
- std::string url = mNewInventoryCapability;
-
- if (!url.empty())
- {
- LLSD body = generate_new_resource_upload_capability_body(
- LLAssetType::AT_MESH,
- desc,
- desc,
- LLFolderType::FT_MESH,
- LLInventoryType::IT_MESH,
- LLFloaterPerms::getNextOwnerPerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getEveryonePerms());
-
- body["asset_resources"] = asset_resources;
-
- mPendingConfirmations++;
- LLCurlRequest::headers_t headers;
-
- data.mPostData = body;
-
- mCurlRequest->post(url, headers, body, new LLMeshCostResponder(data, this));
- }
-}
-
-void LLMeshUploadThread::sendCostRequest(LLTextureUploadData& data)
-{
- if(isDiscarded())
- {
- return ;
- }
-
- if (data.mTexture && data.mTexture->getDiscardLevel() >= 0)
- {
- LLSD asset_resources = LLSD::emptyMap();
-
- std::string url = mNewInventoryCapability;
-
- if (!url.empty())
- {
- LLSD body = generate_new_resource_upload_capability_body(
- LLAssetType::AT_TEXTURE,
- data.mLabel,
- data.mLabel,
- LLFolderType::FT_TEXTURE,
- LLInventoryType::IT_TEXTURE,
- LLFloaterPerms::getNextOwnerPerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getEveryonePerms());
-
- body["asset_resources"] = asset_resources;
-
- mPendingConfirmations++;
- LLCurlRequest::headers_t headers;
-
- data.mPostData = body;
- mCurlRequest->post(url, headers, body, new LLTextureCostResponder(data, this));
- }
- }
-}
-
void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
{
@@ -2950,9 +2894,12 @@ void LLMeshUploadThread::doUploadTexture(LLTextureUploadData& data)
data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
}
- LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage());
+ if(data.mTexture->hasSavedRawImage())
+ {
+ LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getSavedRawImage());
- ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
+ }
data.mAssetData = ostr.str();
@@ -3032,11 +2979,8 @@ LLSD LLMeshUploadThread::createObject(LLModelInstance& instance)
{
LLMatrix4 transformation = instance.mTransform;
- if (instance.mMeshID.isNull())
- {
- llerrs << "WTF?" << llendl;
- }
-
+ llassert(instance.mMeshID.notNull());
+
// check for reflection
BOOL reflected = (transformation.determinant() < 0);
@@ -3200,6 +3144,8 @@ bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
void LLMeshRepository::updateInventory(inventory_data data)
{
LLMutexLock lock(mMeshMutex);
+ dump_llsd_to_file(data.mPostData,make_dump_name("update_inventory_post_data_",dump_num));
+ dump_llsd_to_file(data.mResponse,make_dump_name("update_inventory_response_",dump_num));
mInventoryQ.push(data);
}
@@ -3357,15 +3303,18 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)
mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
- LLCDResult ret = LLCD_OK;
- if (LLConvexDecomposition::getInstance() != NULL)
+ if (mesh.mNumTriangles > 0 && mesh.mNumVertices > 2)
{
- ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
- }
+ LLCDResult ret = LLCD_OK;
+ if (LLConvexDecomposition::getInstance() != NULL)
+ {
+ ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
+ }
- if (ret)
- {
- llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+ if (ret)
+ {
+ llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+ }
}
}
@@ -3374,6 +3323,12 @@ void LLPhysicsDecomp::doDecomposition()
LLCDMeshData mesh;
S32 stage = mStageID[mCurRequest->mStage];
+ if (LLConvexDecomposition::getInstance() == NULL)
+ {
+ // stub library. do nothing.
+ return;
+ }
+
//load data intoLLCD
if (stage == 0)
{
@@ -3423,11 +3378,6 @@ void LLPhysicsDecomp::doDecomposition()
{
ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asBoolean());
}
-
- if (ret)
- {
- llerrs << "WTF?" << llendl;
- }
}
mCurRequest->setStatusMessage("Executing.");
@@ -3574,6 +3524,12 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
+ if (decomp == NULL)
+ {
+ //stub. do nothing.
+ return;
+ }
+
for (S32 i = 0; i < param_count; ++i)
{
decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);
@@ -3653,6 +3609,14 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
void LLPhysicsDecomp::run()
{
LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
+ if (decomp == NULL)
+ {
+ // stub library. Set init to true so the main thread
+ // doesn't wait for this to finish.
+ mInited = true;
+ return;
+ }
+
decomp->initThread();
mInited = true;
@@ -3708,6 +3672,81 @@ void LLPhysicsDecomp::run()
mDone = true;
}
+void LLPhysicsDecomp::Request::assignData(LLModel* mdl)
+{
+ if (!mdl)
+ {
+ return ;
+ }
+
+ U16 index_offset = 0;
+ U16 tri[3] ;
+
+ mPositions.clear();
+ mIndices.clear();
+ mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ;
+ mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ;
+
+ //queue up vertex positions and indices
+ for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i)
+ {
+ const LLVolumeFace& face = mdl->getVolumeFace(i);
+ if (mPositions.size() + face.mNumVertices > 65535)
+ {
+ continue;
+ }
+
+ for (U32 j = 0; j < face.mNumVertices; ++j)
+ {
+ mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr()));
+ for(U32 k = 0 ; k < 3 ; k++)
+ {
+ mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ;
+ mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ;
+ }
+ }
+
+ updateTriangleAreaThreshold() ;
+
+ for (U32 j = 0; j+2 < face.mNumIndices; j += 3)
+ {
+ tri[0] = face.mIndices[j] + index_offset ;
+ tri[1] = face.mIndices[j + 1] + index_offset ;
+ tri[2] = face.mIndices[j + 2] + index_offset ;
+
+ if(isValidTriangle(tri[0], tri[1], tri[2]))
+ {
+ mIndices.push_back(tri[0]);
+ mIndices.push_back(tri[1]);
+ mIndices.push_back(tri[2]);
+ }
+ }
+
+ index_offset += face.mNumVertices;
+ }
+
+ return ;
+}
+
+void LLPhysicsDecomp::Request::updateTriangleAreaThreshold()
+{
+ F32 range = mBBox[1].mV[0] - mBBox[0].mV[0] ;
+ range = llmin(range, mBBox[1].mV[1] - mBBox[0].mV[1]) ;
+ range = llmin(range, mBBox[1].mV[2] - mBBox[0].mV[2]) ;
+
+ mTriangleAreaThreshold = llmin(0.0002f, range * 0.000002f) ;
+}
+
+//check if the triangle area is large enough to qualify for a valid triangle
+bool LLPhysicsDecomp::Request::isValidTriangle(U16 idx1, U16 idx2, U16 idx3)
+{
+ LLVector3 a = mPositions[idx2] - mPositions[idx1] ;
+ LLVector3 b = mPositions[idx3] - mPositions[idx1] ;
+ F32 c = a * b ;
+
+ return ((a*a) * (b*b) - c * c) > mTriangleAreaThreshold ;
+}
+
void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)
{
mStatusMessage = msg;
@@ -3805,3 +3844,27 @@ void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
}
}
}
+
+
+bool LLMeshRepository::meshUploadEnabled()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ if(gSavedSettings.getBOOL("MeshEnabled") &&
+ LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
+ region)
+ {
+ return region->meshUploadEnabled();
+ }
+ return false;
+}
+
+bool LLMeshRepository::meshRezEnabled()
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ if(gSavedSettings.getBOOL("MeshEnabled") &&
+ region)
+ {
+ return region->meshRezEnabled();
+ }
+ return false;
+}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 802e3e1aba..f237c3a60e 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -152,7 +152,7 @@ public:
std::string mStatusMessage;
std::vector<LLModel::PhysicsMesh> mHullMesh;
LLModel::convex_hull_decomposition mHull;
-
+
//status message callback, called from decomposition thread
virtual S32 statusCallback(const char* status, S32 p1, S32 p2) = 0;
@@ -160,6 +160,17 @@ public:
virtual void completed() = 0;
virtual void setStatusMessage(const std::string& msg);
+
+ bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
+
+ protected:
+ //internal use
+ LLVector3 mBBox[2] ;
+ F32 mTriangleAreaThreshold ;
+
+ void assignData(LLModel* mdl) ;
+ void updateTriangleAreaThreshold() ;
+ bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
};
LLCondition* mSignal;
@@ -385,9 +396,8 @@ public:
BOOL mDiscarded ;
LLHost mHost;
- std::string mUploadObjectAssetCapability;
- std::string mNewInventoryCapability;
- std::string mWholeModelUploadCapability;
+ std::string mWholeModelFeeCapability;
+ std::string mWholeModelUploadURL;
std::queue<LLMeshUploadData> mUploadQ;
std::queue<LLMeshUploadData> mConfirmedQ;
@@ -404,12 +414,10 @@ public:
void uploadTexture(LLTextureUploadData& data);
void doUploadTexture(LLTextureUploadData& data);
- void sendCostRequest(LLTextureUploadData& data);
void priceResult(LLTextureUploadData& data, const LLSD& content);
void onTextureUploaded(LLTextureUploadData& data);
void uploadModel(LLMeshUploadData& data);
- void sendCostRequest(LLMeshUploadData& data);
void doUploadModel(LLMeshUploadData& data);
void onModelUploaded(LLMeshUploadData& data);
void createObjects(LLMeshUploadData& data);
@@ -423,7 +431,6 @@ public:
BOOL isDiscarded();
void doWholeModelUpload();
- void doIterativeUpload();
void wholeModelToLLSD(LLSD& dest, bool include_textures);
@@ -466,13 +473,17 @@ public:
static S32 getActualMeshLOD(LLSD& header, S32 lod);
U32 calcResourceCost(LLSD& header);
U32 getResourceCost(const LLUUID& mesh_params);
- const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
+ const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);
void buildHull(const LLVolumeParams& params, S32 detail);
void buildPhysicsMesh(LLModel::Decomposition& decomp);
+
+ bool meshUploadEnabled();
+ bool meshRezEnabled();
+
LLSD& getMeshHeader(const LLUUID& mesh_id);
@@ -495,7 +506,8 @@ public:
std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
//list of mesh ids awaiting skin info
- std::set<LLUUID> mLoadingSkins;
+ typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map;
+ skin_load_map mLoadingSkins;
//list of mesh ids that need to send skin info fetch requests
std::queue<LLUUID> mPendingSkinRequests;
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index d3fd959152..4b961db5f9 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -889,11 +889,11 @@ void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT);
}
-class LLChatHandler : public LLCommandHandler
+class LLChatCommandHandler : public LLCommandHandler
{
public:
// not allowed from outside the app
- LLChatHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
+ LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
// Your code here
bool handle(const LLSD& tokens, const LLSD& query_map,
@@ -909,7 +909,7 @@ public:
{
S32 channel = tokens[0].asInteger();
// VWR-19499 Restrict function to chat channels greater than 0.
- if ((channel > 0) && (channel < 2147483647))
+ if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG))
{
retval = true;
// Send unescaped message, see EXT-6353.
@@ -927,6 +927,6 @@ public:
};
// Creating the object registers with the dispatcher.
-LLChatHandler gChatHandler;
+LLChatCommandHandler gChatHandler;
diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp
new file mode 100644
index 0000000000..a63e1fb76e
--- /dev/null
+++ b/indra/newview/llnearbychatbarlistener.cpp
@@ -0,0 +1,100 @@
+/**
+ * @file llnearbychatbarlistener.cpp
+ * @author Dave Simmons
+ * @date 2011-03-15
+ * @brief Implementation for LLNearbyChatBarListener.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llnearbychatbarlistener.h"
+#include "llnearbychatbar.h"
+
+#include "llagent.h"
+#include "llchat.h"
+
+
+
+LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar)
+ : LLEventAPI("LLChatBar",
+ "LLChatBar listener to (e.g.) sendChat, etc."),
+ mChatbar(chatbar)
+{
+ add("sendChat",
+ "Send chat to the simulator:\n"
+ "[\"message\"] chat message text [required]\n"
+ "[\"channel\"] chat channel number [default = 0]\n"
+ "[\"type\"] chat type \"whisper\", \"normal\", \"shout\" [default = \"normal\"]",
+ &LLNearbyChatBarListener::sendChat);
+}
+
+
+// "sendChat" command
+void LLNearbyChatBarListener::sendChat(LLSD const & chat_data) const
+{
+ // Extract the data
+ std::string chat_text = chat_data["message"].asString();
+
+ S32 channel = 0;
+ if (chat_data.has("channel"))
+ {
+ channel = chat_data["channel"].asInteger();
+ if (channel < 0 || channel >= CHAT_CHANNEL_DEBUG)
+ { // Use 0 up to (but not including) CHAT_CHANNEL_DEBUG
+ channel = 0;
+ }
+ }
+
+ EChatType type_o_chat = CHAT_TYPE_NORMAL;
+ if (chat_data.has("type"))
+ {
+ std::string type_string = chat_data["type"].asString();
+ if (type_string == "whisper")
+ {
+ type_o_chat = CHAT_TYPE_WHISPER;
+ }
+ else if (type_string == "shout")
+ {
+ type_o_chat = CHAT_TYPE_SHOUT;
+ }
+ }
+
+ // Have to prepend /42 style channel numbers
+ std::string chat_to_send;
+ if (channel == 0)
+ {
+ chat_to_send = chat_text;
+ }
+ else
+ {
+ chat_to_send += "/";
+ chat_to_send += chat_data["channel"].asString();
+ chat_to_send += " ";
+ chat_to_send += chat_text;
+ }
+
+ // Send it as if it was typed in
+ mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, (BOOL)(channel == 0));
+}
+
diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h
new file mode 100644
index 0000000000..9af9bc1f7b
--- /dev/null
+++ b/indra/newview/llnearbychatbarlistener.h
@@ -0,0 +1,50 @@
+/**
+ * @file llnearbychatbarlistener.h
+ * @author Dave Simmons
+ * @date 2011-03-15
+ * @brief Class definition for LLNearbyChatBarListener.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLNEARBYCHATBARLISTENER_H
+#define LL_LLNEARBYCHATBARLISTENER_H
+
+#include "lleventapi.h"
+
+class LLSD;
+class LLNearbyChatBar;
+
+class LLNearbyChatBarListener : public LLEventAPI
+{
+public:
+ LLNearbyChatBarListener(LLNearbyChatBar & chatbar);
+
+private:
+ void sendChat(LLSD const & chat_data) const;
+
+ LLNearbyChatBar & mChatbar;
+};
+
+#endif // LL_LLNEARBYCHATBARLISTENER_H
+
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index b56fb65a4c..957b6d5f94 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -268,6 +268,9 @@ bool LLNearbyChatScreenChannel::createPoolToast()
toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1));
+ // If the toast gets somehow prematurely destroyed, deactivate it to prevent crash (STORM-1352).
+ toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1, false));
+
LL_DEBUGS("NearbyChat") << "Creating and pooling toast" << llendl;
m_toast_pool.push_back(toast->getHandle());
return true;
@@ -369,8 +372,10 @@ void LLNearbyChatScreenChannel::arrangeToasts()
}
}
-int sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second)
+static bool sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second)
{
+ if (!first.get() || !second.get()) return false; // STORM-1352
+
F32 v1 = first.get()->getTimeLeftToLive();
F32 v2 = second.get()->getTimeLeftToLive();
return v1 > v2;
@@ -396,7 +401,11 @@ void LLNearbyChatScreenChannel::showToastsBottom()
for(toast_vec_t::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
{
LLToast* toast = it->get();
- if (!toast) continue;
+ if (!toast)
+ {
+ llwarns << "NULL found in the active chat toasts list!" << llendl;
+ continue;
+ }
S32 toast_top = bottom + toast->getRect().getHeight() + margin;
@@ -441,6 +450,8 @@ void LLNearbyChatScreenChannel::reshape (S32 width, S32 height, BOOL called_fr
//-----------------------------------------------------------------------------------------------
//LLNearbyChatHandler
//-----------------------------------------------------------------------------------------------
+boost::scoped_ptr<LLEventPump> LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat"));
+
LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id)
{
mType = type;
@@ -470,7 +481,8 @@ void LLNearbyChatHandler::initChannel()
-void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
+void LLNearbyChatHandler::processChat(const LLChat& chat_msg, // WARNING - not really const, see hack below changing chat_msg.mText
+ const LLSD &args)
{
if(chat_msg.mMuted == TRUE)
return;
@@ -478,7 +490,17 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
if(chat_msg.mText.empty())
return;//don't process empty messages
+ // Handle irc styled messages for toast panel
+ // HACK ALERT - changes mText, stripping out IRC style "/me" prefixes
LLChat& tmp_chat = const_cast<LLChat&>(chat_msg);
+ std::string original_message = tmp_chat.mText; // Save un-modified version of chat text
+ if (tmp_chat.mChatStyle == CHAT_STYLE_IRC)
+ {
+ if(!tmp_chat.mFromName.empty())
+ tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3);
+ else
+ tmp_chat.mText = tmp_chat.mText.substr(3);
+ }
LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
{
@@ -487,6 +509,27 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
// tmp_chat.mFromName = tmp_chat.mFromID.asString();
}
+ // Build notification data
+ LLSD notification;
+ notification["message"] = chat_msg.mText;
+ notification["from"] = chat_msg.mFromName;
+ notification["from_id"] = chat_msg.mFromID;
+ notification["time"] = chat_msg.mTime;
+ notification["source"] = (S32)chat_msg.mSourceType;
+ notification["chat_type"] = (S32)chat_msg.mChatType;
+ notification["chat_style"] = (S32)chat_msg.mChatStyle;
+ // Pass sender info so that it can be rendered properly (STORM-1021).
+ notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);
+
+ if (chat_msg.mChatType == CHAT_TYPE_DIRECT &&
+ chat_msg.mText.length() > 0 &&
+ chat_msg.mText[0] == '@')
+ {
+ // Send event on to LLEventStream and exit
+ sChatWatcher->post(notification);
+ return;
+ }
+
// don't show toast and add message to chat history on receive debug message
// with disabled setting showing script errors or enabled setting to show script
// errors in separate window.
@@ -508,7 +551,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
LLViewerChat::getChatColor(chat_msg,txt_color);
- LLFloaterScriptDebug::addScriptLine(chat_msg.mText,
+ LLFloaterScriptDebug::addScriptLine(original_message, // Send full message with "/me" style prefix
chat_msg.mFromName,
txt_color,
chat_msg.mFromID);
@@ -529,21 +572,16 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
}
+ // Send event on to LLEventStream
+ sChatWatcher->post(notification);
+
+
if( nearby_chat->getVisible()
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
&& gSavedSettings.getBOOL("UseChatBubbles") )
|| !mChannel->getShowToasts() ) // to prevent toasts in Busy mode
return;//no need in toast if chat is visible or if bubble chat is enabled
- // Handle irc styled messages for toast panel
- if (tmp_chat.mChatStyle == CHAT_STYLE_IRC)
- {
- if(!tmp_chat.mFromName.empty())
- tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3);
- else
- tmp_chat.mText = tmp_chat.mText.substr(3);
- }
-
// arrange a channel on a screen
if(!mChannel->getVisible())
{
@@ -562,25 +600,14 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
}
*/
- // Add a nearby chat toast.
- LLUUID id;
- id.generate();
-
LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel);
-
if(channel)
{
- LLSD notification;
+ // Add a nearby chat toast.
+ LLUUID id;
+ id.generate();
notification["id"] = id;
- notification["message"] = chat_msg.mText;
- notification["from"] = chat_msg.mFromName;
- notification["from_id"] = chat_msg.mFromID;
- notification["time"] = chat_msg.mTime;
- notification["source"] = (S32)chat_msg.mSourceType;
- notification["chat_type"] = (S32)chat_msg.mChatType;
- notification["chat_style"] = (S32)chat_msg.mChatStyle;
-
std::string r_color_name = "White";
F32 r_color_alpha = 1.0f;
LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha);
@@ -588,13 +615,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
notification["text_color"] = r_color_name;
notification["color_alpha"] = r_color_alpha;
notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
-
- // Pass sender info so that it can be rendered properly (STORM-1021).
- notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);
-
channel->addNotification(notification);
}
-
}
void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h
index ec1f29cdfc..b0e4f62d51 100644
--- a/indra/newview/llnearbychathandler.h
+++ b/indra/newview/llnearbychathandler.h
@@ -29,6 +29,8 @@
#include "llnotificationhandler.h"
+class LLEventPump;
+
//add LLNearbyChatHandler to LLNotificationsUI namespace
namespace LLNotificationsUI{
@@ -44,6 +46,8 @@ public:
protected:
virtual void onDeleteToast(LLToast* toast);
virtual void initChannel();
+
+ static boost::scoped_ptr<LLEventPump> sChatWatcher;
};
}
diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h
index 72fa394621..16e82e4cce 100644
--- a/indra/newview/llnotificationmanager.h
+++ b/indra/newview/llnotificationmanager.h
@@ -69,7 +69,7 @@ public:
private:
//TODO (*)
std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers;
- std::map<std::string, LLChatHandler*> mChatHandlers;
+ // cruft std::map<std::string, LLChatHandler*> mChatHandlers;
};
}
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 6435126fc0..10887aa53a 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -364,8 +364,8 @@ LLOutfitsList::~LLOutfitsList()
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
- delete mCategoriesObserver;
}
+ delete mCategoriesObserver;
}
BOOL LLOutfitsList::postBuild()
diff --git a/indra/newview/llpanelappearancetab.cpp b/indra/newview/llpanelappearancetab.cpp
index 9910a3a2ac..8fa8867c69 100644
--- a/indra/newview/llpanelappearancetab.cpp
+++ b/indra/newview/llpanelappearancetab.cpp
@@ -31,6 +31,7 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
+#include "llviewerinventory.h"
//virtual
bool LLPanelAppearanceTab::canTakeOffSelected()
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 07c7f35989..a4f6921f98 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -30,6 +30,7 @@
#include "llpanelface.h"
// library includes
+#include "llcalc.h"
#include "llerror.h"
#include "llfocusmgr.h"
#include "llrect.h"
@@ -926,6 +927,16 @@ void LLPanelFace::getState()
getChildView("button apply")->setEnabled(enabled);
}
}
+
+ // Set variable values for numeric expressions
+ LLCalc* calcp = LLCalc::getInstance();
+ calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal());
+ calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal());
+ calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal());
+ calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal());
+ calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal());
+ calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal());
+ calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());
}
else
{
@@ -961,6 +972,16 @@ void LLPanelFace::getState()
//getChildView("has media")->setEnabled(FALSE);
//getChildView("media info set")->setEnabled(FALSE);
+
+ // Set variable values for numeric expressions
+ LLCalc* calcp = LLCalc::getInstance();
+ calcp->clearVar(LLCalc::TEX_U_SCALE);
+ calcp->clearVar(LLCalc::TEX_V_SCALE);
+ calcp->clearVar(LLCalc::TEX_U_OFFSET);
+ calcp->clearVar(LLCalc::TEX_V_OFFSET);
+ calcp->clearVar(LLCalc::TEX_ROTATION);
+ calcp->clearVar(LLCalc::TEX_TRANSPARENCY);
+ calcp->clearVar(LLCalc::TEX_GLOW);
}
}
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 0cc5dcda82..e370f2f622 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -71,7 +71,7 @@ void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &ch
void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
- updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+ updateButtons(new_state);
}
void LLPanelChatControlPanel::updateCallButton()
@@ -96,11 +96,15 @@ void LLPanelChatControlPanel::updateCallButton()
getChildView("call_btn")->setEnabled(enable_connect);
}
-void LLPanelChatControlPanel::updateButtons(bool is_call_started)
+void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state)
{
+ bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED;
getChildView("end_call_btn_panel")->setVisible( is_call_started);
- getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started);
+ getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel"));
getChildView("call_btn_panel")->setVisible( ! is_call_started);
+
+ getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED);
+
updateCallButton();
}
@@ -135,7 +139,7 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
//call (either p2p, group or ad-hoc) can be already in started state
- updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+ updateButtons(voice_channel->getState());
}
}
@@ -156,6 +160,13 @@ BOOL LLPanelIMControlPanel::postBuild()
childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this));
childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this));
+
+ childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this));
+ childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this));
+ childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this));
+
+ getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2));
+
getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this));
@@ -163,6 +174,79 @@ BOOL LLPanelIMControlPanel::postBuild()
return LLPanelChatControlPanel::postBuild();
}
+void LLPanelIMControlPanel::draw()
+{
+ bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID);
+
+ getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted);
+ getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted);
+
+ if (getChildView("volume_ctrl_panel")->getVisible())
+ {
+
+ bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
+ mute_btn->setValue( is_muted_voice );
+
+ LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
+ volume_slider->setEnabled( !is_muted_voice );
+
+ F32 volume;
+
+ if (is_muted_voice)
+ {
+ // it's clearer to display their volume as zero
+ volume = 0.f;
+ }
+ else
+ {
+ // actual volume
+ volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID);
+ }
+ volume_slider->setValue( (F64)volume );
+ }
+
+ LLPanelChatControlPanel::draw();
+}
+
+void LLPanelIMControlPanel::onClickMuteVolume()
+{
+ // By convention, we only display and toggle voice mutes, not all mutes
+ LLMuteList* mute_list = LLMuteList::getInstance();
+ bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+ if (!is_muted)
+ {
+ mute_list->add(mute, LLMute::flagVoiceChat);
+ }
+ else
+ {
+ mute_list->remove(mute, LLMute::flagVoiceChat);
+ }
+}
+
+void LLPanelIMControlPanel::onClickBlock()
+{
+ LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+
+ LLMuteList::getInstance()->add(mute);
+}
+
+void LLPanelIMControlPanel::onClickUnblock()
+{
+ LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+
+ LLMuteList::getInstance()->remove(mute);
+}
+
+void LLPanelIMControlPanel::onVolumeChange(const LLSD& data)
+{
+ F32 volume = (F32)data.asReal();
+ LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
+}
+
void LLPanelIMControlPanel::onTeleportButtonClicked()
{
LLAvatarActions::offerTeleport(mAvatarID);
@@ -262,6 +346,9 @@ void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& ful
std::string avatar_name = full_name;
getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
+
+ bool is_linden = LLStringUtil::endsWith(full_name, " Linden");
+ getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden);
}
}
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 3bbe24ecb9..bba847b5d4 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -54,7 +54,7 @@ public:
virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
- void updateButtons(bool is_call_started);
+ void updateButtons(LLVoiceChannel::EState state);
// Enables/disables call button depending on voice availability
void updateCallButton();
@@ -94,6 +94,12 @@ private:
void onPayButtonClicked();
void onFocusReceived();
+ void onClickMuteVolume();
+ void onClickBlock();
+ void onClickUnblock();
+ /*virtual*/ void draw();
+ void onVolumeChange(const LLSD& data);
+
LLUUID mAvatarID;
};
diff --git a/indra/newview/llpanellandaudio.cpp b/indra/newview/llpanellandaudio.cpp
index f9730d9b71..e7bdc51b4a 100644
--- a/indra/newview/llpanellandaudio.cpp
+++ b/indra/newview/llpanellandaudio.cpp
@@ -91,6 +91,12 @@ BOOL LLPanelLandAudio::postBuild()
mMusicURLEdit = getChild<LLLineEditor>("music_url");
childSetCommitCallback("music_url", onCommitAny, this);
+ mCheckAVSoundAny = getChild<LLCheckBoxCtrl>("all av sound check");
+ childSetCommitCallback("all av sound check", onCommitAny, this);
+
+ mCheckAVSoundGroup = getChild<LLCheckBoxCtrl>("group av sound check");
+ childSetCommitCallback("group av sound check", onCommitAny, this);
+
return TRUE;
}
@@ -144,6 +150,13 @@ void LLPanelLandAudio::refresh()
mMusicURLEdit->setText(parcel->getMusicURL());
mMusicURLEdit->setEnabled( can_change_media );
+
+ BOOL can_change_av_sounds = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_OPTIONS) && parcel->getHaveNewParcelLimitData();
+ mCheckAVSoundAny->set(parcel->getAllowAnyAVSounds());
+ mCheckAVSoundAny->setEnabled(can_change_av_sounds);
+
+ mCheckAVSoundGroup->set(parcel->getAllowGroupAVSounds() || parcel->getAllowAnyAVSounds()); // On if "Everyone" is on
+ mCheckAVSoundGroup->setEnabled(can_change_av_sounds && !parcel->getAllowAnyAVSounds()); // Enabled if "Everyone" is off
}
}
// static
@@ -164,6 +177,13 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata)
BOOL voice_enabled = self->mCheckParcelEnableVoice->get();
BOOL voice_estate_chan = !self->mCheckParcelVoiceLocal->get();
+ BOOL any_av_sound = self->mCheckAVSoundAny->get();
+ BOOL group_av_sound = TRUE; // If set to "Everyone" then group is checked as well
+ if (!any_av_sound)
+ { // If "Everyone" is off, use the value from the checkbox
+ group_av_sound = self->mCheckAVSoundGroup->get();
+ }
+
// Remove leading/trailing whitespace (common when copying/pasting)
LLStringUtil::trim(music_url);
@@ -172,6 +192,8 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata)
parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan);
parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local);
parcel->setMusicURL(music_url);
+ parcel->setAllowAnyAVSounds(any_av_sound);
+ parcel->setAllowGroupAVSounds(group_av_sound);
// Send current parcel data upstream to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
diff --git a/indra/newview/llpanellandaudio.h b/indra/newview/llpanellandaudio.h
index 4b0953bdc1..32a45100f4 100644
--- a/indra/newview/llpanellandaudio.h
+++ b/indra/newview/llpanellandaudio.h
@@ -52,6 +52,8 @@ private:
LLCheckBoxCtrl* mCheckParcelVoiceLocal;
LLLineEditor* mMusicURLEdit;
LLCheckBoxCtrl* mMusicUrlCheck;
+ LLCheckBoxCtrl* mCheckAVSoundAny;
+ LLCheckBoxCtrl* mCheckAVSoundGroup;
LLSafeHandle<LLParcelSelection>& mParcel;
};
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 80f6862169..a9cc247d1b 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -46,6 +46,7 @@
#include "llfolderviewitem.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
+#include "llinventoryfunctions.h"
#include "lllandmarkactions.h"
#include "llmenubutton.h"
#include "llplacesinventorybridge.h"
@@ -299,7 +300,7 @@ void LLLandmarksPanel::onTeleport()
}
LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
{
listenerp->openItem();
}
@@ -529,7 +530,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
// virtual
void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
{
- llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+ llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
}
@@ -645,7 +646,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI
// Start background fetch, mostly for My Inventory and Library
if (expanded)
{
- const LLUUID &cat_id = inventory_list->getStartFolderID();
+ const LLUUID &cat_id = inventory_list->getRootFolderID();
// Just because the category itself has been fetched, doesn't mean its child folders have.
/*
if (!gInventory.isCategoryComplete(cat_id))
@@ -1414,7 +1415,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin
static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
{
- LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID());
+ LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getRootFolderID());
if (category)
{
return category->getDescendentCount() > 0;
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index d0810d0772..27f341b4f6 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -34,7 +34,6 @@
#include "llmd5.h"
#include "llsecondlifeurls.h"
#include "v4color.h"
-#include "llversionviewer.h"
#include "llappviewer.h"
#include "llbutton.h"
@@ -748,20 +747,12 @@ void LLPanelLogin::loadLoginPage()
LLVersionInfo::getShortVersion().c_str(),
LLVersionInfo::getBuild());
- char* curl_channel ;
+ char* curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);
char* curl_version = curl_escape(version.c_str(), 0);
- if(strcmp(LLVersionInfo::getChannel().c_str(), LL_CHANNEL))
- {
- curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);
- }
- else //if LL_CHANNEL, direct it to "Second Life Beta Viewer".
- {
- curl_channel = curl_escape("Second Life Beta Viewer", 0);
- }
oStr << "&channel=" << curl_channel;
oStr << "&version=" << curl_version;
-
+
curl_free(curl_channel);
curl_free(curl_version);
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index bc4998dd0c..1920cc2940 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1,6 +1,6 @@
/**
- * @file llsidepanelmaininventory.cpp
- * @brief Implementation of llsidepanelmaininventory.
+ * @file llpanelmaininventory.cpp
+ * @brief Implementation of llpanelmaininventory.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -95,8 +95,8 @@ private:
/// LLPanelMainInventory
///----------------------------------------------------------------------------
-LLPanelMainInventory::LLPanelMainInventory()
- : LLPanel(),
+LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
+ : LLPanel(p),
mActivePanel(NULL),
mSavedFolderState(NULL),
mFilterText(""),
@@ -193,6 +193,9 @@ BOOL LLPanelMainInventory::postBuild()
mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+ // Trigger callback for focus received so we can deselect items in inbox/outbox
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
+
return TRUE;
}
@@ -572,6 +575,27 @@ void LLPanelMainInventory::updateItemcountText()
getChild<LLUICtrl>("ItemcountText")->setValue(text);
}
+void LLPanelMainInventory::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ LLInventoryPanel * inbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+
+ if (inbox_panel)
+ {
+ inbox_panel->clearSelection();
+ }
+
+ LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+ if (outbox_panel)
+ {
+ outbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+}
+
void LLPanelMainInventory::setFilterTextFromFilter()
{
mFilterText = mActivePanel->getFilter()->getFilterText();
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 2b2ee1c0c9..899931aa89 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -57,7 +57,7 @@ class LLPanelMainInventory : public LLPanel, LLInventoryObserver
public:
friend class LLFloaterInventoryFinder;
- LLPanelMainInventory();
+ LLPanelMainInventory(const LLPanel::Params& p = getDefaultParams());
~LLPanelMainInventory();
BOOL postBuild();
@@ -114,6 +114,8 @@ protected:
bool isSaveTextureEnabled(const LLSD& userdata);
void updateItemcountText();
+ void onFocusReceived();
+
private:
LLFloaterInventoryFinder* getFinder();
diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp
new file mode 100644
index 0000000000..af74f8f261
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinbox.cpp
@@ -0,0 +1,248 @@
+/**
+ * @file llpanelmarketplaceinbox.cpp
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+#include "llsidepanelinventory.h"
+
+
+#define SUPPORTING_FRESH_ITEM_COUNT 0
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox");
+
+const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>();
+}
+
+// protected
+LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
+ : LLPanel(p)
+ , mInventoryPanel(NULL)
+{
+}
+
+LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceInbox::postBuild()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this));
+
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
+
+ return TRUE;
+}
+
+void LLPanelMarketplaceInbox::onSelectionChange()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->updateVerbs();
+}
+
+
+void LLPanelMarketplaceInbox::handleLoginComplete()
+{
+ // Set us up as the class to drive the badge value for the sidebar_inventory button
+ LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this);
+}
+
+void LLPanelMarketplaceInbox::setupInventoryPanel()
+{
+ LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder");
+ LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent();
+
+ mInventoryPanel =
+ LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml",
+ inbox_inventory_parent,
+ LLInventoryPanel::child_registry_t::instance());
+
+ // Reshape the inventory to the proper size
+ LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect();
+ mInventoryPanel->setShape(inventory_placeholder_rect);
+
+ // Set the sort order newest to oldest, and a selection change callback
+ mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));
+
+ // Set up the note to display when the inbox is empty
+ mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems");
+
+ // Hide the placeholder text
+ inbox_inventory_placeholder->setVisible(FALSE);
+}
+
+void LLPanelMarketplaceInbox::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ if (sidepanel_inventory)
+ {
+ LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+ if (inv_panel)
+ {
+ inv_panel->clearSelection();
+ }
+
+ LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+ if (outbox_panel)
+ {
+ outbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+ }
+}
+
+BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
+{
+ *accept = ACCEPT_NO;
+ return TRUE;
+}
+
+U32 LLPanelMarketplaceInbox::getFreshItemCount() const
+{
+#if SUPPORTING_FRESH_ITEM_COUNT
+
+ //
+ // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably
+ // will return "2" for the Inventory and LIBRARY top-levels when that happens.
+ //
+
+ U32 fresh_item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin();
+ LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd();
+
+ for (; folders_it != folders_end; ++folders_it)
+ {
+ const LLFolderViewFolder * folder = *folders_it;
+
+ // TODO: Replace this check with new "fresh" flag
+ if (folder->getCreationDate() > 1500)
+ {
+ fresh_item_count++;
+ }
+ }
+ }
+ }
+
+ return fresh_item_count;
+#else
+ return getTotalItemCount();
+#endif
+}
+
+U32 LLPanelMarketplaceInbox::getTotalItemCount() const
+{
+ U32 item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ item_count += inbox_folder->getFoldersCount();
+ }
+ }
+
+ return item_count;
+}
+
+std::string LLPanelMarketplaceInbox::getBadgeString() const
+{
+ std::string item_count_str("");
+
+ // If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel
+ if (getParent()->getVisible() &&
+ (LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")))
+ {
+ U32 item_count = getFreshItemCount();
+
+ if (item_count)
+ {
+ item_count_str = llformat("%d", item_count);
+ }
+ }
+
+ return item_count_str;
+}
+
+void LLPanelMarketplaceInbox::draw()
+{
+ U32 item_count = getTotalItemCount();
+
+ LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
+
+ if (item_count > 0)
+ {
+ std::string item_count_str = llformat("%d", item_count);
+
+ LLStringUtil::format_map_t args;
+ args["[NUM]"] = item_count_str;
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
+
+#if SUPPORTING_FRESH_ITEM_COUNT
+ // set green text to fresh item count
+ U32 fresh_item_count = getFreshItemCount();
+ fresh_new_count_view->setVisible((fresh_item_count > 0));
+
+ if (fresh_item_count > 0)
+ {
+ getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
+ }
+#else
+ fresh_new_count_view->setVisible(FALSE);
+#endif
+ }
+ else
+ {
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
+
+ fresh_new_count_view->setVisible(FALSE);
+ }
+
+ LLPanel::draw();
+}
diff --git a/indra/newview/llpanelmarketplaceinbox.h b/indra/newview/llpanelmarketplaceinbox.h
new file mode 100644
index 0000000000..4ecea29304
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinbox.h
@@ -0,0 +1,78 @@
+/**
+ * @file llpanelmarketplaceinbox.h
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMARKETPLACEINBOX_H
+#define LL_LLPANELMARKETPLACEINBOX_H
+
+#include "llpanel.h"
+#include "llsidetray.h"
+
+class LLInventoryPanel;
+
+class LLPanelMarketplaceInbox : public LLPanel, public LLSideTrayTabBadgeDriver
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Params() {}
+ };
+
+ LOG_CLASS(LLPanelMarketplaceInbox);
+
+ // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+ static const LLPanelMarketplaceInbox::Params& getDefaultParams();
+
+ LLPanelMarketplaceInbox(const Params& p = getDefaultParams());
+ ~LLPanelMarketplaceInbox();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg);
+
+ /*virtual*/ void draw();
+
+ void setupInventoryPanel();
+
+ U32 getFreshItemCount() const;
+ U32 getTotalItemCount() const;
+
+ std::string getBadgeString() const;
+
+private:
+ void handleLoginComplete();
+
+ void onSelectionChange();
+
+ void onFocusReceived();
+
+private:
+ LLInventoryPanel* mInventoryPanel;
+};
+
+
+#endif //LL_LLPANELMARKETPLACEINBOX_H
+
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp
new file mode 100644
index 0000000000..b644f0e5cb
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp
@@ -0,0 +1,167 @@
+/**
+ * @file llpanelmarketplaceinboxinventory.cpp
+ * @brief LLInboxInventoryPanel class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinboxinventory.h"
+
+#include "llfolderview.h"
+#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llpanellandmarks.h"
+#include "llplacesinventorybridge.h"
+#include "llviewerfoldertype.h"
+
+
+//
+// statics
+//
+
+static LLDefaultChildRegistry::Register<LLInboxInventoryPanel> r1("inbox_inventory_panel");
+static LLDefaultChildRegistry::Register<LLInboxFolderViewFolder> r2("inbox_folder_view_folder");
+
+
+//
+// LLInboxInventoryPanel Implementation
+//
+
+LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p)
+ : LLInventoryPanel(p)
+{
+}
+
+LLInboxInventoryPanel::~LLInboxInventoryPanel()
+{
+}
+
+// virtual
+void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
+{
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+
+ LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false);
+
+ // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+ if (root_id.isNull())
+ {
+ std::string start_folder_name(params.start_folder());
+
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+
+ gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+ {
+ LLInventoryCategory* cat = *cat_it;
+
+ if (cat->getName() == start_folder_name)
+ {
+ root_id = cat->getUUID();
+ break;
+ }
+ }
+ }
+
+ if (root_id == LLUUID::null)
+ {
+ llwarns << "No category found that matches inbox inventory panel start_folder: " << start_folder_name << llendl;
+ }
+ }
+ // leslie -- end temporary HACK
+
+ if (root_id == LLUUID::null)
+ {
+ llwarns << "Inbox inventory panel has no root folder!" << llendl;
+ root_id = LLUUID::generateNewID();
+ }
+
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+ LLAssetType::AT_CATEGORY,
+ LLInventoryType::IT_CATEGORY,
+ this,
+ NULL,
+ root_id);
+
+ mFolderRoot = createFolderView(new_listener, params.use_label_suffix());
+}
+
+LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
+{
+ LLInboxFolderViewFolder::Params params;
+
+ params.name = bridge->getDisplayName();
+ params.icon = bridge->getIcon();
+ params.icon_open = bridge->getOpenIcon();
+
+ if (mShowItemLinkOverlays) // if false, then links show up just like normal items
+ {
+ params.icon_overlay = LLUI::getUIImage("Inv_Link");
+ }
+
+ params.root = mFolderRoot;
+ params.listener = bridge;
+ params.tool_tip = params.name;
+
+ return LLUICtrlFactory::create<LLInboxFolderViewFolder>(params);
+}
+
+
+//
+// LLInboxFolderViewFolder Implementation
+//
+
+LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p)
+ : LLFolderViewFolder(p)
+ , LLBadgeOwner(getHandle())
+ , mFresh(false)
+{
+ initBadgeParams(p.new_badge());
+}
+
+LLInboxFolderViewFolder::~LLInboxFolderViewFolder()
+{
+}
+
+// virtual
+void LLInboxFolderViewFolder::draw()
+{
+ if (!badgeHasParent())
+ {
+ addBadgeToParentPanel();
+ }
+
+ setBadgeVisibility(mFresh);
+
+ LLFolderViewFolder::draw();
+}
+
+
+// eof
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h
new file mode 100644
index 0000000000..8f198c41c1
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinboxinventory.h
@@ -0,0 +1,77 @@
+/**
+ * @file llpanelmarketplaceinboxinventory.h
+ * @brief LLInboxInventoryPanel class declaration
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_INBOXINVENTORYPANEL_H
+#define LL_INBOXINVENTORYPANEL_H
+
+
+#include "llbadgeowner.h"
+#include "llinventorypanel.h"
+#include "llfolderviewitem.h"
+
+class LLInboxInventoryPanel : public LLInventoryPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {
+ Params() {}
+ };
+
+ LLInboxInventoryPanel(const Params& p);
+ ~LLInboxInventoryPanel();
+
+ // virtual
+ void buildFolderView(const LLInventoryPanel::Params& params);
+
+ // virtual
+ class LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge);
+};
+
+
+class LLInboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>
+ {
+ Optional<LLBadge::Params> new_badge;
+
+ Params()
+ : new_badge("new_badge")
+ {
+ }
+ };
+
+ LLInboxFolderViewFolder(const Params& p);
+ ~LLInboxFolderViewFolder();
+
+ void draw();
+
+protected:
+ bool mFresh;
+};
+
+
+#endif //LL_INBOXINVENTORYPANEL_H
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
new file mode 100644
index 0000000000..74d0de3b30
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -0,0 +1,209 @@
+/**
+ * @file llpanelmarketplaceoutbox.cpp
+ * @brief Panel for marketplace outbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceoutbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llinventorypanel.h"
+#include "llloadingindicator.h"
+#include "llpanelmarketplaceinbox.h"
+#include "llsidepanelinventory.h"
+#include "llsidetray.h"
+#include "lltimer.h"
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
+
+const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>();
+}
+
+// protected
+LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p)
+ : LLPanel(p)
+ , mInventoryPanel(NULL)
+ , mSyncButton(NULL)
+ , mSyncIndicator(NULL)
+ , mSyncInProgress(false)
+{
+}
+
+LLPanelMarketplaceOutbox::~LLPanelMarketplaceOutbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceOutbox::postBuild()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceOutbox::handleLoginComplete, this));
+
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceOutbox::onFocusReceived, this));
+
+ return TRUE;
+}
+
+void LLPanelMarketplaceOutbox::handleLoginComplete()
+{
+ mSyncButton = getChild<LLButton>("outbox_sync_btn");
+ mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this));
+ mSyncButton->setEnabled(!isOutboxEmpty());
+
+ mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator");
+}
+
+void LLPanelMarketplaceOutbox::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ if (sidepanel_inventory)
+ {
+ LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+ if (inv_panel)
+ {
+ inv_panel->clearSelection();
+ }
+
+ LLInventoryPanel * inbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+
+ if (inbox_panel)
+ {
+ inbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+ }
+}
+
+void LLPanelMarketplaceOutbox::onSelectionChange()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->updateVerbs();
+}
+
+void LLPanelMarketplaceOutbox::setupInventoryPanel()
+{
+ LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder");
+ LLView * outbox_inventory_parent = outbox_inventory_placeholder->getParent();
+
+ mInventoryPanel =
+ LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml",
+ outbox_inventory_parent,
+ LLInventoryPanel::child_registry_t::instance());
+
+ // Reshape the inventory to the proper size
+ LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect();
+ mInventoryPanel->setShape(inventory_placeholder_rect);
+
+ // Set the sort order newest to oldest, and a selection change callback
+ mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this));
+
+ // Set up the note to display when the outbox is empty
+ mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems");
+
+ // Hide the placeholder text
+ outbox_inventory_placeholder->setVisible(FALSE);
+}
+
+bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
+{
+ // TODO: Check for contents of outbox
+
+ return false;
+}
+
+bool LLPanelMarketplaceOutbox::isSyncInProgress() const
+{
+ return mSyncInProgress;
+}
+
+
+std::string gTimeDelayDebugFunc = "";
+
+void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
+{
+ waitForEventOn(self, "mainloop");
+
+ LLTimer delayTimer;
+ delayTimer.reset();
+ delayTimer.setTimerExpirySec(5.0f);
+
+ while (!delayTimer.hasExpired())
+ {
+ waitForEventOn(self, "mainloop");
+ }
+
+ outboxPanel->onSyncComplete();
+
+ gTimeDelayDebugFunc = "";
+}
+
+void LLPanelMarketplaceOutbox::onSyncButtonClicked()
+{
+ // TODO: Actually trigger sync to marketplace
+
+ mSyncInProgress = true;
+ updateSyncButtonStatus();
+
+ // Set a timer (for testing only)
+
+ gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
+}
+
+void LLPanelMarketplaceOutbox::onSyncComplete()
+{
+ mSyncInProgress = false;
+
+ updateSyncButtonStatus();
+}
+
+void LLPanelMarketplaceOutbox::updateSyncButtonStatus()
+{
+ if (isSyncInProgress())
+ {
+ mSyncButton->setVisible(false);
+
+ mSyncIndicator->setVisible(true);
+ mSyncIndicator->reset();
+ mSyncIndicator->start();
+ }
+ else
+ {
+ mSyncIndicator->stop();
+ mSyncIndicator->setVisible(false);
+
+ mSyncButton->setVisible(true);
+ mSyncButton->setEnabled(!isOutboxEmpty());
+ }
+}
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
new file mode 100644
index 0000000000..1b502127ef
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceoutbox.h
@@ -0,0 +1,82 @@
+/**
+ * @file llpanelmarketplaceoutbox.h
+ * @brief Panel for marketplace outbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMARKETPLACEOUTBOX_H
+#define LL_LLPANELMARKETPLACEOUTBOX_H
+
+#include "llpanel.h"
+
+
+class LLButton;
+class LLInventoryPanel;
+class LLLoadingIndicator;
+
+
+class LLPanelMarketplaceOutbox : public LLPanel
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Params() {}
+ };
+
+ LOG_CLASS(LLPanelMarketplaceOutbox);
+
+ // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+ static const LLPanelMarketplaceOutbox::Params& getDefaultParams();
+
+ LLPanelMarketplaceOutbox(const Params& p = getDefaultParams());
+ ~LLPanelMarketplaceOutbox();
+
+ /*virtual*/ BOOL postBuild();
+
+ void setupInventoryPanel();
+
+ bool isOutboxEmpty() const;
+ bool isSyncInProgress() const;
+
+ void onSyncComplete();
+
+protected:
+ void onSyncButtonClicked();
+ void updateSyncButtonStatus();
+
+ void handleLoginComplete();
+ void onFocusReceived();
+ void onSelectionChange();
+
+private:
+ LLInventoryPanel * mInventoryPanel;
+
+ LLButton * mSyncButton;
+ LLLoadingIndicator * mSyncIndicator;
+ bool mSyncInProgress;
+};
+
+
+#endif //LL_LLPANELMARKETPLACEOUTBOX_H
+
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 64af6c2157..c222bbb191 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -33,16 +33,15 @@
#include "lleconomy.h"
#include "llerror.h"
#include "llfontgl.h"
-#include "llmaterialtable.h"
#include "llpermissionsflags.h"
#include "llstring.h"
#include "llvolume.h"
-#include "material_codes.h"
#include "m3math.h"
// project includes
#include "llagent.h"
#include "llbutton.h"
+#include "llcalc.h"
#include "llcheckboxctrl.h"
#include "llcolorswatch.h"
#include "llcombobox.h"
@@ -57,7 +56,6 @@
#include "lltool.h"
#include "lltoolcomp.h"
#include "lltoolmgr.h"
-#include "lltrans.h"
#include "llui.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
@@ -101,17 +99,6 @@ BOOL LLPanelObject::postBuild()
{
setMouseOpaque(FALSE);
- std::map<std::string, std::string> material_name_map;
- material_name_map["Stone"]= LLTrans::getString("Stone");
- material_name_map["Metal"]= LLTrans::getString("Metal");
- material_name_map["Glass"]= LLTrans::getString("Glass");
- material_name_map["Wood"]= LLTrans::getString("Wood");
- material_name_map["Flesh"]= LLTrans::getString("Flesh");
- material_name_map["Plastic"]= LLTrans::getString("Plastic");
- material_name_map["Rubber"]= LLTrans::getString("Rubber");
- material_name_map["Light"]= LLTrans::getString("Light");
-
- LLMaterialTable::basic.initTableTransNames(material_name_map);
//--------------------------------------------------------
// Top
//--------------------------------------------------------
@@ -166,22 +153,6 @@ BOOL LLPanelObject::postBuild()
//--------------------------------------------------------
- // material type popup
- mComboMaterial = getChild<LLComboBox>("material");
- childSetCommitCallback("material",onCommitMaterial,this);
- mComboMaterial->removeall();
-
- for (LLMaterialTable::info_list_t::iterator iter = LLMaterialTable::basic.mMaterialInfoList.begin();
- iter != LLMaterialTable::basic.mMaterialInfoList.end(); ++iter)
- {
- LLMaterialInfo* minfop = *iter;
- if (minfop->mMCode != LL_MCODE_LIGHT)
- {
- mComboMaterial->add(minfop->mName);
- }
- }
- mComboMaterialItemCount = mComboMaterial->getItemCount();
-
// Base Type
mComboBaseType = getChild<LLComboBox>("comboBaseType");
childSetCommitCallback("comboBaseType",onCommitParametric,this);
@@ -309,7 +280,6 @@ BOOL LLPanelObject::postBuild()
LLPanelObject::LLPanelObject()
: LLPanel(),
- mComboMaterialItemCount(0),
mIsPhysical(FALSE),
mIsTemporary(FALSE),
mIsPhantom(FALSE),
@@ -349,6 +319,8 @@ void LLPanelObject::getState( )
}
}
+ LLCalc* calcp = LLCalc::getInstance();
+
LLVOVolume *volobjp = NULL;
if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
@@ -365,6 +337,7 @@ void LLPanelObject::getState( )
// Disable all text input fields
clearCtrls();
+ calcp->clearAllVariables();
return;
}
@@ -391,12 +364,18 @@ void LLPanelObject::getState( )
mCtrlPosX->set( vec.mV[VX] );
mCtrlPosY->set( vec.mV[VY] );
mCtrlPosZ->set( vec.mV[VZ] );
+ calcp->setVar(LLCalc::X_POS, vec.mV[VX]);
+ calcp->setVar(LLCalc::Y_POS, vec.mV[VY]);
+ calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]);
}
else
{
mCtrlPosX->clear();
mCtrlPosY->clear();
mCtrlPosZ->clear();
+ calcp->clearVar(LLCalc::X_POS);
+ calcp->clearVar(LLCalc::Y_POS);
+ calcp->clearVar(LLCalc::Z_POS);
}
@@ -411,12 +390,18 @@ void LLPanelObject::getState( )
mCtrlScaleX->set( vec.mV[VX] );
mCtrlScaleY->set( vec.mV[VY] );
mCtrlScaleZ->set( vec.mV[VZ] );
+ calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]);
+ calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]);
+ calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]);
}
else
{
mCtrlScaleX->clear();
mCtrlScaleY->clear();
mCtrlScaleZ->clear();
+ calcp->setVar(LLCalc::X_SCALE, 0.f);
+ calcp->setVar(LLCalc::Y_SCALE, 0.f);
+ calcp->setVar(LLCalc::Z_SCALE, 0.f);
}
mLabelSize->setEnabled( enable_scale );
@@ -436,12 +421,18 @@ void LLPanelObject::getState( )
mCtrlRotX->set( mCurEulerDegrees.mV[VX] );
mCtrlRotY->set( mCurEulerDegrees.mV[VY] );
mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] );
+ calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]);
+ calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]);
+ calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]);
}
else
{
mCtrlRotX->clear();
mCtrlRotY->clear();
mCtrlRotZ->clear();
+ calcp->clearVar(LLCalc::X_ROT);
+ calcp->clearVar(LLCalc::Y_ROT);
+ calcp->clearVar(LLCalc::Z_ROT);
}
mLabelRotation->setEnabled( enable_rotate );
@@ -527,43 +518,6 @@ void LLPanelObject::getState( )
mCheckCastShadows->setEnabled( roots_selected==1 && editable );
#endif
- // Update material part
- // slightly inefficient - materials are unique per object, not per TE
- U8 material_code = 0;
- struct f : public LLSelectedTEGetFunctor<U8>
- {
- U8 get(LLViewerObject* object, S32 te)
- {
- return object->getMaterial();
- }
- } func;
- bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code );
- std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
- if (editable && single_volume && material_same)
- {
- mComboMaterial->setEnabled( TRUE );
- if (material_code == LL_MCODE_LIGHT)
- {
- if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
- {
- mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
- }
- mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
- }
- else
- {
- if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
- {
- mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
- }
-
- mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
- }
- }
- else
- {
- mComboMaterial->setEnabled( FALSE );
- }
//----------------------------------------------------------------------------
S32 selected_item = MI_BOX;
@@ -693,9 +647,9 @@ void LLPanelObject::getState( )
F32 end_t = volume_params.getEndT();
// Hollowness
- F32 hollow = volume_params.getHollow();
- mSpinHollow->set( 100.f * hollow );
-
+ F32 hollow = 100.f * volume_params.getHollow();
+ mSpinHollow->set( hollow );
+ calcp->setVar(LLCalc::HOLLOW, hollow);
// All hollow objects allow a shape to be selected.
if (hollow > 0.f)
{
@@ -747,6 +701,10 @@ void LLPanelObject::getState( )
mSpinCutEnd ->set( cut_end );
mCtrlPathBegin ->set( adv_cut_begin );
mCtrlPathEnd ->set( adv_cut_end );
+ calcp->setVar(LLCalc::CUT_BEGIN, cut_begin);
+ calcp->setVar(LLCalc::CUT_END, cut_end);
+ calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin);
+ calcp->setVar(LLCalc::PATH_END, adv_cut_end);
// Twist
F32 twist = volume_params.getTwist();
@@ -765,18 +723,24 @@ void LLPanelObject::getState( )
mSpinTwist ->set( twist );
mSpinTwistBegin ->set( twist_begin );
+ calcp->setVar(LLCalc::TWIST_END, twist);
+ calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin);
// Shear
F32 shear_x = volume_params.getShearX();
F32 shear_y = volume_params.getShearY();
mSpinShearX->set( shear_x );
mSpinShearY->set( shear_y );
+ calcp->setVar(LLCalc::X_SHEAR, shear_x);
+ calcp->setVar(LLCalc::Y_SHEAR, shear_y);
// Taper
F32 taper_x = volume_params.getTaperX();
F32 taper_y = volume_params.getTaperY();
mSpinTaperX->set( taper_x );
mSpinTaperY->set( taper_y );
+ calcp->setVar(LLCalc::X_TAPER, taper_x);
+ calcp->setVar(LLCalc::Y_TAPER, taper_y);
// Radius offset.
F32 radius_offset = volume_params.getRadiusOffset();
@@ -806,10 +770,12 @@ void LLPanelObject::getState( )
}
}
mSpinRadiusOffset->set( radius_offset);
+ calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset);
// Revolutions
F32 revolutions = volume_params.getRevolutions();
mSpinRevolutions->set( revolutions );
+ calcp->setVar(LLCalc::REVOLUTIONS, revolutions);
// Skew
F32 skew = volume_params.getSkew();
@@ -834,6 +800,7 @@ void LLPanelObject::getState( )
}
}
mSpinSkew->set( skew );
+ calcp->setVar(LLCalc::SKEW, skew);
}
// Compute control visibility, label names, and twist range.
@@ -937,6 +904,8 @@ void LLPanelObject::getState( )
case MI_RING:
mSpinScaleX->set( scale_x );
mSpinScaleY->set( scale_y );
+ calcp->setVar(LLCalc::X_HOLE, scale_x);
+ calcp->setVar(LLCalc::Y_HOLE, scale_y);
mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE);
mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X);
mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE);
@@ -951,6 +920,14 @@ void LLPanelObject::getState( )
mSpinScaleX->setMaxValue(1.f);
mSpinScaleY->setMinValue(-1.f);
mSpinScaleY->setMaxValue(1.f);
+
+ // Torus' Hole Size is Box/Cyl/Prism's Taper
+ calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x);
+ calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y);
+
+ // Box/Cyl/Prism have no hole size
+ calcp->setVar(LLCalc::X_HOLE, 0.f);
+ calcp->setVar(LLCalc::Y_HOLE, 0.f);
}
break;
}
@@ -1095,12 +1072,9 @@ void LLPanelObject::getState( )
mCtrlSculptTexture->setVisible(sculpt_texture_visible);
mLabelSculptType->setVisible(sculpt_texture_visible);
mCtrlSculptType->setVisible(sculpt_texture_visible);
- mCtrlSculptMirror->setVisible(sculpt_texture_visible);
- mCtrlSculptInvert->setVisible(sculpt_texture_visible);
// sculpt texture
-
if (selected_item == MI_SCULPT)
{
@@ -1145,7 +1119,7 @@ void LLPanelObject::getState( )
if (mCtrlSculptMirror)
{
mCtrlSculptMirror->set(sculpt_mirror);
- mCtrlSculptMirror->setEnabled(editable);
+ mCtrlSculptMirror->setEnabled(editable && !isMesh);
}
if (mCtrlSculptInvert)
@@ -1166,6 +1140,9 @@ void LLPanelObject::getState( )
mSculptTextureRevert = LLUUID::null;
}
+ mCtrlSculptMirror->setVisible(sculpt_texture_visible && !isMesh);
+ mCtrlSculptInvert->setVisible(sculpt_texture_visible && !isMesh);
+
//----------------------------------------------------------------------------
mObject = objectp;
@@ -1245,25 +1222,6 @@ void LLPanelObject::sendCastShadows()
}
// static
-void LLPanelObject::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
-{
- //LLPanelObject* self = (LLPanelObject*) userdata;
- LLComboBox* box = (LLComboBox*) ctrl;
-
- if (box)
- {
- // apply the currently selected material to the object
- const std::string& material_name = box->getSimple();
- std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
- if (material_name != LEGACY_FULLBRIGHT_DESC)
- {
- U8 material_code = LLMaterialTable::basic.getMCode(material_name);
- LLSelectMgr::getInstance()->selectionSetMaterial(material_code);
- }
- }
-}
-
-// static
void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata )
{
LLPanelObject* self = (LLPanelObject*) userdata;
@@ -1827,25 +1785,11 @@ void LLPanelObject::refresh()
mRootObject = NULL;
}
- bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&
- gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty();
-
F32 max_scale = get_default_max_prim_scale(LLPickInfo::isFlora(mObject));
getChild<LLSpinCtrl>("Scale X")->setMaxValue(max_scale);
getChild<LLSpinCtrl>("Scale Y")->setMaxValue(max_scale);
getChild<LLSpinCtrl>("Scale Z")->setMaxValue(max_scale);
-
- BOOL found = mCtrlSculptType->itemExists("Mesh");
- if (enable_mesh && !found)
- {
- mCtrlSculptType->add("Mesh");
- }
- else if (!enable_mesh && found)
- {
- mCtrlSculptType->remove("Mesh");
- }
}
@@ -1937,7 +1881,6 @@ void LLPanelObject::clearCtrls()
mCheckCastShadows->set(FALSE);
mCheckCastShadows->setEnabled( FALSE );
#endif
- mComboMaterial ->setEnabled( FALSE );
// Disable text labels
mLabelPosition ->setEnabled( FALSE );
mLabelSize ->setEnabled( FALSE );
diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h
index e2f2a4400d..475dfdaedb 100644
--- a/indra/newview/llpanelobject.h
+++ b/indra/newview/llpanelobject.h
@@ -66,7 +66,6 @@ public:
static void onCommitPhantom( LLUICtrl* ctrl, void* userdata);
static void onCommitCastShadows( LLUICtrl* ctrl, void* userdata);
static void onCommitPhysics( LLUICtrl* ctrl, void* userdata);
- static void onCommitMaterial( LLUICtrl* ctrl, void* userdata);
static void onCommitParametric(LLUICtrl* ctrl, void* userdata);
@@ -94,10 +93,6 @@ protected:
void getVolumeParams(LLVolumeParams& volume_params);
protected:
- S32 mComboMaterialItemCount;
-
- LLComboBox* mComboMaterial;
-
// Per-object options
LLComboBox* mComboBaseType;
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index bfe6cab52f..e3b61f695a 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -44,6 +44,7 @@
#include "llcallbacklist.h"
#include "llbuycurrencyhtml.h"
#include "llfloaterreg.h"
+#include "llfolderview.h"
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfilter.h"
@@ -58,8 +59,10 @@
#include "llselectmgr.h"
#include "llsidetray.h"
#include "llstatusbar.h"
+#include "lltooldraganddrop.h"
#include "lltrans.h"
#include "llviewerassettype.h"
+#include "llviewerinventory.h"
#include "llviewerregion.h"
#include "llviewerobjectlist.h"
#include "llviewermessage.h"
@@ -761,7 +764,7 @@ void LLTaskCategoryBridge::openItem()
BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
//llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
- if(mPanel)
+ if(mPanel && mUUID.notNull())
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
@@ -1349,79 +1352,81 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
LLTaskInvFVBridge* new_bridge = NULL;
const LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(object);
const U32 itemflags = ( NULL == item ? 0 : item->getFlags() );
- LLAssetType::EType type = object->getType();
+ LLAssetType::EType type = object ? object->getType() : LLAssetType::AT_CATEGORY;
+ LLUUID object_id = object ? object->getUUID() : LLUUID::null;
+ std::string object_name = object ? object->getName() : std::string();
switch(type)
{
case LLAssetType::AT_TEXTURE:
new_bridge = new LLTaskTextureBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_SOUND:
new_bridge = new LLTaskSoundBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_LANDMARK:
new_bridge = new LLTaskLandmarkBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_CALLINGCARD:
new_bridge = new LLTaskCallingCardBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_SCRIPT:
// OLD SCRIPTS DEPRECATED - JC
llwarns << "Old script" << llendl;
//new_bridge = new LLTaskOldScriptBridge(panel,
- // object->getUUID(),
- // object->getName());
+ // object_id,
+ // object_name);
break;
case LLAssetType::AT_OBJECT:
new_bridge = new LLTaskObjectBridge(panel,
- object->getUUID(),
- object->getName(),
+ object_id,
+ object_name,
itemflags);
break;
case LLAssetType::AT_NOTECARD:
new_bridge = new LLTaskNotecardBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_ANIMATION:
new_bridge = new LLTaskAnimationBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_GESTURE:
new_bridge = new LLTaskGestureBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
new_bridge = new LLTaskWearableBridge(panel,
- object->getUUID(),
- object->getName(),
+ object_id,
+ object_name,
itemflags);
break;
case LLAssetType::AT_CATEGORY:
new_bridge = new LLTaskCategoryBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_LSL_TEXT:
new_bridge = new LLTaskLSLBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_MESH:
new_bridge = new LLTaskMeshBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
default:
llinfos << "Unhandled inventory type (llassetstorage.h): "
@@ -1521,6 +1526,7 @@ void LLPanelObjectInventory::reset()
p.task_id = getTaskUUID();
p.parent_panel = this;
p.tool_tip= LLTrans::getString("PanelContentsTooltip");
+ p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL);
mFolders = LLUICtrlFactory::create<LLFolderView>(p);
// this ensures that we never say "searching..." or "no items found"
mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 62f582c343..35e2e96bab 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -36,7 +36,7 @@
#include "lloutfitobserver.h"
#include "llcofwearables.h"
#include "llfilteredwearablelist.h"
-#include "llfolderviewitem.h"
+#include "llfolderview.h"
#include "llinventory.h"
#include "llinventoryitemslist.h"
#include "llviewercontrol.h"
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index ddce83c616..ddce83c616 100644..100755
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 29db110523..29db110523 100644..100755
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 68ecb0165c..1e9ce58237 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -70,6 +70,8 @@ static std::string icon_scripts;
static std::string icon_scripts_no;
static std::string icon_damage;
static std::string icon_damage_no;
+static std::string icon_see_avs_on;
+static std::string icon_see_avs_off;
LLPanelPlaceProfile::LLPanelPlaceProfile()
: LLPanelPlaceInfo(),
@@ -114,6 +116,8 @@ BOOL LLPanelPlaceProfile::postBuild()
mScriptsText = getChild<LLTextBox>("scripts_value");
mDamageIcon = getChild<LLIconCtrl>("damage_icon");
mDamageText = getChild<LLTextBox>("damage_value");
+ mSeeAVsIcon = getChild<LLIconCtrl>("see_avatars_icon");
+ mSeeAVsText = getChild<LLTextBox>("see_avatars_value");
mRegionNameText = getChild<LLTextBox>("region_name");
mRegionTypeText = getChild<LLTextBox>("region_type");
@@ -153,6 +157,8 @@ BOOL LLPanelPlaceProfile::postBuild()
icon_scripts_no = getString("icon_ScriptsNo");
icon_damage = getString("icon_Damage");
icon_damage_no = getString("icon_DamageNo");
+ icon_see_avs_on = getString("icon_SeeAVs_On");
+ icon_see_avs_off = getString("icon_SeeAVs_Off");
return TRUE;
}
@@ -182,6 +188,8 @@ void LLPanelPlaceProfile::resetLocation()
mScriptsText->setText(loading);
mDamageIcon->setValue(loading);
mDamageText->setText(loading);
+ mSeeAVsIcon->setValue(loading);
+ mSeeAVsText->setText(loading);
mRegionNameText->setValue(loading);
mRegionTypeText->setValue(loading);
@@ -414,6 +422,17 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
mDamageText->setText(off);
}
+ if (parcel->getSeeAVs())
+ {
+ mSeeAVsIcon->setValue(icon_see_avs_on);
+ mSeeAVsText->setText(on);
+ }
+ else
+ {
+ mSeeAVsIcon->setValue(icon_see_avs_off);
+ mSeeAVsText->setText(off);
+ }
+
mRegionNameText->setText(region->getName());
mRegionTypeText->setText(region->getSimProductName());
diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h
index f28b3b3832..a33fc12ce4 100644
--- a/indra/newview/llpanelplaceprofile.h
+++ b/indra/newview/llpanelplaceprofile.h
@@ -91,6 +91,8 @@ private:
LLTextBox* mScriptsText;
LLIconCtrl* mDamageIcon;
LLTextBox* mDamageText;
+ LLIconCtrl* mSeeAVsIcon;
+ LLTextBox* mSeeAVsText;
LLTextBox* mRegionNameText;
LLTextBox* mRegionTypeText;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 46262832dc..1e510a2d7b 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -584,6 +584,13 @@ void LLPanelPlaces::onTeleportButtonClicked()
{
if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
+ if (mItem.isNull())
+ {
+ llwarns << "NULL landmark item" << llendl;
+ llassert(mItem.notNull());
+ return;
+ }
+
LLSD payload;
payload["asset_id"] = mItem->getAssetUUID();
LLSD args;
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index fd5c3362bb..fd5c3362bb 100644..100755
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index fca359f51e..fca359f51e 100644..100755
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp
index 30949f8f02..7087541fc8 100644
--- a/indra/newview/llpaneltopinfobar.cpp
+++ b/indra/newview/llpaneltopinfobar.cpp
@@ -102,6 +102,7 @@ void LLPanelTopInfoBar::initParcelIcons()
mParcelIcon[BUILD_ICON] = getChild<LLIconCtrl>("build_icon");
mParcelIcon[SCRIPTS_ICON] = getChild<LLIconCtrl>("scripts_icon");
mParcelIcon[DAMAGE_ICON] = getChild<LLIconCtrl>("damage_icon");
+ mParcelIcon[SEE_AVATARS_ICON] = getChild<LLIconCtrl>("see_avatars_icon");
mParcelIcon[VOICE_ICON]->setToolTip(LLTrans::getString("LocationCtrlVoiceTooltip"));
mParcelIcon[FLY_ICON]->setToolTip(LLTrans::getString("LocationCtrlFlyTooltip"));
@@ -109,6 +110,7 @@ void LLPanelTopInfoBar::initParcelIcons()
mParcelIcon[BUILD_ICON]->setToolTip(LLTrans::getString("LocationCtrlBuildTooltip"));
mParcelIcon[SCRIPTS_ICON]->setToolTip(LLTrans::getString("LocationCtrlScriptsTooltip"));
mParcelIcon[DAMAGE_ICON]->setToolTip(LLTrans::getString("LocationCtrlDamageTooltip"));
+ mParcelIcon[SEE_AVATARS_ICON]->setToolTip(LLTrans::getString("LocationCtrlSeeAVsTooltip"));
mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, VOICE_ICON));
mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, FLY_ICON));
@@ -116,6 +118,7 @@ void LLPanelTopInfoBar::initParcelIcons()
mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, BUILD_ICON));
mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SCRIPTS_ICON));
mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, DAMAGE_ICON));
+ mParcelIcon[SEE_AVATARS_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, SEE_AVATARS_ICON));
mDamageText->setText(LLStringExplicit("100%"));
}
@@ -295,6 +298,7 @@ void LLPanelTopInfoBar::updateParcelIcons()
bool allow_build = vpm->allowAgentBuild(current_parcel); // true when anyone is allowed to build. See EXT-4610.
bool allow_scripts = vpm->allowAgentScripts(agent_region, current_parcel);
bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel);
+ bool see_avs = current_parcel->getSeeAVs();
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
@@ -304,6 +308,7 @@ void LLPanelTopInfoBar::updateParcelIcons()
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mDamageText->setVisible(allow_damage);
+ mParcelIcon[SEE_AVATARS_ICON]->setVisible( !see_avs );
layoutParcelIcons();
}
@@ -409,6 +414,9 @@ void LLPanelTopInfoBar::onParcelIconClick(EParcelIcon icon)
case DAMAGE_ICON:
LLNotificationsUtil::add("NotSafe");
break;
+ case SEE_AVATARS_ICON:
+ LLNotificationsUtil::add("SeeAvatars");
+ break;
case ICON_COUNT:
break;
// no default to get compiler warning when a new icon gets added
diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h
index db922ef424..583e91d15e 100644
--- a/indra/newview/llpaneltopinfobar.h
+++ b/indra/newview/llpaneltopinfobar.h
@@ -65,12 +65,13 @@ private:
enum EParcelIcon
{
VOICE_ICON = 0,
- FLY_ICON,
- PUSH_ICON,
- BUILD_ICON,
- SCRIPTS_ICON,
- DAMAGE_ICON,
- ICON_COUNT
+ FLY_ICON, // 1
+ PUSH_ICON, // 2
+ BUILD_ICON, // 3
+ SCRIPTS_ICON, // 4
+ DAMAGE_ICON, // 5
+ SEE_AVATARS_ICON, // 6
+ ICON_COUNT // 7 total
};
/**
diff --git a/indra/newview/llpanelvoicedevicesettings.cpp b/indra/newview/llpanelvoicedevicesettings.cpp
index dc87bd0077..4a80bbbe5e 100644
--- a/indra/newview/llpanelvoicedevicesettings.cpp
+++ b/indra/newview/llpanelvoicedevicesettings.cpp
@@ -191,7 +191,21 @@ void LLPanelVoiceDeviceSettings::refresh()
mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device");
- if(!LLVoiceClient::getInstance()->deviceSettingsAvailable())
+ bool device_settings_available = LLVoiceClient::getInstance()->deviceSettingsAvailable();
+
+ if (mCtrlInputDevices)
+ {
+ mCtrlInputDevices->setEnabled(device_settings_available);
+ }
+
+ if (mCtrlOutputDevices)
+ {
+ mCtrlOutputDevices->setEnabled(device_settings_available);
+ }
+
+ getChild<LLSlider>("mic_volume_slider")->setEnabled(device_settings_available);
+
+ if(!device_settings_available)
{
// The combo boxes are disabled, since we can't get the device settings from the daemon just now.
// Put the currently set default (ONLY) in the box, and select it.
@@ -207,6 +221,7 @@ void LLPanelVoiceDeviceSettings::refresh()
mCtrlOutputDevices->add( mOutputDevice, ADD_BOTTOM );
mCtrlOutputDevices->setSimple(mOutputDevice);
}
+ mDevicesUpdated = FALSE;
}
else if (!mDevicesUpdated)
{
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index c443814c89..bb87601d20 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -59,6 +59,7 @@
#include "lltool.h"
#include "lltoolcomp.h"
#include "lltoolmgr.h"
+#include "lltrans.h"
#include "llui.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
@@ -156,6 +157,34 @@ BOOL LLPanelVolume::postBuild()
mSpinPhysicsRestitution = getChild<LLSpinCtrl>("Physics Restitution");
mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution));
}
+
+ std::map<std::string, std::string> material_name_map;
+ material_name_map["Stone"]= LLTrans::getString("Stone");
+ material_name_map["Metal"]= LLTrans::getString("Metal");
+ material_name_map["Glass"]= LLTrans::getString("Glass");
+ material_name_map["Wood"]= LLTrans::getString("Wood");
+ material_name_map["Flesh"]= LLTrans::getString("Flesh");
+ material_name_map["Plastic"]= LLTrans::getString("Plastic");
+ material_name_map["Rubber"]= LLTrans::getString("Rubber");
+ material_name_map["Light"]= LLTrans::getString("Light");
+
+ LLMaterialTable::basic.initTableTransNames(material_name_map);
+
+ // material type popup
+ mComboMaterial = getChild<LLComboBox>("material");
+ childSetCommitCallback("material",onCommitMaterial,this);
+ mComboMaterial->removeall();
+
+ for (LLMaterialTable::info_list_t::iterator iter = LLMaterialTable::basic.mMaterialInfoList.begin();
+ iter != LLMaterialTable::basic.mMaterialInfoList.end(); ++iter)
+ {
+ LLMaterialInfo* minfop = *iter;
+ if (minfop->mMCode != LL_MCODE_LIGHT)
+ {
+ mComboMaterial->add(minfop->mName);
+ }
+ }
+ mComboMaterialItemCount = mComboMaterial->getItemCount();
// Start with everyone disabled
clearCtrls();
@@ -164,7 +193,8 @@ BOOL LLPanelVolume::postBuild()
}
LLPanelVolume::LLPanelVolume()
- : LLPanel()
+ : LLPanel(),
+ mComboMaterialItemCount(0)
{
setMouseOpaque(FALSE);
@@ -379,6 +409,46 @@ void LLPanelVolume::getState( )
getChildView("FlexForceZ")->setEnabled(false);
}
+ // Material properties
+
+ // Update material part
+ // slightly inefficient - materials are unique per object, not per TE
+ U8 material_code = 0;
+ struct f : public LLSelectedTEGetFunctor<U8>
+ {
+ U8 get(LLViewerObject* object, S32 te)
+ {
+ return object->getMaterial();
+ }
+ } func;
+ bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code );
+ std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
+ if (editable && single_volume && material_same)
+ {
+ mComboMaterial->setEnabled( TRUE );
+ if (material_code == LL_MCODE_LIGHT)
+ {
+ if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
+ {
+ mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
+ }
+ mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
+ }
+ else
+ {
+ if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
+ {
+ mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
+ }
+
+ mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
+ }
+ }
+ else
+ {
+ mComboMaterial->setEnabled( FALSE );
+ }
+
// Physics properties
mSpinPhysicsGravity->set(objectp->getPhysicsGravity());
@@ -460,17 +530,24 @@ void LLPanelVolume::refresh()
getChildView("Light Ambiance")->setVisible( visible);
getChildView("light texture control")->setVisible( visible);
- bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&
- gAgent.getRegion() &&
- !gAgent.getRegion()->getCapability("GetMesh").empty();
+ bool enable_mesh = false;
+ LLSD sim_features;
+ LLViewerRegion *region = gAgent.getRegion();
+ if(region)
+ {
+ LLSD sim_features;
+ region->getSimulatorFeatures(sim_features);
+ enable_mesh = sim_features.has("PhysicsShapeTypes");
+ }
getChildView("label physicsshapetype")->setVisible(enable_mesh);
getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh);
getChildView("Physics Gravity")->setVisible(enable_mesh);
- getChildView("Physics Material Override")->setVisible(enable_mesh);
getChildView("Physics Friction")->setVisible(enable_mesh);
getChildView("Physics Density")->setVisible(enable_mesh);
getChildView("Physics Restitution")->setVisible(enable_mesh);
+
+ /* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */
}
@@ -522,6 +599,8 @@ void LLPanelVolume::clearCtrls()
mSpinPhysicsFriction->setEnabled(FALSE);
mSpinPhysicsDensity->setEnabled(FALSE);
mSpinPhysicsRestitution->setEnabled(FALSE);
+
+ mComboMaterial->setEnabled( FALSE );
}
//
@@ -674,6 +753,25 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data)
}
// static
+void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata )
+{
+ //LLPanelObject* self = (LLPanelObject*) userdata;
+ LLComboBox* box = (LLComboBox*) ctrl;
+
+ if (box)
+ {
+ // apply the currently selected material to the object
+ const std::string& material_name = box->getSimple();
+ std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
+ if (material_name != LEGACY_FULLBRIGHT_DESC)
+ {
+ U8 material_code = LLMaterialTable::basic.getMCode(material_name);
+ LLSelectMgr::getInstance()->selectionSetMaterial(material_code);
+ }
+ }
+}
+
+// static
void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*) userdata;
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index 776a2c1f4a..0ef47db0d9 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -63,8 +63,8 @@ public:
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
static void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
-
static void onCommitPhysicsParam( LLUICtrl* ctrl, void* userdata);
+ static void onCommitMaterial( LLUICtrl* ctrl, void* userdata);
void onLightCancelColor(const LLSD& data);
void onLightSelectColor(const LLSD& data);
@@ -104,6 +104,10 @@ protected:
LLSpinCtrl* mSpinForce[3];
*/
+ S32 mComboMaterialItemCount;
+ LLComboBox* mComboMaterial;
+
+
LLColor4 mLightSavedColor;
LLUUID mLightSavedTexture;
LLPointer<LLViewerObject> mObject;
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index 911a9e5dda..f19b54c1d4 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -38,6 +38,8 @@
#include "llsidetray.h"
#include "llviewermenu.h"
#include "llwearableitemslist.h"
+#include "llsdserialize.h"
+#include "llclipboard.h"
// Context menu and Gear menu helper.
static void edit_outfit()
@@ -58,6 +60,7 @@ public:
registrar.add("Gear.Edit", boost::bind(&edit_outfit));
registrar.add("Gear.TakeOff", boost::bind(&LLWearingGearMenu::onTakeOff, this));
+ registrar.add("Gear.Copy", boost::bind(&LLPanelWearing::copyToClipboard, mPanelWearing));
enable_registrar.add("Gear.OnEnable", boost::bind(&LLPanelWearing::isActionEnabled, mPanelWearing, _2));
@@ -174,8 +177,8 @@ LLPanelWearing::~LLPanelWearing()
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
- delete mCategoriesObserver;
}
+ delete mCategoriesObserver;
}
BOOL LLPanelWearing::postBuild()
@@ -280,4 +283,25 @@ void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
mCOFItemsList->getSelectedUUIDs(selected_uuids);
}
+void LLPanelWearing::copyToClipboard()
+{
+ std::string text;
+ std::vector<LLSD> data;
+ mCOFItemsList->getValues(data);
+
+ for(std::vector<LLSD>::const_iterator iter = data.begin(); iter != data.end();)
+ {
+ LLSD uuid = (*iter);
+ LLViewerInventoryItem* item = gInventory.getItem(uuid);
+
+ iter++;
+ if (item != NULL)
+ {
+ // Append a newline to all but the last line
+ text += iter != data.end() ? item->getName() + "\n" : item->getName();
+ }
+ }
+
+ gClipboard.copyFromString(utf8str_to_wstring(text));
+}
// EOF
diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h
index 157b2c4c5f..9a212b3cca 100644
--- a/indra/newview/llpanelwearing.h
+++ b/indra/newview/llpanelwearing.h
@@ -60,6 +60,8 @@ public:
/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const;
+ /*virtual*/ void copyToClipboard();
+
boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb);
bool hasItemSelected();
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
index 29e262199e..f7823f4fe8 100644
--- a/indra/newview/llplacesinventorypanel.cpp
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -35,6 +35,7 @@
#include "llinventoryfunctions.h"
#include "llpanellandmarks.h"
#include "llplacesinventorybridge.h"
+#include "llviewerfoldertype.h"
static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel");
@@ -56,72 +57,44 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel()
delete mSavedFolderState;
}
-BOOL LLPlacesInventoryPanel::postBuild()
+void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
{
- LLInventoryPanel::postBuild();
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder);
- // clear Contents();
- {
- mFolderRoot->destroyView();
- mFolderRoot->getParent()->removeChild(mFolderRoot);
- mFolderRoot->die();
-
- if( mScroller )
- {
- removeChild( mScroller );
- mScroller->die();
- mScroller = NULL;
- }
- mFolderRoot = NULL;
- }
-
-
- mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+ LLUUID root_id;
- // create root folder
+ if ("LIBRARY" == params.start_folder())
{
- LLRect folder_rect(0,
- 0,
- getRect().getWidth(),
- 0);
- LLPlacesFolderView::Params p;
- p.name = getName();
- p.title = getLabel();
- p.rect = folder_rect;
- p.parent_panel = this;
- mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
- mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
+ root_id = gInventory.getLibraryRootFolderID();
}
-
- mCommitCallbackRegistrar.popScope();
-
- mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
-
- // scroller
+ else
{
- LLRect scroller_view_rect = getRect();
- scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
- LLScrollContainer::Params p;
- p.name("Inventory Scroller");
- p.rect(scroller_view_rect);
- p.follows.flags(FOLLOWS_ALL);
- p.reserve_scroll_corner(true);
- p.tab_stop(true);
- mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
}
- addChild(mScroller);
- mScroller->addChild(mFolderRoot);
-
- mFolderRoot->setScrollContainer(mScroller);
- mFolderRoot->addChild(mFolderRoot->mStatusTextBox);
-
- // cut subitems
- mFolderRoot->setUseEllipses(true);
-
- return TRUE;
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLPlacesFolderView::Params p;
+ p.name = getName();
+ p.title = getLabel();
+ p.rect = folder_rect;
+ p.listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+ LLAssetType::AT_CATEGORY,
+ LLInventoryType::IT_CATEGORY,
+ this,
+ NULL,
+ root_id);
+ p.parent_panel = this;
+ p.allow_multiselect = mAllowMultiSelect;
+ p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller
+ mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
}
+
// save current folder open state
void LLPlacesInventoryPanel::saveFolderState()
{
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
index 6641871a0b..f647e7f970 100644
--- a/indra/newview/llplacesinventorypanel.h
+++ b/indra/newview/llplacesinventorypanel.h
@@ -46,7 +46,7 @@ public:
LLPlacesInventoryPanel(const Params& p);
~LLPlacesInventoryPanel();
- /*virtual*/ BOOL postBuild();
+ /*virtual*/ void buildFolderView(const LLInventoryPanel::Params& params);
void saveFolderState();
void restoreFolderState();
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 9f5c55bad1..f47928b131 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -42,6 +42,7 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
+#include "llkeyboard.h"
#include "llmultigesture.h"
#include "llnotificationsutil.h"
#include "llradiogroup.h"
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 9f3ee6ac5d..4974dde282 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -401,15 +401,14 @@ struct LLSaveNotecardInfo
bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
{
- if(!gAssetStorage)
+ LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
+
+ if(!editor)
{
- llwarns << "Not connected to an asset storage system." << llendl;
+ llwarns << "Cannot get handle to the notecard editor." << llendl;
return false;
}
-
- LLViewerTextEditor* editor = getChild<LLViewerTextEditor>("Notecard Editor");
-
if(!editor->isPristine())
{
// We need to update the asset information
@@ -436,8 +435,15 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
// save it out to database
if (item)
{
- std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory");
- std::string task_url = gAgent.getRegion()->getCapability("UpdateNotecardTaskInventory");
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ llwarns << "Not connected to a region, cannot save notecard." << llendl;
+ return false;
+ }
+ std::string agent_url = region->getCapability("UpdateNotecardAgentInventory");
+ std::string task_url = region->getCapability("UpdateNotecardTaskInventory");
+
if (mObjectUUID.isNull() && !agent_url.empty())
{
// Saving into agent inventory
@@ -472,6 +478,11 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
(void*)info,
FALSE);
}
+ else // !gAssetStorage
+ {
+ llwarns << "Not connected to an asset storage system." << llendl;
+ return false;
+ }
}
}
return true;
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 31fde5d58a..028891a90e 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -55,23 +55,18 @@ LLProgressView* LLProgressView::sInstance = NULL;
S32 gStartImageWidth = 1;
S32 gStartImageHeight = 1;
-const F32 FADE_IN_TIME = 1.f;
-
-const std::string ANIMATION_FILENAME = "Login Sequence ";
-const std::string ANIMATION_SUFFIX = ".jpg";
-const F32 TOTAL_LOGIN_TIME = 10.f; // seconds, wild guess at time from GL context to actual world view
-S32 gLastStartAnimationFrame = 0; // human-style indexing, first image = 1
-const S32 ANIMATION_FRAMES = 1; //13;
+const F32 FADE_TO_WORLD_TIME = 1.0f;
static LLRegisterPanelClassWrapper<LLProgressView> r("progress_view");
-
// XUI: Translate
LLProgressView::LLProgressView()
: LLPanel(),
mPercentDone( 0.f ),
+ mMediaCtrl( NULL ),
mMouseDownInActiveArea( false ),
- mUpdateEvents("LLProgressView")
+ mUpdateEvents("LLProgressView"),
+ mFadeToWorldTimer()
{
mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
}
@@ -80,9 +75,14 @@ BOOL LLProgressView::postBuild()
{
mProgressBar = getChild<LLProgressBar>("login_progress_bar");
+ // media control that is used to play intro video
+ mMediaCtrl = getChild<LLMediaCtrl>("login_media_panel");
+ mMediaCtrl->setVisible( false ); // hidden initially
+ mMediaCtrl->addObserver( this ); // watch events
+
mCancelBtn = getChild<LLButton>("cancel_btn");
mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked, NULL );
- mFadeTimer.stop();
+ mFadeToWorldTimer.stop();
getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle()));
@@ -125,24 +125,43 @@ BOOL LLProgressView::handleKeyHere(KEY key, MASK mask)
return TRUE;
}
+void LLProgressView::revealIntroPanel()
+{
+ // if user hasn't yet seen intro video
+ std::string intro_url = gSavedSettings.getString("PostFirstLoginIntroURL");
+ if ( intro_url.length() > 0 &&
+ gSavedSettings.getBOOL("PostFirstLoginIntroViewed" ) == FALSE )
+ {
+ // navigate to intro URL and reveal widget
+ mMediaCtrl->navigateTo( intro_url );
+ mMediaCtrl->setVisible( TRUE );
+
+ // flag as having seen the new user post login intro
+ gSavedSettings.setBOOL("PostFirstLoginIntroViewed", TRUE );
+ }
+ else
+ {
+ // start the timer that will control the fade through to the world view
+ mFadeToWorldTimer.start();
+ }
+}
+
void LLProgressView::setVisible(BOOL visible)
{
// hiding progress view
if (getVisible() && !visible)
{
- mFadeTimer.start();
+ LLPanel::setVisible(FALSE);
}
// showing progress view
- else if (visible && (!getVisible() || mFadeTimer.getStarted()))
+ else if (visible && (!getVisible() || mFadeToWorldTimer.getStarted()))
{
setFocus(TRUE);
- mFadeTimer.stop();
- mProgressTimer.start();
+ mFadeToWorldTimer.stop();
LLPanel::setVisible(TRUE);
}
}
-
void LLProgressView::draw()
{
static LLTimer timer;
@@ -153,7 +172,7 @@ void LLProgressView::draw()
{
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->bind(gStartTexture.get());
- gGL.color4f(1.f, 1.f, 1.f, mFadeTimer.getStarted() ? clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, FADE_IN_TIME, 1.f, 0.f) : 1.f);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
F32 image_aspect = (F32)gStartImageWidth / (F32)gStartImageHeight;
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
@@ -180,16 +199,36 @@ void LLProgressView::draw()
}
glPopMatrix();
- // Handle fade-in animation
- if (mFadeTimer.getStarted())
+ // handle fade out to world view when we're asked to
+ if (mFadeToWorldTimer.getStarted())
{
+ // draw fading panel
+ F32 alpha = clamp_rescale(mFadeToWorldTimer.getElapsedTimeF32(), 0.f, FADE_TO_WORLD_TIME, 1.f, 0.f);
+ LLViewDrawContext context(alpha);
LLPanel::draw();
- if (mFadeTimer.getElapsedTimeF32() > FADE_IN_TIME)
+
+ // faded out completely - remove panel and reveal world
+ if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
{
+ mFadeToWorldTimer.stop();
+
// Fade is complete, release focus
gFocusMgr.releaseFocusIfNeeded( this );
+
+ // turn off panel that hosts intro so we see the world
LLPanel::setVisible(FALSE);
- mFadeTimer.stop();
+
+ // stop observing events since we no longer care
+ mMediaCtrl->remObserver( this );
+
+ // hide the intro
+ mMediaCtrl->setVisible( false );
+
+ // navigate away from intro page to something innocuous since 'unload' is broken right now
+ //mMediaCtrl->navigateTo( "about:blank" );
+
+ // FIXME: this causes a crash that i haven't been able to fix
+ mMediaCtrl->unloadMediaSource();
gStartTexture = NULL;
}
@@ -307,3 +346,12 @@ bool LLProgressView::onAlertModal(const LLSD& notify)
}
return false;
}
+
+void LLProgressView::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if( event == MEDIA_EVENT_CLOSE_REQUEST )
+ {
+ // the intro web content calls javascript::window.close() when it's done
+ mFadeToWorldTimer.start();
+ }
+}
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index be1744f08a..73dd478e98 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -28,6 +28,7 @@
#define LL_LLPROGRESSVIEW_H
#include "llpanel.h"
+#include "llmediactrl.h"
#include "llframetimer.h"
#include "llevents.h"
@@ -35,7 +36,10 @@ class LLImageRaw;
class LLButton;
class LLProgressBar;
-class LLProgressView : public LLPanel
+class LLProgressView :
+ public LLPanel,
+ public LLViewerMediaObserver
+
{
public:
LLProgressView();
@@ -49,25 +53,35 @@ public:
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ void setVisible(BOOL visible);
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
void setText(const std::string& text);
void setPercent(const F32 percent);
// Set it to NULL when you want to eliminate the message.
void setMessage(const std::string& msg);
+ // turns on (under certain circumstances) the into video after login
+ void revealIntroPanel();
+
void setCancelButtonVisible(BOOL b, const std::string& label);
static void onCancelButtonClicked( void* );
static void onClickMessage(void*);
bool onAlertModal(const LLSD& sd);
+ // note - this is not just hiding the intro panel - it also hides the parent panel
+ // and is used when the intro is finished and we want to show the world
+ void removeIntroPanel();
+
protected:
LLProgressBar* mProgressBar;
+ LLMediaCtrl* mMediaCtrl;
F32 mPercentDone;
std::string mMessage;
LLButton* mCancelBtn;
- LLFrameTimer mFadeTimer;
- LLFrameTimer mProgressTimer;
+ LLFrameTimer mFadeToWorldTimer;
LLRect mOutlineRect;
bool mMouseDownInActiveArea;
diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp
new file mode 100644
index 0000000000..698c4f9bb9
--- /dev/null
+++ b/indra/newview/llregioninfomodel.cpp
@@ -0,0 +1,217 @@
+/**
+ * @file llregioninfomodel.cpp
+ * @brief Region info model
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llregioninfomodel.h"
+
+// libs
+#include "message.h"
+#include "llregionflags.h"
+
+// viewer
+#include "llagent.h"
+#include "llviewerregion.h"
+
+void LLRegionInfoModel::reset()
+{
+ mSimAccess = 0;
+ mAgentLimit = 0;
+
+ mRegionFlags = 0;
+ mEstateID = 0;
+ mParentEstateID = 0;
+
+ mPricePerMeter = 0;
+ mRedirectGridX = 0;
+ mRedirectGridY = 0;
+
+ mBillableFactor = 0.0f;
+ mObjectBonusFactor = 0.0f;
+ mWaterHeight = 0.0f;
+ mTerrainRaiseLimit = 0.0f;
+ mTerrainLowerLimit = 0.0f;
+ mSunHour = 0.0f;
+
+ mUseEstateSun = false;
+
+ mSimType.clear();
+ mSimName.clear();
+}
+
+LLRegionInfoModel::LLRegionInfoModel()
+{
+ reset();
+}
+
+boost::signals2::connection LLRegionInfoModel::setUpdateCallback(const update_signal_t::slot_type& cb)
+{
+ return mUpdateSignal.connect(cb);
+}
+
+void LLRegionInfoModel::sendRegionTerrain(const LLUUID& invoice) const
+{
+ std::string buffer;
+ std::vector<std::string> strings;
+
+ // ==========================================
+ // Assemble and send setregionterrain message
+ // "setregionterrain"
+ // strings[0] = float water height
+ // strings[1] = float terrain raise
+ // strings[2] = float terrain lower
+ // strings[3] = 'Y' use estate time
+ // strings[4] = 'Y' fixed sun
+ // strings[5] = float sun_hour
+ // strings[6] = from estate, 'Y' use global time
+ // strings[7] = from estate, 'Y' fixed sun
+ // strings[8] = from estate, float sun_hour
+
+ // *NOTE: this resets estate sun info.
+ BOOL estate_global_time = true;
+ BOOL estate_fixed_sun = false;
+ F32 estate_sun_hour = 0.f;
+
+ buffer = llformat("%f", mWaterHeight);
+ strings.push_back(buffer);
+ buffer = llformat("%f", mTerrainRaiseLimit);
+ strings.push_back(buffer);
+ buffer = llformat("%f", mTerrainLowerLimit);
+ strings.push_back(buffer);
+ buffer = llformat("%s", (mUseEstateSun ? "Y" : "N"));
+ strings.push_back(buffer);
+ buffer = llformat("%s", (getUseFixedSun() ? "Y" : "N"));
+ strings.push_back(buffer);
+ buffer = llformat("%f", mSunHour);
+ strings.push_back(buffer);
+ buffer = llformat("%s", (estate_global_time ? "Y" : "N") );
+ strings.push_back(buffer);
+ buffer = llformat("%s", (estate_fixed_sun ? "Y" : "N") );
+ strings.push_back(buffer);
+ buffer = llformat("%f", estate_sun_hour);
+ strings.push_back(buffer);
+
+ sendEstateOwnerMessage(gMessageSystem, "setregionterrain", invoice, strings);
+}
+
+bool LLRegionInfoModel::getUseFixedSun() const
+{
+ return mRegionFlags & REGION_FLAGS_SUN_FIXED;
+}
+
+void LLRegionInfoModel::setUseFixedSun(bool fixed)
+{
+ if (fixed)
+ {
+ mRegionFlags |= REGION_FLAGS_SUN_FIXED;
+ }
+ else
+ {
+ mRegionFlags &= ~REGION_FLAGS_SUN_FIXED;
+ }
+}
+
+void LLRegionInfoModel::update(LLMessageSystem* msg)
+{
+ reset();
+
+ msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, mSimName);
+ msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, mEstateID);
+ msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, mParentEstateID);
+ msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, mRegionFlags);
+ msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_SimAccess, mSimAccess);
+ msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_MaxAgents, mAgentLimit);
+ msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, mObjectBonusFactor);
+ msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, mBillableFactor);
+ msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, mWaterHeight);
+ msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, mTerrainRaiseLimit);
+ msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, mTerrainLowerLimit);
+ msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter, mPricePerMeter);
+ msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridX, mRedirectGridX);
+ msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridY, mRedirectGridY);
+
+ msg->getBOOL(_PREHASH_RegionInfo, _PREHASH_UseEstateSun, mUseEstateSun);
+
+ // actually the "last set" sun hour, not the current sun hour. JC
+ msg->getF32(_PREHASH_RegionInfo, _PREHASH_SunHour, mSunHour);
+ LL_DEBUGS("Windlight Sync") << "Got region sun hour: " << mSunHour << LL_ENDL;
+
+ // the only reasonable way to decide if we actually have any data is to
+ // check to see if any of these fields have nonzero sizes
+ if (msg->getSize(_PREHASH_RegionInfo2, _PREHASH_ProductSKU) > 0 ||
+ msg->getSize(_PREHASH_RegionInfo2, "ProductName") > 0)
+ {
+ msg->getString(_PREHASH_RegionInfo2, "ProductName", mSimType);
+ }
+
+ // Let interested parties know that region info has been updated.
+ mUpdateSignal();
+}
+
+// static
+void LLRegionInfoModel::sendEstateOwnerMessage(
+ LLMessageSystem* msg,
+ const std::string& request,
+ const LLUUID& invoice,
+ const std::vector<std::string>& strings)
+{
+ LLViewerRegion* cur_region = gAgent.getRegion();
+
+ if (!cur_region)
+ {
+ llwarns << "Agent region not set" << llendl;
+ return;
+ }
+
+ llinfos << "Sending estate request '" << request << "'" << llendl;
+ msg->newMessage("EstateOwnerMessage");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
+ msg->nextBlock("MethodData");
+ msg->addString("Method", request);
+ msg->addUUID("Invoice", invoice);
+
+ if (strings.empty())
+ {
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", NULL);
+ }
+ else
+ {
+ std::vector<std::string>::const_iterator it = strings.begin();
+ std::vector<std::string>::const_iterator end = strings.end();
+ for (unsigned i = 0; it != end; ++it, ++i)
+ {
+ lldebugs << "- [" << i << "] " << (*it) << llendl;
+ msg->nextBlock("ParamList");
+ msg->addString("Parameter", *it);
+ }
+ }
+
+ msg->sendReliable(cur_region->getHost());
+}
diff --git a/indra/newview/llregioninfomodel.h b/indra/newview/llregioninfomodel.h
new file mode 100644
index 0000000000..89efd82767
--- /dev/null
+++ b/indra/newview/llregioninfomodel.h
@@ -0,0 +1,99 @@
+/**
+ * @file llregioninfomodel.h
+ * @brief Region info model
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLREGIONINFOMODEL_H
+#define LL_LLREGIONINFOMODEL_H
+
+class LLMessageSystem;
+
+#include "llsingleton.h"
+
+/**
+ * Contains region info, notifies interested parties of its changes.
+ */
+class LLRegionInfoModel : public LLSingleton<LLRegionInfoModel>
+{
+ LOG_CLASS(LLRegionInfoModel);
+
+public:
+ typedef boost::signals2::signal<void()> update_signal_t;
+ boost::signals2::connection setUpdateCallback(const update_signal_t::slot_type& cb);
+
+ void sendRegionTerrain(const LLUUID& invoice) const; /// upload region terrain data
+
+ bool getUseFixedSun() const;
+
+ void setUseFixedSun(bool fixed);
+
+ // *TODO: Add getters and make the data private.
+ U8 mSimAccess;
+ U8 mAgentLimit;
+
+ U32 mRegionFlags;
+ U32 mEstateID;
+ U32 mParentEstateID;
+
+ S32 mPricePerMeter;
+ S32 mRedirectGridX;
+ S32 mRedirectGridY;
+
+ F32 mBillableFactor;
+ F32 mObjectBonusFactor;
+ F32 mWaterHeight;
+ F32 mTerrainRaiseLimit;
+ F32 mTerrainLowerLimit;
+ F32 mSunHour; // 6..30
+
+ BOOL mUseEstateSun;
+
+ std::string mSimName;
+ std::string mSimType;
+
+protected:
+ friend class LLSingleton<LLRegionInfoModel>;
+ friend class LLViewerRegion;
+
+ LLRegionInfoModel();
+
+ /**
+ * Refresh model with data from the incoming server message.
+ */
+ void update(LLMessageSystem* msg);
+
+private:
+ void reset();
+
+ // *FIXME: Duplicated code from LLPanelRegionInfo
+ static void sendEstateOwnerMessage(
+ LLMessageSystem* msg,
+ const std::string& request,
+ const LLUUID& invoice,
+ const std::vector<std::string>& strings);
+
+ update_signal_t mUpdateSignal;
+};
+
+#endif // LL_LLREGIONINFOMODEL_H
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 9b264b81c7..8fa4065fa6 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1997,7 +1997,7 @@ void LLSelectMgr::selectionSetPhysicsType(U8 type)
if (object->permModify())
{
object->setPhysicsShapeType(mType);
- object->updateFlags();
+ object->updateFlags(TRUE);
}
return true;
}
@@ -2016,7 +2016,7 @@ void LLSelectMgr::selectionSetFriction(F32 friction)
if (object->permModify())
{
object->setPhysicsFriction(mFriction);
- object->updateFlags();
+ object->updateFlags(TRUE);
}
return true;
}
@@ -2035,7 +2035,7 @@ void LLSelectMgr::selectionSetGravity(F32 gravity )
if (object->permModify())
{
object->setPhysicsGravity(mGravity);
- object->updateFlags();
+ object->updateFlags(TRUE);
}
return true;
}
@@ -2054,7 +2054,7 @@ void LLSelectMgr::selectionSetDensity(F32 density )
if (object->permModify())
{
object->setPhysicsDensity(mDensity);
- object->updateFlags();
+ object->updateFlags(TRUE);
}
return true;
}
@@ -2073,7 +2073,7 @@ void LLSelectMgr::selectionSetRestitution(F32 restitution)
if (object->permModify())
{
object->setPhysicsRestitution(mRestitution);
- object->updateFlags();
+ object->updateFlags(TRUE);
}
return true;
}
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 16729f045a..28ec11d1c7 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -32,6 +32,7 @@
#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
+#include "llfolderview.h"
#include "llinventorypanel.h"
#include "llfiltereditor.h"
#include "llfloaterreg.h"
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 31ea542743..65655f82cd 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -29,33 +29,147 @@
#include "llagent.h"
#include "llappearancemgr.h"
+#include "llappviewer.h"
#include "llavataractions.h"
#include "llbutton.h"
+#include "lldate.h"
#include "llfirstuse.h"
+#include "llfoldertype.h"
+#include "llhttpclient.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventoryobserver.h"
#include "llinventorypanel.h"
+#include "lllayoutstack.h"
#include "lloutfitobserver.h"
#include "llpanelmaininventory.h"
+#include "llpanelmarketplaceinbox.h"
+#include "llpanelmarketplaceoutbox.h"
+#include "llselectmgr.h"
#include "llsidepaneliteminfo.h"
#include "llsidepaneltaskinfo.h"
+#include "llstring.h"
#include "lltabcontainer.h"
-#include "llselectmgr.h"
+#include "llviewermedia.h"
#include "llweb.h"
static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
-LLSidepanelInventory::LLSidepanelInventory()
- : LLPanel(),
- mItemPanel(NULL),
- mPanelMainInventory(NULL)
+//
+// Constants
+//
+
+static const char * const INBOX_EXPAND_TIME_SETTING = "LastInventoryInboxExpand";
+
+static const char * const INBOX_BUTTON_NAME = "inbox_btn";
+static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
+
+static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
+static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel";
+static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel";
+
+static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox";
+static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox";
+
+static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
+
+static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
+static const char * const MARKETPLACE_OUTBOX_PANEL = "marketplace_outbox";
+
+//
+// Helpers
+//
+
+class LLInboxOutboxAddedObserver : public LLInventoryCategoryAddedObserver
{
+public:
+ LLInboxOutboxAddedObserver(LLSidepanelInventory * sidepanelInventory)
+ : LLInventoryCategoryAddedObserver()
+ , mSidepanelInventory(sidepanelInventory)
+ {
+ }
+
+ void done()
+ {
+ for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it)
+ {
+ LLViewerInventoryCategory* added_category = *it;
+
+ LLFolderType::EType added_category_type = added_category->getPreferredType();
+
+ switch (added_category_type)
+ {
+ case LLFolderType::FT_INBOX:
+ mSidepanelInventory->observeInboxModifications(added_category->getUUID());
+ break;
+ case LLFolderType::FT_OUTBOX:
+ mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
+ break;
+ case LLFolderType::FT_NONE:
+ // HACK until sim update to properly create folder with system type
+ if (added_category->getName() == "Received Items")
+ {
+ mSidepanelInventory->observeInboxModifications(added_category->getUUID());
+ }
+ else if (added_category->getName() == "Merchant Outbox")
+ {
+ mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+private:
+ LLSidepanelInventory * mSidepanelInventory;
+};
+//
+// Implementation
+//
+
+LLSidepanelInventory::LLSidepanelInventory()
+ : LLPanel()
+ , mItemPanel(NULL)
+ , mPanelMainInventory(NULL)
+ , mInboxEnabled(false)
+ , mOutboxEnabled(false)
+ , mCategoriesObserver(NULL)
+ , mInboxOutboxAddedObserver(NULL)
+{
//buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
}
LLSidepanelInventory::~LLSidepanelInventory()
{
+ if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
+ {
+ gInventory.removeObserver(mCategoriesObserver);
+ }
+ delete mCategoriesObserver;
+
+ if (mInboxOutboxAddedObserver && gInventory.containsObserver(mInboxOutboxAddedObserver))
+ {
+ gInventory.removeObserver(mInboxOutboxAddedObserver);
+ }
+ delete mInboxOutboxAddedObserver;
+}
+
+void handleInventoryDisplayInboxChanged()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
+}
+
+void handleInventoryDisplayOutboxChanged()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
}
BOOL LLSidepanelInventory::postBuild()
@@ -85,7 +199,7 @@ BOOL LLSidepanelInventory::postBuild()
mOverflowBtn = mInventoryPanel->getChild<LLButton>("overflow_btn");
mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
- mPanelMainInventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ mPanelMainInventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
mPanelMainInventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
LLTabContainer* tabs = mPanelMainInventory->getChild<LLTabContainer>("inventory filter tabs");
tabs->setCommitCallback(boost::bind(&LLSidepanelInventory::updateVerbs, this));
@@ -103,7 +217,7 @@ BOOL LLSidepanelInventory::postBuild()
// UI elements from item panel
{
- mItemPanel = findChild<LLSidepanelItemInfo>("sidepanel__item_panel");
+ mItemPanel = getChild<LLSidepanelItemInfo>("sidepanel__item_panel");
LLButton* back_btn = mItemPanel->getChild<LLButton>("back_btn");
back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
@@ -119,13 +233,263 @@ BOOL LLSidepanelInventory::postBuild()
}
}
+ // Marketplace inbox/outbox setup
+ {
+ LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+
+ // Disable user_resize on main inventory panel by default
+ stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false);
+ stack->setPanelUserResize(INBOX_LAYOUT_PANEL_NAME, false);
+ stack->setPanelUserResize(OUTBOX_LAYOUT_PANEL_NAME, false);
+
+ // Collapse both inbox and outbox panels
+ stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
+ stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true);
+
+ // Set up button states and callbacks
+ LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME);
+ LLButton * outbox_button = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+
+ inbox_button->setToggleState(false);
+ outbox_button->setToggleState(false);
+
+ inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this));
+ outbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleOutboxBtn, this));
+
+ // Set the inbox and outbox visible based on debug settings (final setting comes from http request below)
+ enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
+ enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
+
+ // Trigger callback for after login so we can setup to track inbox and outbox changes after initial inventory load
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::handleLoginComplete, this));
+ }
+
+ gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged));
+ gSavedSettings.getControl("InventoryDisplayOutbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayOutboxChanged));
+
return TRUE;
}
+void LLSidepanelInventory::handleLoginComplete()
+{
+ //
+ // Track inbox and outbox folder changes
+ //
+
+ const bool do_not_create_folder = false;
+ const bool do_not_find_in_library = false;
+
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library);
+ const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
+
+ // Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist
+ if (inbox_id.isNull() || outbox_id.isNull())
+ {
+ observeInboxOutboxCreation();
+ }
+
+ // Set up observer for inbox changes, if we have an inbox already
+ if (!inbox_id.isNull())
+ {
+ observeInboxModifications(inbox_id);
+
+ // Enable the display of the inbox if it exists
+ enableInbox(true);
+ }
+
+ // Set up observer for outbox changes, if we have an outbox already
+ if (!outbox_id.isNull())
+ {
+ observeOutboxModifications(outbox_id);
+
+ // Enable the display of the outbox if it exists
+ //enableOutbox(true);
+ // leslie NOTE: Disabling outbox until we support it officially.
+ }
+}
+
+void LLSidepanelInventory::observeInboxOutboxCreation()
+{
+ //
+ // Set up observer to track inbox and outbox folder creation
+ //
+
+ if (mInboxOutboxAddedObserver == NULL)
+ {
+ mInboxOutboxAddedObserver = new LLInboxOutboxAddedObserver(this);
+
+ gInventory.addObserver(mInboxOutboxAddedObserver);
+ }
+}
+
+void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID)
+{
+ //
+ // Track inbox and outbox folder changes
+ //
+
+ if (inboxID.isNull())
+ {
+ llwarns << "Attempting to track modifications to non-existant inbox" << llendl;
+ return;
+ }
+
+ if (mCategoriesObserver == NULL)
+ {
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mCategoriesObserver);
+ }
+
+ mCategoriesObserver->addCategory(inboxID, boost::bind(&LLSidepanelInventory::onInboxChanged, this, inboxID));
+
+ //
+ // Trigger a load for the entire contents of the Inbox
+ //
+
+ LLInventoryModelBackgroundFetch::instance().start(inboxID);
+
+ //
+ // Set up the inbox inventory view
+ //
+
+ LLPanelMarketplaceInbox * inbox = getChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+ inbox->setupInventoryPanel();
+}
+
+
+void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID)
+{
+ //
+ // Track outbox folder changes
+ //
+
+ if (outboxID.isNull())
+ {
+ llwarns << "Attempting to track modifications to non-existant outbox" << llendl;
+ return;
+ }
+
+ if (mCategoriesObserver == NULL)
+ {
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mCategoriesObserver);
+ }
+
+ mCategoriesObserver->addCategory(outboxID, boost::bind(&LLSidepanelInventory::onOutboxChanged, this, outboxID));
+
+ //
+ // Set up the outbox inventory view
+ //
+
+ LLPanelMarketplaceOutbox * outbox = getChild<LLPanelMarketplaceOutbox>(MARKETPLACE_OUTBOX_PANEL);
+ outbox->setupInventoryPanel();
+}
+
+void LLSidepanelInventory::enableInbox(bool enabled)
+{
+ mInboxEnabled = enabled;
+ getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->setVisible(enabled);
+}
+
+void LLSidepanelInventory::enableOutbox(bool enabled)
+{
+ mOutboxEnabled = enabled;
+ getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->setVisible(enabled);
+}
+
+void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
+{
+ // Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting
+ LLInventoryModelBackgroundFetch::instance().start(inbox_id);
+
+ // Expand the inbox since we have fresh items
+ LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+ if (inbox && (inbox->getFreshItemCount() > 0))
+ {
+ getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
+ onToggleInboxBtn();
+ }
+}
+
+void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id)
+{
+ // Perhaps use this to track outbox changes?
+}
+
+bool manageInboxOutboxPanels(LLLayoutStack * stack,
+ LLButton * pressedButton, LLLayoutPanel * pressedPanel,
+ LLButton * otherButton, LLLayoutPanel * otherPanel)
+{
+ bool expand = pressedButton->getToggleState();
+ bool otherExpanded = otherButton->getToggleState();
+
+ //
+ // NOTE: Ideally we could have two panel sizes stored for a collapsed and expanded minimum size.
+ // For now, leave this code disabled because it creates some bad artifacts when expanding
+ // and collapsing the inbox/outbox.
+ //
+ //S32 smallMinSize = (expand ? pressedPanel->getMinDim() : otherPanel->getMinDim());
+ //S32 pressedMinSize = (expand ? 2 * smallMinSize : smallMinSize);
+ //otherPanel->setMinDim(smallMinSize);
+ //pressedPanel->setMinDim(pressedMinSize);
+
+ if (expand && otherExpanded)
+ {
+ // Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size
+ pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight());
+
+ stack->collapsePanel(otherPanel, true);
+ otherButton->setToggleState(false);
+ }
+
+ stack->collapsePanel(pressedPanel, !expand);
+
+ // Enable user_resize on main inventory panel only when a marketplace box is expanded
+ stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand);
+
+ return expand;
+}
+
+void LLSidepanelInventory::onToggleInboxBtn()
+{
+ LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+ LLButton* pressedButton = getChild<LLButton>(INBOX_BUTTON_NAME);
+ LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
+ LLButton* otherButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+ LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
+
+ bool inboxExpanded = manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel);
+
+ if (inboxExpanded)
+ {
+ // Save current time as a setting for future new-ness tests
+ gSavedSettings.setString(INBOX_EXPAND_TIME_SETTING, LLDate::now().asString());
+ }
+}
+
+void LLSidepanelInventory::onToggleOutboxBtn()
+{
+ LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+ LLButton* pressedButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+ LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
+ LLButton* otherButton = getChild<LLButton>(INBOX_BUTTON_NAME);
+ LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
+
+ manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel);
+}
+
void LLSidepanelInventory::onOpen(const LLSD& key)
{
LLFirstUse::newInventory(false);
+ // Expand the inbox if we have fresh items
+ LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+ if (inbox && (inbox->getFreshItemCount() > 0))
+ {
+ getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
+ onToggleInboxBtn();
+ }
+
if(key.size() == 0)
return;
@@ -171,26 +535,29 @@ void LLSidepanelInventory::onShopButtonClicked()
void LLSidepanelInventory::performActionOnSelection(const std::string &action)
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
if (!current_item)
{
- return;
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ current_item = inbox->getRootFolder()->getCurSelectedItem();
+ }
+
+ if (!current_item)
+ {
+ return;
+ }
}
+
current_item->getListener()->performAction(panel_main_inventory->getActivePanel()->getModel(), action);
}
void LLSidepanelInventory::onWearButtonClicked()
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
- if (!panel_main_inventory)
- {
- llassert(panel_main_inventory != NULL);
- return;
- }
-
// Get selected items set.
- const std::set<LLUUID> selected_uuids_set = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> selected_uuids_set = LLAvatarActions::getInventorySelectedUUIDs();
if (selected_uuids_set.empty()) return; // nothing selected
// Convert the set to a vector.
@@ -329,31 +696,28 @@ bool LLSidepanelInventory::canShare()
LLPanelMainInventory* panel_main_inventory =
mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
- if (!panel_main_inventory)
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+
+ // Avoid flicker in the Recent tab while inventory is being loaded.
+ if ( (!inbox || inbox->getRootFolder()->getSelectionList().empty())
+ && (panel_main_inventory && !panel_main_inventory->getActivePanel()->getRootFolder()->hasVisibleChildren()) )
{
- llwarns << "Failed to get the main inventory panel" << llendl;
return false;
}
- LLInventoryPanel* active_panel = panel_main_inventory->getActivePanel();
- // Avoid flicker in the Recent tab while inventory is being loaded.
- if (!active_panel->getRootFolder()->hasVisibleChildren()) return false;
-
- return LLAvatarActions::canShareSelectedItems(active_panel);
+ return ( (panel_main_inventory ? LLAvatarActions::canShareSelectedItems(panel_main_inventory->getActivePanel()) : false)
+ || (inbox ? LLAvatarActions::canShareSelectedItems(inbox) : false) );
}
+
bool LLSidepanelInventory::canWearSelected()
{
- LLPanelMainInventory* panel_main_inventory =
- mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
- if (!panel_main_inventory)
- {
- llassert(panel_main_inventory != NULL);
+ std::set<LLUUID> selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
+
+ if (selected_uuids.empty())
return false;
- }
- std::set<LLUUID> selected_uuids = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
for (std::set<LLUUID>::const_iterator it = selected_uuids.begin();
it != selected_uuids.end();
++it)
@@ -366,11 +730,20 @@ bool LLSidepanelInventory::canWearSelected()
LLInventoryItem *LLSidepanelInventory::getSelectedItem()
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
if (!current_item)
{
- return NULL;
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ current_item = inbox->getRootFolder()->getCurSelectedItem();
+ }
+
+ if (!current_item)
+ {
+ return NULL;
+ }
}
const LLUUID &item_id = current_item->getListener()->getUUID();
LLInventoryItem *item = gInventory.getItem(item_id);
@@ -379,9 +752,20 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()
U32 LLSidepanelInventory::getSelectedCount()
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ int count = 0;
+
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
std::set<LLUUID> selection_list = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
- return selection_list.size();
+ count += selection_list.size();
+
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ selection_list = inbox->getRootFolder()->getSelectionList();
+ count += selection_list.size();
+ }
+
+ return count;
}
LLInventoryPanel *LLSidepanelInventory::getActivePanel()
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
index 32c98bc034..9117e3bf27 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -30,6 +30,8 @@
#include "llpanel.h"
class LLFolderViewItem;
+class LLInboxOutboxAddedObserver;
+class LLInventoryCategoriesObserver;
class LLInventoryItem;
class LLInventoryPanel;
class LLPanelMainInventory;
@@ -42,6 +44,14 @@ public:
LLSidepanelInventory();
virtual ~LLSidepanelInventory();
+private:
+ void handleLoginComplete();
+
+public:
+ void observeInboxOutboxCreation();
+ void observeInboxModifications(const LLUUID& inboxID);
+ void observeOutboxModifications(const LLUUID& outboxID);
+
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
@@ -56,6 +66,17 @@ public:
// checks can share selected item(s)
bool canShare();
+ void onToggleInboxBtn();
+ void onToggleOutboxBtn();
+
+ void enableInbox(bool enabled);
+ void enableOutbox(bool enabled);
+
+ bool isInboxEnabled() const { return mInboxEnabled; }
+ bool isOutboxEnabled() const { return mOutboxEnabled; }
+
+ void updateVerbs();
+
protected:
// Tracks highlighted (selected) item in inventory panel.
LLInventoryItem *getSelectedItem();
@@ -63,10 +84,12 @@ protected:
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
// "wear", "teleport", etc.
void performActionOnSelection(const std::string &action);
- void updateVerbs();
bool canWearSelected(); // check whether selected items can be worn
+ void onInboxChanged(const LLUUID& inbox_id);
+ void onOutboxChanged(const LLUUID& outbox_id);
+
//
// UI Elements
//
@@ -85,6 +108,7 @@ protected:
void onTeleportButtonClicked();
void onOverflowButtonClicked();
void onBackButtonClicked();
+
private:
LLButton* mInfoBtn;
LLButton* mShareBtn;
@@ -94,6 +118,11 @@ private:
LLButton* mOverflowBtn;
LLButton* mShopBtn;
+ bool mInboxEnabled;
+ bool mOutboxEnabled;
+
+ LLInventoryCategoriesObserver* mCategoriesObserver;
+ LLInboxOutboxAddedObserver* mInboxOutboxAddedObserver;
};
#endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp
index 37b10b592f..2918bb388a 100644
--- a/indra/newview/llsidepanelinventorysubpanel.cpp
+++ b/indra/newview/llsidepanelinventorysubpanel.cpp
@@ -46,8 +46,8 @@
///----------------------------------------------------------------------------
// Default constructor
-LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
- : LLPanel(),
+LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel(const LLPanel::Params& p)
+ : LLPanel(p),
mIsDirty(TRUE),
mIsEditing(FALSE),
mCancelBtn(NULL),
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h
index b2de7d3b0b..b5cf3aaf17 100644
--- a/indra/newview/llsidepanelinventorysubpanel.h
+++ b/indra/newview/llsidepanelinventorysubpanel.h
@@ -40,7 +40,7 @@ class LLInventoryItem;
class LLSidepanelInventorySubpanel : public LLPanel
{
public:
- LLSidepanelInventorySubpanel();
+ LLSidepanelInventorySubpanel(const LLPanel::Params& p = getDefaultParams());
virtual ~LLSidepanelInventorySubpanel();
/*virtual*/ void setVisible(BOOL visible);
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index fbd2f7ca83..1ce05da849 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -130,9 +130,10 @@ void LLObjectInventoryObserver::inventoryChanged(LLViewerObject* object,
static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
// Default constructor
-LLSidepanelItemInfo::LLSidepanelItemInfo()
- : mItemID(LLUUID::null)
- , mObjectInventoryObserver(NULL)
+LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
+ : LLSidepanelInventorySubpanel(p)
+ , mItemID(LLUUID::null)
+ , mObjectInventoryObserver(NULL)
{
mPropertiesObserver = new LLItemPropertiesObserver(this);
}
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 25be145f64..12aaca923e 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -44,7 +44,7 @@ class LLPermissions;
class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
{
public:
- LLSidepanelItemInfo();
+ LLSidepanelItemInfo(const LLPanel::Params& p = getDefaultParams());
virtual ~LLSidepanelItemInfo();
/*virtual*/ BOOL postBuild();
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 631b244785..651897a217 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -30,6 +30,7 @@
#include "llagentcamera.h"
#include "llappviewer.h"
+#include "llbadge.h"
#include "llbottomtray.h"
#include "llfloaterreg.h"
#include "llfirstuse.h"
@@ -40,6 +41,7 @@
#include "llfocusmgr.h"
#include "llrootview.h"
#include "llnavigationbar.h"
+#include "llpanelmarketplaceinbox.h"
#include "llaccordionctrltab.h"
@@ -113,11 +115,14 @@ public:
Optional<std::string> image_selected;
Optional<std::string> tab_title;
Optional<std::string> description;
+ Optional<LLBadge::Params> badge;
+
Params()
: image("image"),
image_selected("image_selected"),
tab_title("tab_title","no title"),
- description("description","no description")
+ description("description","no description"),
+ badge("badge")
{};
};
protected:
@@ -140,7 +145,6 @@ public:
static LLSideTrayTab* createInstance ();
const std::string& getDescription () const { return mDescription;}
- const std::string& getTabTitle() const { return mTabTitle;}
void onOpen (const LLSD& key);
@@ -150,7 +154,10 @@ public:
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- LLPanel *getPanel();
+ LLPanel* getPanel();
+
+ LLButton* createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback);
+
private:
std::string mTabTitle;
std::string mImage;
@@ -158,6 +165,9 @@ private:
std::string mDescription;
LLView* mMainPanel;
+
+ bool mHasBadge;
+ LLBadge::Params mBadgeParams;
};
LLSideTrayTab::LLSideTrayTab(const Params& p)
@@ -166,8 +176,10 @@ LLSideTrayTab::LLSideTrayTab(const Params& p)
mImage(p.image),
mImageSelected(p.image_selected),
mDescription(p.description),
- mMainPanel(NULL)
+ mMainPanel(NULL),
+ mBadgeParams(p.badge)
{
+ mHasBadge = p.badge.isProvided();
}
LLSideTrayTab::~LLSideTrayTab()
@@ -182,8 +194,6 @@ bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
//return res;
}
-
-
//virtual
BOOL LLSideTrayTab::postBuild()
{
@@ -196,7 +206,7 @@ BOOL LLSideTrayTab::postBuild()
getChild<LLButton>("undock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, false));
getChild<LLButton>("dock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, true));
- return true;
+ return LLPanel::postBuild();
}
static const S32 splitter_margin = 1;
@@ -523,18 +533,36 @@ public:
return FALSE;
}
+ void setBadgeDriver(LLSideTrayTabBadgeDriver* driver)
+ {
+ mBadgeDriver = driver;
+ }
+
protected:
LLSideTrayButton(const LLButton::Params& p)
- : LLButton(p)
- , mDragLastScreenX(0)
- , mDragLastScreenY(0)
+ : LLButton(p)
+ , mDragLastScreenX(0)
+ , mDragLastScreenY(0)
+ , mBadgeDriver(NULL)
{}
friend class LLUICtrlFactory;
+ void draw()
+ {
+ if (mBadgeDriver)
+ {
+ setBadgeLabel(mBadgeDriver->getBadgeString());
+ }
+
+ LLButton::draw();
+ }
+
private:
S32 mDragLastScreenX;
S32 mDragLastScreenY;
+
+ LLSideTrayTabBadgeDriver* mBadgeDriver;
};
//////////////////////////////////////////////////////////////////////////////
@@ -615,11 +643,31 @@ BOOL LLSideTray::postBuild()
return true;
}
+void LLSideTray::setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver)
+{
+ mTabButtonBadgeDrivers[tabName] = driver;
+}
+
void LLSideTray::handleLoginComplete()
{
//reset tab to "home" tab if it was changesd during login process
selectTabByName("sidebar_home");
+ for (badge_map_t::iterator it = mTabButtonBadgeDrivers.begin(); it != mTabButtonBadgeDrivers.end(); ++it)
+ {
+ LLButton* button = mTabButtons[it->first];
+ LLSideTrayButton* side_button = dynamic_cast<LLSideTrayButton*>(button);
+
+ if (side_button)
+ {
+ side_button->setBadgeDriver(it->second);
+ }
+ else
+ {
+ llwarns << "Unable to find button " << it->first << " to set the badge driver. " << llendl;
+ }
+ }
+
detachTabs();
}
@@ -766,51 +814,6 @@ bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible
return true;
}
-LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,const std::string& tooltip,
- LLUICtrl::commit_callback_t callback)
-{
- static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
-
- LLButton::Params bparams;
-
- LLRect rect;
- rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height);
-
- bparams.name(name);
- bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
- bparams.rect (rect);
- bparams.tab_stop(false);
- bparams.image_unselected(sidetray_params.tab_btn_image_normal);
- bparams.image_selected(sidetray_params.tab_btn_image_selected);
- bparams.image_disabled(sidetray_params.tab_btn_image_normal);
- bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected);
-
- LLButton* button;
- if (name == "sidebar_openclose")
- {
- // "Open/Close" button shouldn't allow "tear off"
- // hence it is created as LLButton instance.
- button = LLUICtrlFactory::create<LLButton>(bparams);
- }
- else
- {
- button = LLUICtrlFactory::create<LLSideTrayButton>(bparams);
- }
-
- button->setClickedCallback(callback);
-
- button->setToolTip(tooltip);
-
- if(image.length())
- {
- button->setImageOverlay(image);
- }
-
- mButtonsPanel->addChildInBack(button);
-
- return button;
-}
-
bool LLSideTray::addChild(LLView* view, S32 tab_group)
{
LLSideTrayTab* tab_panel = dynamic_cast<LLSideTrayTab*>(view);
@@ -938,7 +941,56 @@ bool LLSideTray::addTab(LLSideTrayTab* tab)
return true;
}
-void LLSideTray::createButtons ()
+LLButton* LLSideTrayTab::createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback)
+{
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ LLRect rect;
+ rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height);
+
+ LLButton::Params bparams;
+
+ // Append "_button" to the side tray tab name
+ std::string button_name = getName() + "_button";
+ bparams.name(button_name);
+ bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
+ bparams.rect (rect);
+ bparams.tab_stop(false);
+ bparams.image_unselected(sidetray_params.tab_btn_image_normal);
+ bparams.image_selected(sidetray_params.tab_btn_image_selected);
+ bparams.image_disabled(sidetray_params.tab_btn_image_normal);
+ bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected);
+
+ if (mHasBadge)
+ {
+ bparams.badge = mBadgeParams;
+ }
+
+ LLButton* button;
+ if (allowTearOff)
+ {
+ button = LLUICtrlFactory::create<LLSideTrayButton>(bparams);
+ }
+ else
+ {
+ // "Open/Close" button shouldn't allow "tear off"
+ // hence it is created as LLButton instance.
+ button = LLUICtrlFactory::create<LLButton>(bparams);
+ }
+
+ button->setClickedCallback(callback);
+
+ button->setToolTip(mTabTitle);
+
+ if(mImage.length())
+ {
+ button->setImageOverlay(mImage);
+ }
+
+ return button;
+}
+
+void LLSideTray::createButtons()
{
//create buttons for tabs
child_vector_const_iter_t child_it = mTabs.begin();
@@ -951,17 +1003,22 @@ void LLSideTray::createButtons ()
// The "OpenClose" button will open/close the whole panel
if (name == "sidebar_openclose")
{
- mCollapseButton = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(),
- boost::bind(&LLSideTray::onToggleCollapse, this));
+ mCollapseButton = sidebar_tab->createButton(false, boost::bind(&LLSideTray::onToggleCollapse, this));
+
+ mButtonsPanel->addChildInBack(mCollapseButton);
+
LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle());
}
else
{
- LLButton* button = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(),
- boost::bind(&LLSideTray::onTabButtonClick, this, name));
+ LLButton* button = sidebar_tab->createButton(true, boost::bind(&LLSideTray::onTabButtonClick, this, name));
+
+ mButtonsPanel->addChildInBack(button);
+
mTabButtons[name] = button;
}
}
+
LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle());
}
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 24882411f4..17158329dc 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -33,6 +33,13 @@
class LLAccordionCtrl;
class LLSideTrayTab;
+// Define an interface for side tab button badge values
+class LLSideTrayTabBadgeDriver
+{
+public:
+ virtual std::string getBadgeString() const = 0;
+};
+
// Deal with LLSideTrayTab being opaque. Generic do-nothing cast...
template <class T>
T tab_cast(LLSideTrayTab* tab) { return tab; }
@@ -166,6 +173,8 @@ public:
bool getCollapsed() { return mCollapsed; }
+ void setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver);
+
public:
virtual ~LLSideTray(){};
@@ -204,8 +213,6 @@ protected:
void createButtons ();
- LLButton* createButton (const std::string& name,const std::string& image,const std::string& tooltip,
- LLUICtrl::commit_callback_t callback);
void arrange ();
void detachTabs ();
void reflectCollapseChange();
@@ -234,6 +241,8 @@ private:
LLPanel* mButtonsPanel;
typedef std::map<std::string,LLButton*> button_map_t;
button_map_t mTabButtons;
+ typedef std::map<std::string,LLSideTrayTabBadgeDriver*> badge_map_t;
+ badge_map_t mTabButtonBadgeDrivers;
child_vector_t mTabs;
child_vector_t mDetachedTabs;
tab_order_vector_t mOriginalTabOrder;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index fa329eb0ae..f99afa923b 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -35,6 +35,7 @@
#include "llvolumeoctree.h"
#include "llviewercamera.h"
#include "llface.h"
+#include "llfloatertools.h"
#include "llviewercontrol.h"
#include "llviewerregion.h"
#include "llcamera.h"
@@ -69,6 +70,7 @@ U32 LLSpatialGroup::sNodeCount = 0;
std::set<GLuint> LLSpatialGroup::sPendingQueries;
+U32 gOctreeMaxCapacity;
BOOL LLSpatialGroup::sNoDelete = FALSE;
@@ -630,7 +632,7 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
if (mOctreeNode->isInside(drawablep->getPositionGroup()) &&
(mOctreeNode->contains(drawablep) ||
(drawablep->getBinRadius() > mOctreeNode->getSize()[0] &&
- parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
+ parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{
unbound();
setState(OBJECT_DIRTY);
@@ -689,17 +691,8 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
{
- /*if (!gPipeline.hasRenderType(mDrawableType))
- {
- return;
- }*/
-
if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
- /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup)
- {
- llerrs << "WTF?" << llendl;
- }*/
return;
}
@@ -961,21 +954,15 @@ void LLSpatialGroup::setState(U32 state)
{
mState |= state;
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
+ llassert(state <= LLSpatialGroup::STATE_MASK);
}
void LLSpatialGroup::setState(U32 state, S32 mode)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
-
+ llassert(state <= LLSpatialGroup::STATE_MASK);
+
if (mode > STATE_MODE_SINGLE)
{
if (mode == STATE_MODE_DIFF)
@@ -1021,20 +1008,14 @@ public:
void LLSpatialGroup::clearState(U32 state)
{
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
+ llassert(state <= LLSpatialGroup::STATE_MASK);
mState &= ~state;
}
void LLSpatialGroup::clearState(U32 state, S32 mode)
{
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
+ llassert(state <= LLSpatialGroup::STATE_MASK);
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -1059,10 +1040,7 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
BOOL LLSpatialGroup::isState(U32 state) const
{
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
+ llassert(state <= LLSpatialGroup::STATE_MASK);
return mState & state ? TRUE : FALSE;
}
@@ -1250,7 +1228,8 @@ void LLSpatialGroup::updateDistance(LLCamera &camera)
{
if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
{
- llerrs << "WTF?" << llendl;
+ llwarns << "Attempted to update distance for camera other than world camera!" << llendl;
+ return;
}
#if !LL_RELEASE_FOR_DOWNLOAD
@@ -2064,11 +2043,8 @@ public:
virtual void processGroup(LLSpatialGroup* group)
{
- if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty())
- {
- llerrs << "WTF?" << llendl;
- }
-
+ llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty())
+
if (mRes < 2)
{
if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0)
@@ -2541,7 +2517,7 @@ void renderOctree(LLSpatialGroup* group)
//coded by buffer usage and activity
gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
LLVector4 col;
- if (group->mBuilt > 0.f)
+ /*if (group->mBuilt > 0.f)
{
group->mBuilt -= 2.f * gFrameIntervalSeconds;
if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
@@ -2610,7 +2586,7 @@ void renderOctree(LLSpatialGroup* group)
gGL.color4f(1,1,1,1);
}
}
- else
+ else*/
{
if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty()
&& group->mSpatialPartition->mRenderByGroup)
@@ -2630,33 +2606,24 @@ void renderOctree(LLSpatialGroup* group)
size.mul(1.01f);
size.add(fudge);
- {
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- drawBox(group->mObjectBounds[0], fudge);
- }
+ //{
+ // LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ // drawBox(group->mObjectBounds[0], fudge);
+ //}
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- if (group->mBuilt <= 0.f)
+ //if (group->mBuilt <= 0.f)
{
//draw opaque outline
- gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
- drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
+ //gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
+ //drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
- if (group->mOctreeNode->isLeaf())
- {
- gGL.color4f(1,1,1,1);
- }
- else
- {
- gGL.color4f(0,1,1,1);
- }
-
+ gGL.color4f(0,1,1,1);
drawBoxOutline(group->mBounds[0],group->mBounds[1]);
-
-
+
//draw bounding box for draw info
- if (group->mSpatialPartition->mRenderByGroup)
+ /*if (group->mSpatialPartition->mRenderByGroup)
{
gGL.color4f(1.0f, 0.75f, 0.25f, 0.6f);
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -2673,7 +2640,7 @@ void renderOctree(LLSpatialGroup* group)
drawBoxOutline(center, size);
}
}
- }
+ }*/
}
// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
@@ -2716,7 +2683,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
gGL.color4f(0.f, 0.75f, 0.f, 0.5f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
}
- else if (camera && group->mOcclusionVerts.notNull())
+ /*else if (camera && group->mOcclusionVerts.notNull())
{
LLVertexBuffer::unbind();
group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
@@ -2728,7 +2695,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
glColor4f(1.0f, 1.f, 1.f, 1.0f);
group->mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, group->mBounds[0]));
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
+ }*/
}
}
@@ -2818,7 +2785,7 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
gGL.color4f(0,1,1,1);
break;
case LLViewerObject::LL_VO_CLOUDS:
- gGL.color4f(0.5f,0.5f,0.5f,1.0f);
+ // no longer used
break;
case LLViewerObject::LL_VO_PART_GROUP:
case LLViewerObject::LL_VO_HUD_PART_GROUP:
@@ -3002,13 +2969,6 @@ void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColo
void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
{
- if (volume->isSelected())
- {
- LLVector3 construct_me(5,5,5);
- construct_me.normalize();
- }
-
-
U8 physics_type = volume->getPhysicsShapeType();
if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible())
@@ -3473,6 +3433,8 @@ void renderTextureAnim(LLDrawInfo* params)
void renderBatchSize(LLDrawInfo* params)
{
+ LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.f, 1.f);
glColor3ubv((GLubyte*) &(params->mDebugColor));
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
}
@@ -3910,6 +3872,28 @@ public:
renderAgentTarget(avatar);
}
+ if (gDebugGL)
+ {
+ for (U32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* facep = drawable->getFace(i);
+ U8 index = facep->getTextureIndex();
+ if (facep->mDrawInfo)
+ {
+ if (index < 255)
+ {
+ if (facep->mDrawInfo->mTextureList.size() <= index)
+ {
+ llerrs << "Face texture index out of bounds." << llendl;
+ }
+ else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture())
+ {
+ llerrs << "Face texture index incorrect." << llendl;
+ }
+ }
+ }
+ }
+ }
}
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -4282,7 +4266,29 @@ public:
if (vobj)
{
LLVector3 intersection;
- if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
+ bool skip_check = false;
+ if (vobj->isAvatar())
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*) vobj;
+ if (avatar->isSelf() && LLFloater::isVisible(gFloaterTools))
+ {
+ LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal);
+ if (hit)
+ {
+ mEnd = intersection;
+ if (mIntersection)
+ {
+ *mIntersection = intersection;
+ }
+
+ mHit = hit->mDrawable;
+ skip_check = true;
+ }
+
+ }
+ }
+
+ if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
{
mEnd = intersection; // shorten ray so we only find CLOSER hits
if (mIntersection)
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 0d9cad914a..54d5d36f6e 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -91,6 +91,8 @@ public:
LLPointer<LLVertexBuffer> mVertexBuffer;
LLPointer<LLViewerTexture> mTexture;
+ std::vector<LLPointer<LLViewerTexture> > mTextureList;
+
LLColor4U mGlowColor;
S32 mDebugColor;
const LLMatrix4* mTextureMatrix;
@@ -207,7 +209,7 @@ public:
typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t;
typedef std::map<U32, drawmap_elem_t > draw_map_t;
typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t;
- typedef std::map<LLPointer<LLViewerTexture>, buffer_list_t> buffer_texture_map_t;
+ typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t;
typedef std::map<U32, buffer_texture_map_t> buffer_map_t;
typedef LLOctreeListener<LLDrawable> BaseType;
@@ -399,7 +401,7 @@ protected:
public:
bridge_list_t mBridgeList;
- buffer_map_t mBufferMap; //used by volume buffers to store unique buffers per texture
+ buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
F32 mBuilt;
OctreeNode* mOctreeNode;
@@ -662,13 +664,6 @@ public:
LLGrassPartition();
};
-//spatial partition for clouds (implemented in LLVOClouds.cpp)
-class LLCloudPartition : public LLParticlePartition
-{
-public:
- LLCloudPartition();
-};
-
//class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp)
class LLVolumeGeometryManager: public LLGeometryManager
{
@@ -684,7 +679,7 @@ class LLVolumeGeometryManager: public LLGeometryManager
virtual void rebuildGeom(LLSpatialGroup* group);
virtual void rebuildMesh(LLSpatialGroup* group);
virtual void getGeometry(LLSpatialGroup* group);
- void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE);
+ void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE);
void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
};
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 141a81c717..4dfcb85295 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -76,6 +76,7 @@
#include "lluserrelations.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
+#include "llviewerhelp.h"
#include "llvfs.h"
#include "llxorcipher.h" // saved password, MAC address
#include "llwindow.h"
@@ -163,7 +164,6 @@
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
-#include "llvoclouds.h"
#include "llweb.h"
#include "llworld.h"
#include "llworldmapmessage.h"
@@ -1171,8 +1171,6 @@ bool idle_startup()
// init the shader managers
LLPostProcess::initClass();
- LLWLParamManager::initClass();
- LLWaterParamManager::initClass();
LLViewerObject::initVOClasses();
@@ -1692,11 +1690,22 @@ bool idle_startup()
gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
}
+ if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin"))
+ {
+ gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+ }
+
// Set the show start location to true, now that the user has logged
// on with this install.
gSavedSettings.setBOOL("ShowStartLocation", TRUE);
}
+ if (gSavedSettings.getBOOL("HelpFloaterOpen"))
+ {
+ // show default topic
+ LLViewerHelp::instance().showTopic("");
+ }
+
// We're successfully logged in.
gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
@@ -1953,7 +1962,8 @@ bool idle_startup()
gViewerWindow->getWindow()->resetBusyCount();
gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL;
- gViewerWindow->setShowProgress(FALSE);
+ gViewerWindow->revealIntroPanel();
+ //gViewerWindow->setShowProgress(FALSE); // reveal intro video now handles this
gViewerWindow->setProgressCancelButtonVisible(FALSE);
// We're not away from keyboard, even though login might have taken
@@ -1970,7 +1980,6 @@ bool idle_startup()
// Start automatic replay if the flag is set.
if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession())
{
- LLUUID id;
LL_DEBUGS("AppInit") << "Starting automatic playback" << LL_ENDL;
gAgentPilot.startPlayback();
}
@@ -3151,11 +3160,6 @@ bool process_login_success_response()
gMoonTextureID = id;
}
- id = global_textures["cloud_texture_id"];
- if(id.notNull())
- {
- gCloudTextureID = id;
- }
}
// Set the location of the snapshot sharing config endpoint
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 500c2a7b86..bd41aa64f0 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -51,6 +51,9 @@
using namespace LLVOAvatarDefines;
+static const S32 BAKE_UPLOAD_ATTEMPTS = 7;
+static const F32 BAKE_UPLOAD_RETRY_DELAY = 2.f; // actual delay grows by power of 2 each attempt
+
class LLTexLayerInfo
{
friend class LLTexLayer;
@@ -93,11 +96,13 @@ private:
//-----------------------------------------------------------------------------
LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
LLTexLayerSet* layerset,
- const LLUUID& id) :
+ const LLUUID& id,
+ bool highest_res) :
mAvatar(avatar),
mTexLayerSet(layerset),
mID(id),
- mStartTime(LLFrameTimer::getTotalTime()) // Record starting time
+ mStartTime(LLFrameTimer::getTotalTime()), // Record starting time
+ mIsHighestRes(highest_res)
{
}
@@ -116,6 +121,7 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
mUploadPending(FALSE), // Not used for any logic here, just to sync sending of updates
mNeedsUpload(FALSE),
mNumLowresUploads(0),
+ mUploadFailCount(0),
mNeedsUpdate(TRUE),
mNumLowresUpdates(0),
mTexLayerSet(owner)
@@ -204,6 +210,7 @@ void LLTexLayerSetBuffer::cancelUpload()
mNeedsUpload = FALSE;
mUploadPending = FALSE;
mNeedsUploadTimer.pause();
+ mUploadRetryTimer.reset();
}
void LLTexLayerSetBuffer::pushProjection() const
@@ -356,25 +363,38 @@ BOOL LLTexLayerSetBuffer::isReadyToUpload() const
if (!gAgentQueryManager.hasNoPendingQueries()) return FALSE; // Can't upload if there are pending queries.
if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures()) return FALSE; // Don't upload if avatar is using composites.
- // If we requested an upload and have the final LOD ready, then upload.
- if (mTexLayerSet->isLocalTextureDataFinal()) return TRUE;
-
- // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure
- // we aren't doing uploads too frequently.
- const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
- if (texture_timeout != 0)
+ BOOL ready = FALSE;
+ if (mTexLayerSet->isLocalTextureDataFinal())
+ {
+ // If we requested an upload and have the final LOD ready, upload (or wait a while if this is a retry)
+ if (mUploadFailCount == 0)
+ {
+ ready = TRUE;
+ }
+ else
+ {
+ ready = mUploadRetryTimer.getElapsedTimeF32() >= BAKE_UPLOAD_RETRY_DELAY * (1 << (mUploadFailCount - 1));
+ }
+ }
+ else
{
- // The timeout period increases exponentially between every lowres upload in order to prevent
- // spamming the server with frequent uploads.
- const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
+ // Upload if we've hit a timeout. Upload is a pretty expensive process so we need to make sure
+ // we aren't doing uploads too frequently.
+ const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureUploadTimeout");
+ if (texture_timeout != 0)
+ {
+ // The timeout period increases exponentially between every lowres upload in order to prevent
+ // spamming the server with frequent uploads.
+ const U32 texture_timeout_threshold = texture_timeout*(1 << mNumLowresUploads);
- // If we hit our timeout and have textures available at even lower resolution, then upload.
- const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
- const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
- if (has_lower_lod && is_upload_textures_timeout) return TRUE;
+ // If we hit our timeout and have textures available at even lower resolution, then upload.
+ const BOOL is_upload_textures_timeout = mNeedsUploadTimer.getElapsedTimeF32() >= texture_timeout_threshold;
+ const BOOL has_lower_lod = mTexLayerSet->isLocalTextureDataAvailable();
+ ready = has_lower_lod && is_upload_textures_timeout;
+ }
}
- return FALSE;
+ return ready;
}
BOOL LLTexLayerSetBuffer::isReadyToUpdate() const
@@ -482,17 +502,20 @@ void LLTexLayerSetBuffer::doUpload()
if (valid)
{
+ const bool highest_lod = mTexLayerSet->isLocalTextureDataFinal();
// Baked_upload_data is owned by the responder and deleted after the request completes.
LLBakedUploadData* baked_upload_data = new LLBakedUploadData(gAgentAvatarp,
this->mTexLayerSet,
- asset_id);
+ asset_id,
+ highest_lod);
// upload ID is used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
mUploadID = asset_id;
// Upload the image
const std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
if(!url.empty()
- && !LLPipeline::sForceOldBakedUpload) // toggle debug setting UploadBakedTexOld to change between the new caps method and old method
+ && !LLPipeline::sForceOldBakedUpload // toggle debug setting UploadBakedTexOld to change between the new caps method and old method
+ && (mUploadFailCount < (BAKE_UPLOAD_ATTEMPTS - 1))) // Try last ditch attempt via asset store if cap upload is failing.
{
LLSD body = LLSD::emptyMap();
// The responder will call LLTexLayerSetBuffer::onTextureUploadComplete()
@@ -511,7 +534,6 @@ void LLTexLayerSetBuffer::doUpload()
llinfos << "Baked texture upload via Asset Store." << llendl;
}
- const BOOL highest_lod = mTexLayerSet->isLocalTextureDataFinal();
if (highest_lod)
{
// Sending the final LOD for the baked texture. All done, pause
@@ -603,14 +625,15 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
{
LLBakedUploadData* baked_upload_data = (LLBakedUploadData*)userdata;
- if ((result == 0) &&
- isAgentAvatarValid() &&
+ if (isAgentAvatarValid() &&
!gAgentAvatarp->isDead() &&
(baked_upload_data->mAvatar == gAgentAvatarp) && // Sanity check: only the user's avatar should be uploading textures.
(baked_upload_data->mTexLayerSet->hasComposite()))
{
LLTexLayerSetBuffer* layerset_buffer = baked_upload_data->mTexLayerSet->getComposite();
-
+ S32 failures = layerset_buffer->mUploadFailCount;
+ layerset_buffer->mUploadFailCount = 0;
+
if (layerset_buffer->mUploadID.isNull())
{
// The upload got canceled, we should be in the
@@ -626,20 +649,28 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
{
// This is the upload we're currently waiting for.
layerset_buffer->mUploadID.setNull();
+ const std::string name(baked_upload_data->mTexLayerSet->getBodyRegionName());
+ const std::string resolution = baked_upload_data->mIsHighestRes ? " full res " : " low res ";
if (result >= 0)
{
- layerset_buffer->mUploadPending = FALSE;
+ layerset_buffer->mUploadPending = FALSE; // Allows sending of AgentSetAppearance later
LLVOAvatarDefines::ETextureIndex baked_te = gAgentAvatarp->getBakedTE(layerset_buffer->mTexLayerSet);
// Update baked texture info with the new UUID
U64 now = LLFrameTimer::getTotalTime(); // Record starting time
- llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
+ llinfos << "Baked" << resolution << "texture upload for " << name << " took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
gAgentAvatarp->setNewBakedTexture(baked_te, uuid);
}
else
{
- // Avatar appearance is changing, ignore the upload results
- llinfos << "Baked upload failed. Reason: " << result << llendl;
- // *FIX: retry upload after n seconds, asset server could be busy
+ ++failures;
+ S32 max_attempts = baked_upload_data->mIsHighestRes ? BAKE_UPLOAD_ATTEMPTS : 1; // only retry final bakes
+ llwarns << "Baked" << resolution << "texture upload for " << name << " failed (attempt " << failures << "/" << max_attempts << ")" << llendl;
+ if (failures < max_attempts)
+ {
+ layerset_buffer->mUploadFailCount = failures;
+ layerset_buffer->mUploadRetryTimer.start();
+ layerset_buffer->requestUpload();
+ }
}
}
else
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 2d710d2dce..85dadb213c 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -312,6 +312,8 @@ private:
BOOL mUploadPending; // Whether we have received back the new baked textures
LLUUID mUploadID; // The current upload process (null if none).
LLFrameTimer mNeedsUploadTimer; // Tracks time since upload was requested and performed.
+ S32 mUploadFailCount; // Number of consecutive upload failures
+ LLFrameTimer mUploadRetryTimer; // Tracks time since last upload failure.
//--------------------------------------------------------------------
// Updates
@@ -363,12 +365,14 @@ struct LLBakedUploadData
{
LLBakedUploadData(const LLVOAvatarSelf* avatar,
LLTexLayerSet* layerset,
- const LLUUID& id);
+ const LLUUID& id,
+ bool highest_res);
~LLBakedUploadData() {}
const LLUUID mID;
const LLVOAvatarSelf* mAvatar; // note: backlink only; don't LLPointer
LLTexLayerSet* mTexLayerSet;
const U64 mStartTime; // for measuring baked texture upload time
+ const bool mIsHighestRes; // whether this is a "final" bake, or intermediate low res
};
#endif // LL_LLTEXLAYER_H
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 7fb52c1939..9b417307fd 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -949,7 +949,7 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache
max_size -= sCacheMaxTexturesSize;
LL_INFOS("TextureCache") << "Headers: " << sCacheMaxEntries
- << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << LL_ENDL;
+ << " Textures size: " << sCacheMaxTexturesSize / (1024 * 1024) << " MB" << LL_ENDL;
setDirNames(location);
@@ -1513,12 +1513,12 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
{
const char* subdirs = "0123456789abcdef";
std::string delem = gDirUtilp->getDirDelimiter();
- std::string mask = delem + "*";
+ std::string mask = "*";
for (S32 i=0; i<16; i++)
{
std::string dirname = mTexturesDirName + delem + subdirs[i];
llinfos << "Deleting files in directory: " << dirname << llendl;
- gDirUtilp->deleteFilesInDir(dirname,mask);
+ gDirUtilp->deleteFilesInDir(dirname, mask);
if (purge_directories)
{
LLFile::rmdir(dirname);
@@ -1655,7 +1655,7 @@ void LLTextureCache::purgeTextures(bool validate)
LL_INFOS("TextureCache") << "TEXTURE CACHE:"
<< " PURGED: " << purge_count
<< " ENTRIES: " << num_entries
- << " CACHE SIZE: " << mTexturesSizeTotal / 1024*1024 << " MB"
+ << " CACHE SIZE: " << mTexturesSizeTotal / (1024 * 1024) << " MB"
<< llendl;
}
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 1023a4339b..de22f2ae6b 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -420,7 +420,6 @@ BOOL LLFloaterTexturePicker::postBuild()
mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mInventoryPanel->setAllowMultiSelect(FALSE);
// Disable auto selecting first filtered item because it takes away
// selection from the item set by LLTextureCtrl owning this floater.
@@ -1093,7 +1092,7 @@ public:
BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask)
{
- getWindow()->setCursor(UI_CURSOR_HAND);
+ getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW);
return TRUE;
}
@@ -1102,7 +1101,7 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = LLUICtrl::handleMouseDown( x, y , mask );
- if( !handled )
+ if (!handled && mBorder->parentPointInView(x, y))
{
showPicker(FALSE);
//grab textures first...
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index b6c0f662e5..319e2508e0 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -54,7 +54,6 @@
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
-#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llworld.h"
@@ -387,22 +386,7 @@ void LLToolGrab::startGrab()
mDragStartPointGlobal = grab_start_global;
mDragStartFromCamera = grab_start_global - gAgentCamera.getCameraPositionGlobal();
- LLMessageSystem *msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ObjectGrab);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
- msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset );
- msg->nextBlock("SurfaceInfo");
- msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
- msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
- msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace);
- msg->addVector3("Position", mGrabPick.mIntersection);
- msg->addVector3("Normal", mGrabPick.mNormal);
- msg->addVector3("Binormal", mGrabPick.mBinormal);
- msg->sendMessage( objectp->getRegion()->getHost());
+ send_ObjectGrab_message(objectp, mGrabPick, grab_offset);
mGrabOffsetFromCenterInitial = grab_offset;
mGrabHiddenOffsetFromCamera = mDragStartFromCamera;
@@ -1036,28 +1020,12 @@ void LLToolGrab::stopGrab()
}
// Next, send messages to simulator
- LLMessageSystem *msg = gMessageSystem;
switch(mMode)
{
case GRAB_ACTIVE_CENTER:
case GRAB_NONPHYSICAL:
case GRAB_LOCKED:
- msg->newMessageFast(_PREHASH_ObjectDeGrab);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
- msg->nextBlock("SurfaceInfo");
- msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
- msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
- msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
- msg->addVector3("Position", pick.mIntersection);
- msg->addVector3("Normal", pick.mNormal);
- msg->addVector3("Binormal", pick.mBinormal);
-
- msg->sendMessage(objectp->getRegion()->getHost());
-
+ send_ObjectDeGrab_message(objectp, pick);
mVerticalDragging = FALSE;
break;
@@ -1109,3 +1077,66 @@ LLVector3d LLToolGrab::getGrabPointGlobal()
return gAgent.getPositionGlobal();
}
}
+
+
+void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, const LLVector3 &grab_offset)
+{
+ if (!object) return;
+
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_ObjectGrab);
+ msg->nextBlockFast( _PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast( _PREHASH_ObjectData);
+ msg->addU32Fast( _PREHASH_LocalID, object->mLocalID);
+ msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset);
+ msg->nextBlock("SurfaceInfo");
+ msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
+ msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
+ msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
+ msg->addVector3("Position", pick.mIntersection);
+ msg->addVector3("Normal", pick.mNormal);
+ msg->addVector3("Binormal", pick.mBinormal);
+ msg->sendMessage( object->getRegion()->getHost());
+
+ /* Diagnostic code
+ llinfos << "mUVCoords: " << pick.mUVCoords
+ << ", mSTCoords: " << pick.mSTCoords
+ << ", mObjectFace: " << pick.mObjectFace
+ << ", mIntersection: " << pick.mIntersection
+ << ", mNormal: " << pick.mNormal
+ << ", mBinormal: " << pick.mBinormal
+ << llendl;
+
+ llinfos << "Avatar pos: " << gAgent.getPositionAgent() << llendl;
+ llinfos << "Object pos: " << object->getPosition() << llendl;
+ */
+}
+
+
+void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick)
+{
+ if (!object) return;
+
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_ObjectDeGrab);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
+ msg->nextBlock("SurfaceInfo");
+ msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
+ msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
+ msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
+ msg->addVector3("Position", pick.mIntersection);
+ msg->addVector3("Normal", pick.mNormal);
+ msg->addVector3("Binormal", pick.mBinormal);
+ msg->sendMessage(object->getRegion()->getHost());
+}
+
+
+
diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h
index 61e3fcb8b2..06a3b662c8 100644
--- a/indra/newview/lltoolgrab.h
+++ b/indra/newview/lltoolgrab.h
@@ -39,6 +39,13 @@ class LLTextBox;
class LLViewerObject;
class LLPickInfo;
+
+// Message utilities
+void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, const LLVector3 &grab_offset);
+void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick);
+
+
+
class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab>
{
public:
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 9ec4d33036..c38c8bad80 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -639,6 +639,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
if (click_action == CLICK_ACTION_NONE // not doing 1-click action
&& gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled
&& !gAgent.getFlying() // don't auto-navigate while flying until that works
+ && gAgentAvatarp
&& !gAgentAvatarp->isSitting()
&& !mBlockClickToWalk // another behavior hasn't cancelled click to walk
&& !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 2de7db38ed..2f60b6b90b 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -28,6 +28,8 @@
#include "lltranslate.h"
+#include <curl/curl.h>
+
#include "llbufferstream.h"
#include "llui.h"
#include "llversioninfo.h"
@@ -76,7 +78,9 @@ void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std
//static
void LLTranslate::getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
{
- std::string escaped_mesg = curl_escape(mesg.c_str(), mesg.size());
+ char * curl_str = curl_escape(mesg.c_str(), mesg.size());
+ std::string const escaped_mesg(curl_str);
+ curl_free(curl_str);
translate_url = m_GoogleURL
+ escaped_mesg + m_GoogleLangSpec
diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp
index e06fe7bda0..93687dbd5f 100644
--- a/indra/newview/llviewerchat.cpp
+++ b/indra/newview/llviewerchat.cpp
@@ -80,6 +80,10 @@ void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color)
{
r_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor");
}
+ else if ( chat.mChatType == CHAT_TYPE_DIRECT )
+ {
+ r_color = LLUIColorTable::instance().getColor("DirectChatColor");
+ }
else
{
r_color = LLUIColorTable::instance().getColor("ObjectChatColor");
@@ -146,6 +150,10 @@ void LLViewerChat::getChatColor(const LLChat& chat, std::string& r_color_name, F
{
r_color_name = "llOwnerSayChatColor";
}
+ else if ( chat.mChatType == CHAT_TYPE_DIRECT )
+ {
+ r_color_name = "DirectChatColor";
+ }
else
{
r_color_name = "ObjectChatColor";
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 379bbe614d..87ca80260f 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -57,6 +57,7 @@
#include "llworld.h"
#include "pipeline.h"
#include "llviewerjoystick.h"
+#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
#include "llparcel.h"
#include "llkeyboard.h"
@@ -183,6 +184,21 @@ static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
return true;
}
+static bool handleFSAASamplesChanged(const LLSD& newvalue)
+{
+ if (gPipeline.isInit())
+ {
+ gPipeline.releaseGLBuffers();
+ gPipeline.createGLBuffers();
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ LLViewerShaderMgr::instance()->setShaders();
+ }
+ }
+ return true;
+}
+
static bool handleAnisotropicChanged(const LLSD& newvalue)
{
LLImageGL::sGlobalUseAnisotropic = newvalue.asBoolean();
@@ -357,6 +373,16 @@ static bool handleResetVertexBuffersChanged(const LLSD&)
return true;
}
+static bool handleRepartition(const LLSD&)
+{
+ if (gPipeline.isInit())
+ {
+ gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+ gObjectList.repartitionObjects();
+ }
+ return true;
+}
+
static bool handleRenderDynamicLODChanged(const LLSD& newvalue)
{
LLPipeline::sDynamicLOD = newvalue.asBoolean();
@@ -560,6 +586,12 @@ void settings_setup_listeners()
gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2));
gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _2));
gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _2));
+ gSavedSettings.getControl("OctreeStaticObjectSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+ gSavedSettings.getControl("OctreeDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+ gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+ gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+ gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2));
+ gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
@@ -568,7 +600,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
- gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+ gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleFSAASamplesChanged, _2));
gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2));
gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index e41773d273..911fc8e1ed 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -178,8 +178,8 @@ void display_update_camera()
gViewerWindow->setup3DRender();
// update all the sky/atmospheric/water settings
- LLWLParamManager::instance()->update(LLViewerCamera::getInstance());
- LLWaterParamManager::instance()->update(LLViewerCamera::getInstance());
+ LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
+ LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
// Update land visibility too
LLWorld::getInstance()->setLandFarClip(final_far);
@@ -582,6 +582,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
gPipeline.createObjects(max_geom_update_time);
+ gPipeline.processPartitionQ();
gPipeline.updateGeom(max_geom_update_time);
stop_glerror();
}
@@ -836,7 +837,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
gPipeline.mDeferredScreen.bindTarget();
- glClearColor(0,0,0,0);
+ glClearColor(1,0,1,1);
gPipeline.mDeferredScreen.clear();
}
else
@@ -995,8 +996,7 @@ void render_hud_attachments()
S32 use_occlusion = LLPipeline::sUseOcclusion;
LLPipeline::sUseOcclusion = 0;
- LLPipeline::sDisableShaders = TRUE;
-
+
//cull, sort, and render hud objects
static LLCullResult result;
LLSpatialGroup::sNoDelete = TRUE;
@@ -1036,7 +1036,6 @@ void render_hud_attachments()
gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
}
LLPipeline::sUseOcclusion = use_occlusion;
- LLPipeline::sDisableShaders = FALSE;
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index a1c2c926af..6ae8e79be4 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -48,11 +48,14 @@
#include "llfloaterbulkpermission.h"
#include "llfloaterbump.h"
#include "llfloatercamera.h"
-#include "llfloaterdaycycle.h"
+#include "llfloaterdeleteenvpreset.h"
#include "llfloaterdisplayname.h"
+#include "llfloatereditdaycycle.h"
+#include "llfloatereditsky.h"
+#include "llfloatereditwater.h"
+#include "llfloaterenvironmentsettings.h"
#include "llfloaterevent.h"
#include "llfloatersearch.h"
-#include "llfloaterenvsettings.h"
#include "llfloaterfonttest.h"
#include "llfloatergesture.h"
#include "llfloatergodtools.h"
@@ -101,9 +104,7 @@
#include "llfloatertopobjects.h"
#include "llfloateruipreview.h"
#include "llfloatervoiceeffect.h"
-#include "llfloaterwater.h"
#include "llfloaterwhitelistentry.h"
-#include "llfloaterwindlight.h"
#include "llfloaterwindowsize.h"
#include "llfloaterworldmap.h"
#include "llimfloatercontainer.h"
@@ -179,11 +180,12 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);
- LLFloaterReg::add("env_day_cycle", "floater_day_cycle_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDayCycle>);
LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
- LLFloaterReg::add("env_settings", "floater_env_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvSettings>);
- LLFloaterReg::add("env_water", "floater_water.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWater>);
- LLFloaterReg::add("env_windlight", "floater_windlight_options.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWindLight>);
+ LLFloaterReg::add("env_settings", "floater_environment_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentSettings>);
+ LLFloaterReg::add("env_delete_preset", "floater_delete_env_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeleteEnvPreset>);
+ LLFloaterReg::add("env_edit_sky", "floater_edit_sky_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditSky>);
+ LLFloaterReg::add("env_edit_water", "floater_edit_water_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditWater>);
+ LLFloaterReg::add("env_edit_day_cycle", "floater_edit_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditDayCycle>);
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 42f780a8a3..9101222393 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -128,8 +128,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE));
addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "Inv_SysOpen", "Inv_SysClosed", FALSE));
-
addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE));
+ addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE));
+
+ addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE));
addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, "default"));
diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp
index 9fe8c142b9..3a3d4f3881 100644
--- a/indra/newview/llviewerhelp.cpp
+++ b/indra/newview/llviewerhelp.cpp
@@ -101,8 +101,9 @@ void LLViewerHelp::showTopic(const std::string &topic)
// work out the URL for this topic and display it
showHelp();
+
std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic );
- setRawURL( helpURL );
+ setRawURL(helpURL);
}
std::string LLViewerHelp::defaultTopic()
@@ -148,18 +149,7 @@ std::string LLViewerHelp::getTopicFromFocus()
// static
void LLViewerHelp::showHelp()
{
- LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
- if (helpbrowser)
- {
- BOOL visible = TRUE;
- BOOL take_focus = TRUE;
- helpbrowser->setVisible(visible);
- helpbrowser->setFrontmost(take_focus);
- }
- else
- {
- llwarns << "Eep, help_browser floater not found" << llendl;
- }
+ LLFloaterReg::showInstance("help_browser");
}
// static
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 9e58acdcd3..22666cec0d 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1269,7 +1269,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons
{
std::string type_name = userdata.asString();
- if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+ if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
{
LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 79c6c8db75..1be58eae45 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -62,9 +62,12 @@
#include "llmutelist.h"
#include "llpanelprofile.h"
#include "llappviewer.h"
+#include "lllogininstance.h"
//#include "llfirstuse.h"
+#include "llviewernetwork.h"
#include "llwindow.h"
+
#include "llfloatermediabrowser.h" // for handling window close requests and geometry change requests in media browser windows.
#include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows.
@@ -1359,6 +1362,34 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
}
+class LLInventoryUserStatusResponder : public LLHTTPClient::Responder
+{
+public:
+ LLInventoryUserStatusResponder()
+ : LLCurl::Responder()
+ {
+ }
+
+ void completed(U32 status, const std::string& reason, const LLSD& content)
+ {
+ if (isGoodStatus(status))
+ {
+ // Complete success
+ gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+ }
+ else if (status == 401)
+ {
+ // API is available for use but OpenID authorization failed
+ gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+ }
+ else
+ {
+ // API in unavailable
+ llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl;
+ }
+ }
+};
+
/////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::setOpenIDCookie()
@@ -1405,6 +1436,25 @@ void LLViewerMedia::setOpenIDCookie()
LLHTTPClient::get(profile_url,
new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
headers);
+
+ std::string url = "https://marketplace.secondlife.com/";
+
+ if (!LLGridManager::getInstance()->isInProductionGrid())
+ {
+ std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
+ url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
+ }
+
+ url += "api/1/users/";
+ url += gAgent.getID().getString();
+ url += "/user_status";
+
+ headers = LLSD::emptyMap();
+ headers["Accept"] = "*/*";
+ headers["Cookie"] = sOpenIDCookie;
+ headers["User-Agent"] = getCurrentUserAgent();
+
+ LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), headers);
}
}
@@ -2343,6 +2393,64 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
}
//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::updateJavascriptObject()
+{
+ if ( mMediaSource )
+ {
+ // flag to expose this information to internal browser or not.
+ bool enable = gSavedSettings.getBOOL("BrowserEnableJSObject");
+ mMediaSource->jsEnableObject( enable );
+
+ // these values are only menaingful after login so don't set them before
+ bool logged_in = LLLoginInstance::getInstance()->authSuccess();
+ if ( logged_in )
+ {
+ // current location within a region
+ LLVector3 agent_pos = gAgent.getPositionAgent();
+ double x = agent_pos.mV[ VX ];
+ double y = agent_pos.mV[ VY ];
+ double z = agent_pos.mV[ VZ ];
+ mMediaSource->jsAgentLocationEvent( x, y, z );
+
+ // current location within the grid
+ LLVector3d agent_pos_global = gAgent.getLastPositionGlobal();
+ double global_x = agent_pos_global.mdV[ VX ];
+ double global_y = agent_pos_global.mdV[ VY ];
+ double global_z = agent_pos_global.mdV[ VZ ];
+ mMediaSource->jsAgentGlobalLocationEvent( global_x, global_y, global_z );
+
+ // current agent orientation
+ double rotation = atan2( gAgent.getAtAxis().mV[VX], gAgent.getAtAxis().mV[VY] );
+ double angle = rotation * RAD_TO_DEG;
+ if ( angle < 0.0f ) angle = 360.0f + angle; // TODO: has to be a better way to get orientation!
+ mMediaSource->jsAgentOrientationEvent( angle );
+
+ // current region agent is in
+ std::string region_name("");
+ LLViewerRegion* region = gAgent.getRegion();
+ if ( region )
+ {
+ region_name = region->getName();
+ };
+ mMediaSource->jsAgentRegionEvent( region_name );
+ }
+
+ // language code the viewer is set to
+ mMediaSource->jsAgentLanguageEvent( LLUI::getLanguage() );
+
+ // maturity setting the agent has selected
+ if ( gAgent.prefersAdult() )
+ mMediaSource->jsAgentMaturityEvent( "GMA" ); // Adult means see adult, mature and general content
+ else
+ if ( gAgent.prefersMature() )
+ mMediaSource->jsAgentMaturityEvent( "GM" ); // Mature means see mature and general content
+ else
+ if ( gAgent.prefersPG() )
+ mMediaSource->jsAgentMaturityEvent( "G" ); // PG means only see General content
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
std::string LLViewerMediaImpl::getName() const
{
if (mMediaSource)
@@ -2640,6 +2748,9 @@ void LLViewerMediaImpl::update()
{
updateVolume();
+ // TODO: this is updated every frame - is this bad?
+ updateJavascriptObject();
+
// If we didn't just create the impl, it may need to get cookie updates.
if(!sUpdatedCookies.empty())
{
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index e2e342cc45..a70c6f4887 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -339,7 +339,10 @@ public:
LLVOVolume *getSomeObject();
void setUpdated(BOOL updated) ;
BOOL isUpdated() ;
-
+
+ // updates the javascript object in the embedded browser with viewer values
+ void updateJavascriptObject();
+
// Updates the "interest" value in this object
void calculateInterest();
F64 getInterest() const { return mInterest; };
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2ed208bad1..a37f8ad0d8 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -45,6 +45,7 @@
#include "llcompilequeue.h"
#include "llconsole.h"
#include "lldebugview.h"
+#include "llenvmanager.h"
#include "llfilepicker.h"
#include "llfirstuse.h"
#include "llfloaterbuy.h"
@@ -106,6 +107,8 @@
#include "llappearancemgr.h"
#include "lltrans.h"
#include "lleconomy.h"
+#include "lltoolgrab.h"
+#include "llwindow.h"
#include "boost/unordered_map.hpp"
using namespace LLVOAvatarDefines;
@@ -2420,50 +2423,23 @@ class LLObjectEnableReportAbuse : public view_listener_t
}
};
+
void handle_object_touch()
{
- LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
- if (!object) return;
-
- LLPickInfo pick = LLToolPie::getInstance()->getPick();
+ LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (!object) return;
- LLMessageSystem *msg = gMessageSystem;
+ LLPickInfo pick = LLToolPie::getInstance()->getPick();
- msg->newMessageFast(_PREHASH_ObjectGrab);
- msg->nextBlockFast( _PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast( _PREHASH_ObjectData);
- msg->addU32Fast( _PREHASH_LocalID, object->mLocalID);
- msg->addVector3Fast(_PREHASH_GrabOffset, LLVector3::zero );
- msg->nextBlock("SurfaceInfo");
- msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
- msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
- msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
- msg->addVector3("Position", pick.mIntersection);
- msg->addVector3("Normal", pick.mNormal);
- msg->addVector3("Binormal", pick.mBinormal);
- msg->sendMessage( object->getRegion()->getHost());
-
- // *NOTE: Hope the packets arrive safely and in order or else
- // there will be some problems.
- // *TODO: Just fix this bad assumption.
- msg->newMessageFast(_PREHASH_ObjectDeGrab);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
- msg->nextBlock("SurfaceInfo");
- msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
- msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
- msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
- msg->addVector3("Position", pick.mIntersection);
- msg->addVector3("Normal", pick.mNormal);
- msg->addVector3("Binormal", pick.mBinormal);
- msg->sendMessage(object->getRegion()->getHost());
+ // *NOTE: Hope the packets arrive safely and in order or else
+ // there will be some problems.
+ // *TODO: Just fix this bad assumption.
+ send_ObjectGrab_message(object, pick, LLVector3::zero);
+ send_ObjectDeGrab_message(object, pick);
}
+
+
static void init_default_item_label(const std::string& item_name)
{
boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
@@ -7608,74 +7584,85 @@ class LLWorldEnvSettings : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
std::string tod = userdata.asString();
- LLVector3 sun_direction;
if (tod == "editor")
{
- // if not there or is hidden, show it
LLFloaterReg::toggleInstance("env_settings");
return true;
}
-
+
if (tod == "sunrise")
{
- // set the value, turn off animation
- LLWLParamManager::instance()->mAnimator.setDayTime(0.25);
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- // then call update once
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
+ LLEnvManagerNew::instance().setUseSkyPreset("Sunrise");
}
else if (tod == "noon")
{
- // set the value, turn off animation
- LLWLParamManager::instance()->mAnimator.setDayTime(0.567);
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- // then call update once
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
+ LLEnvManagerNew::instance().setUseSkyPreset("Midday");
}
else if (tod == "sunset")
{
- // set the value, turn off animation
- LLWLParamManager::instance()->mAnimator.setDayTime(0.75);
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- // then call update once
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
+ LLEnvManagerNew::instance().setUseSkyPreset("Sunset");
}
else if (tod == "midnight")
{
- // set the value, turn off animation
- LLWLParamManager::instance()->mAnimator.setDayTime(0.0);
- LLWLParamManager::instance()->mAnimator.mIsRunning = false;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
- // then call update once
- LLWLParamManager::instance()->mAnimator.update(
- LLWLParamManager::instance()->mCurParams);
+ LLEnvManagerNew::instance().setUseSkyPreset("Midnight");
}
else
{
- LLWLParamManager::instance()->mAnimator.mIsRunning = true;
- LLWLParamManager::instance()->mAnimator.mUseLindenTime = true;
+ LLEnvManagerNew::instance().setUseDayCycle(LLEnvManagerNew::instance().getDayCycleName());
}
+
return true;
}
};
-/// Water Menu callbacks
-class LLWorldWaterSettings : public view_listener_t
-{
+class LLWorldEnvPreset : public view_listener_t
+{
bool handleEvent(const LLSD& userdata)
{
- LLFloaterReg::toggleInstance("env_water");
+ std::string item = userdata.asString();
+
+ if (item == "new_water")
+ {
+ LLFloaterReg::showInstance("env_edit_water", "new");
+ }
+ else if (item == "edit_water")
+ {
+ LLFloaterReg::showInstance("env_edit_water", "edit");
+ }
+ else if (item == "delete_water")
+ {
+ LLFloaterReg::showInstance("env_delete_preset", "water");
+ }
+ else if (item == "new_sky")
+ {
+ LLFloaterReg::showInstance("env_edit_sky", "new");
+ }
+ else if (item == "edit_sky")
+ {
+ LLFloaterReg::showInstance("env_edit_sky", "edit");
+ }
+ else if (item == "delete_sky")
+ {
+ LLFloaterReg::showInstance("env_delete_preset", "sky");
+ }
+ else if (item == "new_day_cycle")
+ {
+ LLFloaterReg::showInstance("env_edit_day_cycle", "new");
+ }
+ else if (item == "edit_day_cycle")
+ {
+ LLFloaterReg::showInstance("env_edit_day_cycle", "edit");
+ }
+ else if (item == "delete_day_cycle")
+ {
+ LLFloaterReg::showInstance("env_delete_preset", "day_cycle");
+ }
+ else
+ {
+ llwarns << "Unknown item selected" << llendl;
+ }
+
return true;
}
};
@@ -7690,16 +7677,6 @@ class LLWorldPostProcess : public view_listener_t
}
};
-/// Day Cycle callbacks
-class LLWorldDayCycle : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLFloaterReg::showInstance("env_day_cycle");
- return true;
- }
-};
-
class LLWorldToggleMovementControls : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -7928,9 +7905,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings");
- view_listener_t::addMenu(new LLWorldWaterSettings(), "World.WaterSettings");
+ view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset");
view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
- view_listener_t::addMenu(new LLWorldDayCycle(), "World.DayCycle");
view_listener_t::addMenu(new LLWorldToggleMovementControls(), "World.Toggle.MovementControls");
view_listener_t::addMenu(new LLWorldToggleCameraControls(), "World.Toggle.CameraControls");
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 37640ad0d4..b9293b3b31 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -107,9 +107,7 @@ class LLMeshUploadVisible : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- return gSavedSettings.getBOOL("MeshEnabled") &&
- LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
- !gAgent.getRegion()->getCapability("ObjectAdd").empty();
+ return gMeshRepo.meshUploadEnabled();
}
};
@@ -1203,78 +1201,6 @@ void upload_new_resource(
}
}
-BOOL upload_new_variable_price_resource(
- const LLTransactionID &tid,
- LLAssetType::EType asset_type,
- std::string name,
- std::string desc,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- const LLSD& asset_resources)
-{
- LLAssetID uuid =
- upload_new_resource_prep(
- tid,
- asset_type,
- inv_type,
- name,
- display_name,
- desc);
-
- llinfos << "*** Uploading: " << llendl;
- llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
- llinfos << "UUID: " << uuid << llendl;
- llinfos << "Name: " << name << llendl;
- llinfos << "Desc: " << desc << llendl;
- lldebugs << "Folder: "
- << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? (LLFolderType::EType)asset_type : destination_folder_type) << llendl;
- lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
-
- std::string url = gAgent.getRegion()->getCapability(
- "NewFileAgentInventoryVariablePrice");
-
- if ( !url.empty() )
- {
- lldebugs
- << "New Agent Inventory variable price upload" << llendl;
-
- // Each of the two capabilities has similar data, so
- // let's reuse that code
-
- LLSD body;
-
- body = generate_new_resource_upload_capability_body(
- asset_type,
- name,
- desc,
- destination_folder_type,
- inv_type,
- next_owner_perms,
- group_perms,
- everyone_perms);
-
- body["asset_resources"] = asset_resources;
-
- LLHTTPClient::post(
- url,
- body,
- new LLNewAgentInventoryVariablePriceResponder(
- uuid,
- asset_type,
- body));
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)
{
if ( gDisconnected )
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 1597821504..3136358b83 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -68,23 +68,6 @@ void upload_new_resource(
S32 expected_upload_cost,
void *userdata);
-// TODO* : Move all uploads to use this new function
-// since at some point, that upload path will be deprecated and no longer
-// used
-
-// We make a new function here to ensure that previous code is not broken
-BOOL upload_new_variable_price_resource(
- const LLTransactionID& tid,
- LLAssetType::EType type,
- std::string name,
- std::string desc,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- const LLSD& asset_resources);
LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);
void increase_new_upload_stats(LLAssetType::EType asset_type);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 86b56df556..e934c38c22 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -37,6 +37,7 @@
#include "lleconomy.h"
#include "lleventtimer.h"
#include "llfloaterreg.h"
+#include "llfolderview.h"
#include "llfollowcamparams.h"
#include "llinventorydefines.h"
#include "lllslconstants.h"
@@ -87,6 +88,7 @@
#include "lluri.h"
#include "llviewergenericmessage.h"
#include "llviewermenu.h"
+#include "llviewerinventory.h"
#include "llviewerjoystick.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
@@ -96,7 +98,6 @@
#include "llviewerwindow.h"
#include "llvlmanager.h"
#include "llvoavatarself.h"
-#include "llvotextbubble.h"
#include "llworld.h"
#include "pipeline.h"
#include "llfloaterworldmap.h"
@@ -695,7 +696,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
return false;
}
-static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
+static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
{
if (NULL == inventory_panel) return;
@@ -709,7 +710,7 @@ static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items,
continue;
}
- LLInventoryItem* item = gInventory.getItem(item_id);
+ LLInventoryObject* item = gInventory.getObject(item_id);
llassert(item);
if (!item) {
continue;
@@ -788,7 +789,6 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO
public:
LLViewerInventoryMoveFromWorldObserver()
: LLInventoryAddItemByAssetObserver()
- , mActivePanel(NULL)
{
}
@@ -799,13 +799,16 @@ private:
/*virtual */void onAssetAdded(const LLUUID& asset_id)
{
// Store active Inventory panel.
- mActivePanel = LLInventoryPanel::getActiveInventoryPanel();
+ if (LLInventoryPanel::getActiveInventoryPanel())
+ {
+ mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
+ }
// Store selected items (without destination folder)
mSelectedItems.clear();
- if (mActivePanel)
+ if (LLInventoryPanel::getActiveInventoryPanel())
{
- mSelectedItems = mActivePanel->getRootFolder()->getSelectionList();
+ mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList();
}
mSelectedItems.erase(mMoveIntoFolderID);
}
@@ -816,12 +819,14 @@ private:
*/
void done()
{
+ LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
+
// if selection is not changed since watch started lets hightlight new items.
- if (mActivePanel && !isSelectionChanged())
+ if (active_panel && !isSelectionChanged())
{
LL_DEBUGS("Inventory_Move") << "Selecting new items..." << LL_ENDL;
- mActivePanel->clearSelection();
- highlight_inventory_items_in_panel(mAddedItems, mActivePanel);
+ active_panel->clearSelection();
+ highlight_inventory_objects_in_panel(mAddedItems, active_panel);
}
}
@@ -829,16 +834,16 @@ private:
* Returns true if selected inventory items were changed since moved inventory items were started to watch.
*/
bool isSelectionChanged()
- {
- const LLInventoryPanel * const current_active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ {
+ LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
- if (NULL == mActivePanel || current_active_panel != mActivePanel)
+ if (NULL == active_panel)
{
return true;
}
// get selected items (without destination folder)
- selected_items_t selected_items = mActivePanel->getRootFolder()->getSelectionList();
+ selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList();
selected_items.erase(mMoveIntoFolderID);
// compare stored & current sets of selected items
@@ -852,7 +857,7 @@ private:
return different_items.size() > 0;
}
- LLInventoryPanel *mActivePanel;
+ LLHandle<LLPanel> mActivePanel;
typedef std::set<LLUUID> selected_items_t;
selected_items_t mSelectedItems;
@@ -881,6 +886,75 @@ void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder
gInventoryMoveObserver->watchAsset(inv_item->getAssetUUID());
}
+
+/**
+ * Class to observe moving of items and to select them in inventory.
+ *
+ * Used currently for dragging from inbox to regular inventory folders
+ */
+
+class LLViewerInventoryMoveObserver : public LLInventoryObserver
+{
+public:
+
+ LLViewerInventoryMoveObserver(const LLUUID& object_id)
+ : LLInventoryObserver()
+ , mObjectID(object_id)
+ {
+ if (LLInventoryPanel::getActiveInventoryPanel())
+ {
+ mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
+ }
+ }
+
+ virtual ~LLViewerInventoryMoveObserver() {}
+ virtual void changed(U32 mask);
+
+private:
+ LLUUID mObjectID;
+ LLHandle<LLPanel> mActivePanel;
+
+};
+
+void LLViewerInventoryMoveObserver::changed(U32 mask)
+{
+ LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
+
+ if (NULL == active_panel)
+ {
+ gInventory.removeObserver(this);
+ return;
+ }
+
+ if((mask & (LLInventoryObserver::STRUCTURE)) != 0)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ if ((*id_it) == mObjectID)
+ {
+ active_panel->clearSelection();
+ std::vector<LLUUID> items;
+ items.push_back(mObjectID);
+ highlight_inventory_objects_in_panel(items, active_panel);
+ active_panel->getRootFolder()->scrollToShowSelection();
+
+ gInventory.removeObserver(this);
+ break;
+ }
+ }
+ }
+}
+
+void set_dad_inbox_object(const LLUUID& object_id)
+{
+ LLViewerInventoryMoveObserver* move_observer = new LLViewerInventoryMoveObserver(object_id);
+ gInventory.addObserver(move_observer);
+}
+
//unlike the FetchObserver for AgentOffer, we only make one
//instance of the AddedObserver for TaskOffers
//and it never dies. We do this because we don't know the UUID of
@@ -937,7 +1011,6 @@ protected:
//one global instance to bind them
LLOpenTaskOffer* gNewInventoryObserver=NULL;
-
class LLNewInventoryHintObserver : public LLInventoryAddedObserver
{
protected:
@@ -947,6 +1020,8 @@ protected:
}
};
+LLNewInventoryHintObserver* gNewInventoryHintObserver=NULL;
+
void start_new_inventory_observer()
{
if (!gNewInventoryObserver) //task offer observer
@@ -963,7 +1038,12 @@ void start_new_inventory_observer()
gInventory.addObserver(gInventoryMoveObserver);
}
- gInventory.addObserver(new LLNewInventoryHintObserver());
+ if (!gNewInventoryHintObserver)
+ {
+ // Observer is deleted by gInventory
+ gNewInventoryHintObserver = new LLNewInventoryHintObserver();
+ gInventory.addObserver(gNewInventoryHintObserver);
+ }
}
class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver
@@ -1502,7 +1582,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
LLSD args;
args["MESSAGE"] = log_message;
- LLNotificationsUtil::add("SystemMessage", args);
+ LLNotificationsUtil::add("SystemMessageTip", args);
}
break;
@@ -1676,7 +1756,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
LLSD args;
args["MESSAGE"] = log_message;
- LLNotificationsUtil::add("SystemMessage", args);
+ LLNotificationsUtil::add("SystemMessageTip", args);
}
// we will want to open this item when it comes back.
@@ -1727,7 +1807,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
LLSD args;
args["MESSAGE"] = log_message;
- LLNotificationsUtil::add("SystemMessage", args);
+ LLNotificationsUtil::add("SystemMessageTip", args);
}
if (busy && (!mFromGroup && !mFromObject))
@@ -3213,7 +3293,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
if (is_audible)
{
BOOL visible_in_chat_bubble = FALSE;
- std::string verb;
color.setVec(1.f,1.f,1.f,1.f);
msg->getStringFast(_PREHASH_ChatData, _PREHASH_Message, mesg);
@@ -3262,18 +3341,19 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
}
else
{
+ chat.mText = "";
switch(chat.mChatType)
{
case CHAT_TYPE_WHISPER:
- verb = LLTrans::getString("whisper") + " ";
+ chat.mText = LLTrans::getString("whisper") + " ";
break;
case CHAT_TYPE_DEBUG_MSG:
case CHAT_TYPE_OWNER:
case CHAT_TYPE_NORMAL:
- verb = "";
+ case CHAT_TYPE_DIRECT:
break;
case CHAT_TYPE_SHOUT:
- verb = LLTrans::getString("shout") + " ";
+ chat.mText = LLTrans::getString("shout") + " ";
break;
case CHAT_TYPE_START:
case CHAT_TYPE_STOP:
@@ -3281,13 +3361,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
break;
default:
LL_WARNS("Messaging") << "Unknown type " << chat.mChatType << " in chat!" << LL_ENDL;
- verb = "";
break;
}
-
- chat.mText = "";
- chat.mText += verb;
chat.mText += mesg;
}
@@ -4232,15 +4308,8 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
// Display green bubble on kill
if ( gShowObjectUpdates )
{
- LLViewerObject* newobject;
- newobject = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, objectp->getRegion());
-
- LLVOTextBubble* bubble = (LLVOTextBubble*) newobject;
-
- bubble->mColor.setVec(0.f, 1.f, 0.f, 1.f);
- bubble->setScale( 2.0f * bubble->getScale() );
- bubble->setPositionGlobal(objectp->getPositionGlobal());
- gPipeline.addObject(bubble);
+ LLColor4 color(0.f,1.f,0.f,1.f);
+ gPipeline.addDebugBlip(objectp->getPositionAgent(), color);
}
// Do the kill
@@ -4277,8 +4346,7 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec);
- //LL_DEBUGS("Messaging") << "time_synch() - " << sun_direction << ", " << sun_ang_velocity
- // << ", " << phase << LL_ENDL;
+ LL_DEBUGS("Windlight Sync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL;
gSky.setSunPhase(phase);
gSky.setSunTargetDirection(sun_direction, sun_ang_velocity);
@@ -4337,6 +4405,12 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
return;
}
+ // Don't play sounds from gestures if they are not enabled.
+ if (object_id == owner_id && !gSavedSettings.getBOOL("EnableGestureSounds"))
+ {
+ return;
+ }
+
gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global);
}
@@ -5376,10 +5450,10 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
{
// notification was specified using the new mechanism, so we can just handle it here
std::string notificationID;
- msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
- if (!LLNotifications::getInstance()->templateExists(notificationID))
- {
- return false;
+ msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
+ if (!LLNotifications::getInstance()->templateExists(notificationID))
+ {
+ return false;
}
std::string llsdRaw;
@@ -6270,6 +6344,18 @@ void send_group_notice(const LLUUID& group_id,
bool handle_lure_callback(const LLSD& notification, const LLSD& response)
{
+ static const unsigned OFFER_RECIPIENT_LIMIT = 250;
+ if(notification["payload"]["ids"].size() > OFFER_RECIPIENT_LIMIT)
+ {
+ // More than OFFER_RECIPIENT_LIMIT targets will overload the message
+ // producing an llerror.
+ LLSD args;
+ args["OFFERS"] = notification["payload"]["ids"].size();
+ args["LIMIT"] = static_cast<int>(OFFER_RECIPIENT_LIMIT);
+ LLNotificationsUtil::add("TooManyTeleportOffers", args);
+ return false;
+ }
+
std::string text = response["message"].asString();
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
@@ -6487,10 +6573,14 @@ void process_script_dialog(LLMessageSystem* msg, void**)
LLSD payload;
LLUUID object_id;
- LLUUID owner_id;
-
msg->getUUID("Data", "ObjectID", object_id);
+
+// For compability with OS grids first check for presence of extended packet before fetching data.
+ LLUUID owner_id;
+ if (gMessageSystem->getNumberOfBlocks("OwnerData") > 0)
+ {
msg->getUUID("OwnerData", "OwnerID", owner_id);
+ }
if (LLMuteList::getInstance()->isMuted(object_id) || LLMuteList::getInstance()->isMuted(owner_id))
{
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index b4a9b8e677..9d09d9c01a 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -203,6 +203,8 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name)
bool highlight_offered_object(const LLUUID& obj_id);
void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid);
+void set_dad_inbox_object(const LLUUID& object_id);
+
class LLOfferInfo : public LLNotificationResponderInterface
{
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 6d493bfcd5..972993202a 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -81,7 +81,6 @@
#include "llviewerwindow.h" // For getSpinAxis
#include "llvoavatar.h"
#include "llvoavatarself.h"
-#include "llvoclouds.h"
#include "llvograss.h"
#include "llvoground.h"
#include "llvolume.h"
@@ -89,7 +88,6 @@
#include "llvopartgroup.h"
#include "llvosky.h"
#include "llvosurfacepatch.h"
-#include "llvotextbubble.h"
#include "llvotree.h"
#include "llvovolume.h"
#include "llvowater.h"
@@ -102,6 +100,7 @@
#include "lltrans.h"
#include "llsdutil.h"
#include "llmediaentry.h"
+#include "llaccountingquota.h"
//#define DEBUG_UPDATE_TYPE
@@ -167,10 +166,6 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
// llwarns << "Creating new tree!" << llendl;
// res = new LLVOTree(id, pcode, regionp); break;
res = NULL; break;
- case LL_PCODE_LEGACY_TEXT_BUBBLE:
- res = new LLVOTextBubble(id, pcode, regionp); break;
- case LL_VO_CLOUDS:
- res = new LLVOClouds(id, pcode, regionp); break;
case LL_VO_SURFACE_PATCH:
res = new LLVOSurfacePatch(id, pcode, regionp); break;
case LL_VO_SKY:
@@ -1893,7 +1888,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
//
//
- // WTF? If we're going to skip this message, why are we
+ // If we're going to skip this message, why are we
// doing all the parenting, etc above?
U32 packet_id = mesgsys->getCurrentRecvPacketID();
if (packet_id < mLatestRecvPacketID &&
@@ -1972,23 +1967,16 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
if ( gShowObjectUpdates )
{
- if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf()))
- && mRegionp)
+ LLColor4 color;
+ if (update_type == OUT_TERSE_IMPROVED)
{
- LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp);
- LLVOTextBubble* bubble = (LLVOTextBubble*) object;
-
- if (update_type == OUT_TERSE_IMPROVED)
- {
- bubble->mColor.setVec(0.f, 0.f, 1.f, 1.f);
- }
- else
- {
- bubble->mColor.setVec(1.f, 0.f, 0.f, 1.f);
- }
- object->setPositionGlobal(getPositionGlobal());
- gPipeline.addObject(object);
+ color.setVec(0.f, 0.f, 1.f, 1.f);
}
+ else
+ {
+ color.setVec(1.f, 0.f, 0.f, 1.f);
+ }
+ gPipeline.addDebugBlip(getPositionAgent(), color);
}
if ((0.0f == vel_mag_sq) &&
@@ -5282,7 +5270,7 @@ bool LLViewerObject::specialHoverCursor() const
|| (mClickAction != 0);
}
-void LLViewerObject::updateFlags()
+void LLViewerObject::updateFlags(BOOL physics_changed)
{
LLViewerRegion* regionp = getRegion();
if(!regionp) return;
@@ -5295,12 +5283,15 @@ void LLViewerObject::updateFlags()
gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() );
gMessageSystem->addBOOL("IsPhantom", flagPhantom() );
gMessageSystem->addBOOL("CastsShadows", flagCastShadows() );
- gMessageSystem->nextBlock("ExtraPhysics");
- gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() );
- gMessageSystem->addF32("Density", getPhysicsDensity() );
- gMessageSystem->addF32("Friction", getPhysicsFriction() );
- gMessageSystem->addF32("Restitution", getPhysicsRestitution() );
- gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() );
+ if (physics_changed)
+ {
+ gMessageSystem->nextBlock("ExtraPhysics");
+ gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() );
+ gMessageSystem->addF32("Density", getPhysicsDensity() );
+ gMessageSystem->addF32("Friction", getPhysicsFriction() );
+ gMessageSystem->addF32("Restitution", getPhysicsRestitution() );
+ gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() );
+ }
gMessageSystem->sendReliable( regionp->getHost() );
}
@@ -5699,3 +5690,10 @@ public:
LLHTTPRegistration<ObjectPhysicsProperties>
gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties");
+
+
+void LLViewerObject::updateQuota( const SelectionQuota& quota )
+{
+ //update quotas
+ mSelectionQuota = quota;
+}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index e417343bec..7ebcee7b74 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -43,6 +43,7 @@
#include "v3dmath.h"
#include "v3math.h"
#include "llvertexbuffer.h"
+#include "llaccountingquota.h"
class LLAgent; // TODO: Get rid of this.
class LLAudioSource;
@@ -488,7 +489,7 @@ public:
void setRegion(LLViewerRegion *regionp);
virtual void updateRegion(LLViewerRegion *regionp);
- void updateFlags();
+ void updateFlags(BOOL physics_changed = FALSE);
BOOL setFlags(U32 flag, BOOL state);
void setPhysicsShapeType(U8 type);
void setPhysicsGravity(F32 gravity);
@@ -546,7 +547,7 @@ public:
//
typedef enum e_vo_types
{
- LL_VO_CLOUDS = LL_PCODE_APP | 0x20,
+ LL_VO_CLOUDS = LL_PCODE_APP | 0x20, // no longer used
LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30,
LL_VO_WL_SKY = LL_PCODE_APP | 0x40,
LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50,
@@ -643,7 +644,11 @@ protected:
void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id);
void deleteParticleSource();
void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id);
-
+
+public:
+ void updateQuota( const SelectionQuota& quota );
+ const SelectionQuota& getQuota( void ) { return mSelectionQuota; }
+
private:
void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string
void deleteTEImages(); // correctly deletes list of images
@@ -705,6 +710,8 @@ protected:
F32 mPhysicsCost;
F32 mLinksetPhysicsCost;
+ SelectionQuota mSelectionQuota;
+
bool mCostStale;
mutable bool mPhysicsShapeUnknown;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index ab2e07e4df..9f882ee732 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -957,8 +957,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
iter != idle_list.end(); iter++)
{
objectp = *iter;
- if (objectp->getPCode() == LLViewerObject::LL_VO_CLOUDS ||
- objectp->isAvatar())
+ if (objectp->isAvatar())
{
objectp->idleUpdate(agent, world, frame_time);
}
@@ -1418,6 +1417,15 @@ void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id)
mPendingObjectCost.erase(object_id);
}
+void LLViewerObjectList::updateQuota( const LLUUID& objectId, const SelectionQuota& quota )
+{
+ LLViewerObject* pVO = findObject( objectId );
+ if ( pVO )
+ {
+ pVO->updateQuota( quota );
+ }
+}
+
void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object)
{
mStalePhysicsFlags.insert(object->getID());
@@ -1488,6 +1496,24 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
LLWorld::getInstance()->shiftRegions(offset);
}
+void LLViewerObjectList::repartitionObjects()
+{
+ for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
+ {
+ LLViewerObject* objectp = *iter;
+ if (!objectp->isDead())
+ {
+ LLDrawable* drawable = objectp->mDrawable;
+ if (drawable && !drawable->isDead())
+ {
+ drawable->updateBinRadius();
+ drawable->updateSpatialExtents();
+ drawable->movePartition();
+ }
+ }
+ }
+}
+
//debug code
bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp)
{
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 65374bca70..9d1b5cb56f 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -36,6 +36,7 @@
// project includes
#include "llviewerobject.h"
+#include "llaccountingquota.h"
class LLCamera;
class LLNetMap;
@@ -101,7 +102,10 @@ public:
F32 restitution,
F32 gravity_multiplier);
+ void updateQuota( const LLUUID& objectId, const SelectionQuota& costs );
+
void shiftObjects(const LLVector3 &offset);
+ void repartitionObjects();
bool hasMapObjectInRegion(LLViewerRegion* regionp) ;
void clearAllMapObjectsInRegion(LLViewerRegion* regionp) ;
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 5ae4e872f3..8db72da1ee 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -2202,9 +2202,9 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
= parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID());
bool isAuthorized
- = (authorizeBuyer.isNull()
- || (gAgent.getID() == authorizeBuyer)
- || (gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_DEED)
+ = (authorizeBuyer.isNull()
+ || (gAgent.getID() == authorizeBuyer)
+ || (gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_DEED)
&& gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_SET_SALE_INFO)));
return isForSale && !isOwner && isAuthorized && isEmpowered;
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index 45c9b3e91f..252183b6d7 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -33,6 +33,8 @@
// in viewer.
// It is used to precompile headers for improved build speed.
+#include <boost/coroutine/coroutine.hpp>
+
#include "linden_common.h"
// Work around stupid Microsoft STL warning
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index f835351c04..bb7170e0f7 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -54,6 +54,7 @@
#include "llfloaterreporter.h"
#include "llfloaterregioninfo.h"
#include "llhttpnode.h"
+#include "llregioninfomodel.h"
#include "llsdutil.h"
#include "llstartup.h"
#include "lltrans.h"
@@ -64,11 +65,11 @@
#include "llvlmanager.h"
#include "llvlcomposition.h"
#include "llvocache.h"
-#include "llvoclouds.h"
#include "llworld.h"
#include "llspatialpartition.h"
#include "stringize.h"
#include "llviewercontrol.h"
+#include "llsdserialize.h"
#ifdef LL_WINDOWS
#pragma warning(disable:4355)
@@ -314,7 +315,6 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
- mImpl->mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD
mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS
mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME
mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE
@@ -349,7 +349,6 @@ LLViewerRegion::~LLViewerRegion()
// Can't do this on destruction, because the neighbor pointers might be invalid.
// This should be reference counted...
disconnectAllNeighbors();
- mCloudLayer.destroy();
LLViewerPartSim::getInstance()->cleanupRegion(this);
gObjectList.killObjects(this);
@@ -485,7 +484,6 @@ void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global)
updateRenderMatrix();
mImpl->mLandp->setOriginGlobal(origin_global);
mWind.setOriginGlobal(origin_global);
- mCloudLayer.setOriginGlobal(origin_global);
calculateCenterGlobal();
}
@@ -646,6 +644,9 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access)
void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**)
{
// send it to 'observers'
+ // *TODO: switch the floaters to using LLRegionInfoModel
+ llinfos << "Processing region info" << llendl;
+ LLRegionInfoModel::instance().update(msg);
LLFloaterGodTools::processRegionInfo(msg);
LLFloaterRegionInfo::processRegionInfo(msg);
LLFloaterReporter::processRegionInfo(msg);
@@ -708,14 +709,12 @@ void LLViewerRegion::forceUpdate()
void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction)
{
mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction);
- mCloudLayer.connectNeighbor(&(neighborp->mCloudLayer), direction);
}
void LLViewerRegion::disconnectAllNeighbors()
{
mImpl->mLandp->disconnectAllNeighbors();
- mCloudLayer.disconnectAllNeighbors();
}
LLVLComposition * LLViewerRegion::getComposition() const
@@ -1140,6 +1139,20 @@ void LLViewerRegion::getInfo(LLSD& info)
info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
}
+void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features)
+{
+ sim_features = mSimulatorFeatures;
+}
+
+void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
+{
+ std::stringstream str;
+
+ LLSDSerialize::toPrettyXML(sim_features, str);
+ llinfos << str.str() << llendl;
+ mSimulatorFeatures = sim_features;
+}
+
LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
{
U32 local_id = objectp->getLocalID();
@@ -1480,6 +1493,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
LLSD capabilityNames = LLSD::emptyArray();
+ capabilityNames.append("AccountingParcel");
+ capabilityNames.append("AccountingSelection");
capabilityNames.append("AttachmentResources");
capabilityNames.append("AvatarPickerSearch");
capabilityNames.append("ChatSessionRequest");
@@ -1487,6 +1502,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
+ capabilityNames.append("EnvironmentSettings");
capabilityNames.append("ObjectMedia");
capabilityNames.append("ObjectMediaNavigate");
@@ -1509,8 +1525,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
capabilityNames.append("NewFileAgentInventory");
- capabilityNames.append("NewFileAgentInventoryVariablePrice");
- capabilityNames.append("ObjectAdd");
capabilityNames.append("ParcelPropertiesUpdate");
capabilityNames.append("ParcelMediaURLFilterList");
capabilityNames.append("ParcelNavigateMedia");
@@ -1541,10 +1555,14 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("UpdateNotecardTaskInventory");
capabilityNames.append("UpdateScriptTask");
capabilityNames.append("UploadBakedTexture");
- capabilityNames.append("UploadObjectAsset");
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
+ //prep# Finalize these!!!!!!!!!
+ //capabilityNames.append("AccountingVO");
+ capabilityNames.append("AccountingParcel");
+ capabilityNames.append("AccountingRegion");
+
// Please add new capabilities alphabetically to reduce
// merge conflicts.
@@ -1554,6 +1572,42 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
}
+class SimulatorFeaturesReceived : public LLHTTPClient::Responder
+{
+ LOG_CLASS(SimulatorFeaturesReceived);
+public:
+ SimulatorFeaturesReceived(LLViewerRegion* region)
+ : mRegion(region)
+ { }
+
+
+ void error(U32 statusNum, const std::string& reason)
+ {
+ LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL;
+ }
+
+ void result(const LLSD& content)
+ {
+ if(!mRegion) //region is removed or responder is not created.
+ {
+ return ;
+ }
+
+ mRegion->setSimulatorFeatures(content);
+ }
+
+ static boost::intrusive_ptr<SimulatorFeaturesReceived> build(
+ LLViewerRegion* region)
+ {
+ return boost::intrusive_ptr<SimulatorFeaturesReceived>(
+ new SimulatorFeaturesReceived(region));
+ }
+
+private:
+ LLViewerRegion* mRegion;
+};
+
+
void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
{
if(name == "EventQueueGet")
@@ -1566,6 +1620,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
{
LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
}
+ else if (name == "SimulatorFeatures")
+ {
+ // kick off a request for simulator features
+ LLHTTPClient::get(url, new SimulatorFeaturesReceived(this));
+ }
else
{
mImpl->mCapabilities[name] = url;
@@ -1600,6 +1659,21 @@ bool LLViewerRegion::capabilitiesReceived() const
void LLViewerRegion::setCapabilitiesReceived(bool received)
{
mCapabilitiesReceived = received;
+
+ // Tell interested parties that we've received capabilities,
+ // so that they can safely use getCapability().
+ if (received)
+ {
+ mCapabilitiesReceivedSignal(getRegionID());
+
+ // This is a single-shot signal. Forget callbacks to save resources.
+ mCapabilitiesReceivedSignal.disconnect_all_slots();
+ }
+}
+
+boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb)
+{
+ return mCapabilitiesReceivedSignal.connect(cb);
}
void LLViewerRegion::logActiveCapabilities() const
@@ -1658,3 +1732,17 @@ std::string LLViewerRegion::getDescription() const
{
return stringize(*this);
}
+
+bool LLViewerRegion::meshUploadEnabled() const
+{
+ return (mSimulatorFeatures.has("MeshUploadEnabled") &&
+ mSimulatorFeatures["MeshUploadEnabled"].asBoolean());
+}
+
+bool LLViewerRegion::meshRezEnabled() const
+{
+ return (mSimulatorFeatures.has("MeshRezEnabled") &&
+ mSimulatorFeatures["MeshRezEnabled"].asBoolean());
+}
+
+
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 9c5b85b77f..f68b51ea65 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -30,10 +30,10 @@
// A ViewerRegion is a class that contains a bunch of objects and surfaces
// that are in to a particular region.
#include <string>
+#include <boost/signals2.hpp>
#include "lldarray.h"
#include "llwind.h"
-#include "llcloud.h"
#include "llstat.h"
#include "v3dmath.h"
#include "llstring.h"
@@ -81,7 +81,6 @@ public:
PARTITION_WATER,
PARTITION_TREE,
PARTITION_PARTICLE,
- PARTITION_CLOUD,
PARTITION_GRASS,
PARTITION_VOLUME,
PARTITION_BRIDGE,
@@ -90,6 +89,8 @@ public:
NUM_PARTITIONS
} eObjectPartitions;
+ typedef boost::signals2::signal<void(const LLUUID& region_id)> caps_received_signal_t;
+
LLViewerRegion(const U64 &handle,
const LLHost &host,
const U32 surface_grid_width,
@@ -237,6 +238,7 @@ public:
// has region received its final (not seed) capability list?
bool capabilitiesReceived() const;
void setCapabilitiesReceived(bool received);
+ boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb);
static bool isSpecialCapabilityName(const std::string &name);
void logActiveCapabilities() const;
@@ -275,6 +277,12 @@ public:
F32 getLandHeightRegion(const LLVector3& region_pos);
void getInfo(LLSD& info);
+
+ bool meshRezEnabled() const;
+ bool meshUploadEnabled() const;
+
+ void getSimulatorFeatures(LLSD& info);
+ void setSimulatorFeatures(const LLSD& info);
typedef enum
{
@@ -330,7 +338,6 @@ protected:
public:
LLWind mWind;
- LLCloudLayer mCloudLayer;
LLViewerParcelOverlay *mParcelOverlay;
LLStat mBitStat;
@@ -398,8 +405,11 @@ private:
bool mAlive; // can become false if circuit disconnects
bool mCapabilitiesReceived;
+ caps_received_signal_t mCapabilitiesReceivedSignal;
BOOL mReleaseNotesRequested;
+
+ LLSD mSimulatorFeatures;
};
inline BOOL LLViewerRegion::getAllowDamage() const
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 3e85802ba6..e473901609 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -66,12 +66,20 @@ LLGLSLShader gObjectSimpleProgram;
LLGLSLShader gObjectSimpleWaterProgram;
LLGLSLShader gObjectFullbrightProgram;
LLGLSLShader gObjectFullbrightWaterProgram;
-
LLGLSLShader gObjectFullbrightShinyProgram;
LLGLSLShader gObjectFullbrightShinyWaterProgram;
LLGLSLShader gObjectShinyProgram;
LLGLSLShader gObjectShinyWaterProgram;
+LLGLSLShader gObjectSimpleNonIndexedProgram;
+LLGLSLShader gObjectSimpleNonIndexedWaterProgram;
+LLGLSLShader gObjectFullbrightNonIndexedProgram;
+LLGLSLShader gObjectFullbrightNonIndexedWaterProgram;
+LLGLSLShader gObjectFullbrightShinyNonIndexedProgram;
+LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram;
+LLGLSLShader gObjectShinyNonIndexedProgram;
+LLGLSLShader gObjectShinyNonIndexedWaterProgram;
+
//object hardware skinning shaders
LLGLSLShader gSkinnedObjectSimpleProgram;
LLGLSLShader gSkinnedObjectFullbrightProgram;
@@ -113,6 +121,7 @@ LLGLSLShader gDeferredImpostorProgram;
LLGLSLShader gDeferredEdgeProgram;
LLGLSLShader gDeferredWaterProgram;
LLGLSLShader gDeferredDiffuseProgram;
+LLGLSLShader gDeferredNonIndexedDiffuseProgram;
LLGLSLShader gDeferredSkinnedDiffuseProgram;
LLGLSLShader gDeferredSkinnedBumpProgram;
LLGLSLShader gDeferredSkinnedAlphaProgram;
@@ -132,13 +141,16 @@ LLGLSLShader gDeferredShadowProgram;
LLGLSLShader gDeferredAvatarShadowProgram;
LLGLSLShader gDeferredAttachmentShadowProgram;
LLGLSLShader gDeferredAlphaProgram;
+LLGLSLShader gDeferredAvatarEyesProgram;
LLGLSLShader gDeferredFullbrightProgram;
LLGLSLShader gDeferredGIProgram;
LLGLSLShader gDeferredGIFinalProgram;
LLGLSLShader gDeferredPostGIProgram;
LLGLSLShader gDeferredPostProgram;
LLGLSLShader gDeferredPostNoDoFProgram;
-
+LLGLSLShader gDeferredWLSkyProgram;
+LLGLSLShader gDeferredWLCloudProgram;
+LLGLSLShader gDeferredStarProgram;
LLGLSLShader gLuminanceGatherProgram;
@@ -160,6 +172,10 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gObjectFullbrightProgram);
mShaderList.push_back(&gObjectFullbrightShinyProgram);
mShaderList.push_back(&gObjectFullbrightShinyWaterProgram);
+ mShaderList.push_back(&gObjectSimpleNonIndexedProgram);
+ mShaderList.push_back(&gObjectFullbrightNonIndexedProgram);
+ mShaderList.push_back(&gObjectFullbrightShinyNonIndexedProgram);
+ mShaderList.push_back(&gObjectFullbrightShinyNonIndexedWaterProgram);
mShaderList.push_back(&gSkinnedObjectSimpleProgram);
mShaderList.push_back(&gSkinnedObjectFullbrightProgram);
mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram);
@@ -183,6 +199,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredAlphaProgram);
mShaderList.push_back(&gDeferredSkinnedAlphaProgram);
mShaderList.push_back(&gDeferredFullbrightProgram);
+ mShaderList.push_back(&gDeferredAvatarEyesProgram);
mShaderList.push_back(&gDeferredPostGIProgram);
mShaderList.push_back(&gDeferredEdgeProgram);
mShaderList.push_back(&gDeferredPostProgram);
@@ -190,6 +207,9 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gDeferredGIFinalProgram);
mShaderList.push_back(&gDeferredWaterProgram);
mShaderList.push_back(&gDeferredAvatarAlphaProgram);
+ mShaderList.push_back(&gDeferredWLSkyProgram);
+ mShaderList.push_back(&gDeferredWLCloudProgram);
+ mShaderList.push_back(&gDeferredStarProgram);
}
LLViewerShaderMgr::~LLViewerShaderMgr()
@@ -347,6 +367,10 @@ void LLViewerShaderMgr::setShaders()
return;
}
+ //setup preprocessor definitions
+ LLShaderMgr::instance()->mDefinitions["samples"] = llformat("%d", gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples")));
+ LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits);
+
reentrance = true;
// Make sure the compiled shader map is cleared before we recompile shaders.
@@ -577,6 +601,16 @@ void LLViewerShaderMgr::unloadShaders()
gObjectFullbrightShinyWaterProgram.unload();
gObjectShinyWaterProgram.unload();
+ gObjectSimpleNonIndexedProgram.unload();
+ gObjectSimpleNonIndexedWaterProgram.unload();
+ gObjectFullbrightNonIndexedProgram.unload();
+ gObjectFullbrightNonIndexedWaterProgram.unload();
+
+ gObjectShinyNonIndexedProgram.unload();
+ gObjectFullbrightShinyNonIndexedProgram.unload();
+ gObjectFullbrightShinyNonIndexedWaterProgram.unload();
+ gObjectShinyNonIndexedWaterProgram.unload();
+
gSkinnedObjectSimpleProgram.unload();
gSkinnedObjectFullbrightProgram.unload();
gSkinnedObjectFullbrightShinyProgram.unload();
@@ -607,6 +641,7 @@ void LLViewerShaderMgr::unloadShaders()
gPostNightVisionProgram.unload();
gDeferredDiffuseProgram.unload();
+ gDeferredNonIndexedDiffuseProgram.unload();
gDeferredSkinnedDiffuseProgram.unload();
gDeferredSkinnedBumpProgram.unload();
gDeferredSkinnedAlphaProgram.unload();
@@ -685,24 +720,40 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
shaders.clear();
shaders.reserve(13);
- shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
- shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) );
- shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
- shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
- shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) );
- shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
- shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ S32 ch = gGLManager.mNumTextureImageUnits-1;
+
+ if (gGLManager.mGLVersion < 3.1f)
+ { //force to 1 texture index channel for old drivers
+ ch = 1;
+ }
+
+ std::vector<S32> index_channels;
+ index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
for (U32 i = 0; i < shaders.size(); i++)
{
// Note usage of GL_FRAGMENT_SHADER_ARB
- if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB) == 0)
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, index_channels[i]) == 0)
{
return FALSE;
}
@@ -833,6 +884,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
{
BOOL success = TRUE;
+ U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
+ bool multisample = samples > 1 && LLPipeline::sRenderDeferred && gGLManager.mHasTextureMultisample;
+
if (mVertexShaderLevel[SHADER_EFFECT] == 0)
{
gGlowProgram.unload();
@@ -858,10 +912,21 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
if (success)
{
+ std::string fragment;
+
+ if (multisample)
+ {
+ fragment = "effects/glowExtractMSF.glsl";
+ }
+ else
+ {
+ fragment = "effects/glowExtractF.glsl";
+ }
+
gGlowExtractProgram.mName = "Glow Extract Shader (Post)";
gGlowExtractProgram.mShaderFiles.clear();
gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));
- gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowExtractProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
success = gGlowExtractProgram.createShader(NULL, &mGlowExtractUniforms);
if (!success)
@@ -925,6 +990,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredTreeProgram.unload();
gDeferredDiffuseProgram.unload();
+ gDeferredNonIndexedDiffuseProgram.unload();
gDeferredSkinnedDiffuseProgram.unload();
gDeferredSkinnedBumpProgram.unload();
gDeferredSkinnedAlphaProgram.unload();
@@ -945,6 +1011,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaProgram.unload();
gDeferredAlphaProgram.unload();
gDeferredFullbrightProgram.unload();
+ gDeferredAvatarEyesProgram.unload();
gDeferredPostGIProgram.unload();
gDeferredEdgeProgram.unload();
gDeferredPostProgram.unload();
@@ -952,6 +1019,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredGIProgram.unload();
gDeferredGIFinalProgram.unload();
gDeferredWaterProgram.unload();
+ gDeferredWLSkyProgram.unload();
+ gDeferredWLCloudProgram.unload();
+ gDeferredStarProgram.unload();
return TRUE;
}
@@ -959,18 +1029,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
BOOL success = TRUE;
+ U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
+ bool multisample = samples > 1 && gGLManager.mHasTextureMultisample;
+
if (success)
{
gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader";
gDeferredDiffuseProgram.mShaderFiles.clear();
gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits;
gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredDiffuseProgram.createShader(NULL, NULL);
}
if (success)
{
+ gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader";
+ gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear();
+ gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredNonIndexedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL);
+ }
+
+
+ if (success)
+ {
gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader";
gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedDiffuseProgram.mShaderFiles.clear();
@@ -1000,9 +1085,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+ gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
}
@@ -1039,40 +1125,83 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ std::string fragment;
+
+ if (multisample)
+ {
+ fragment = "deferred/pointLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/pointLightF.glsl";
+ }
+
gDeferredLightProgram.mName = "Deferred Light Shader";
gDeferredLightProgram.mShaderFiles.clear();
gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredLightProgram.createShader(NULL, NULL);
}
if (success)
{
+ std::string fragment;
+ if (multisample)
+ {
+ fragment = "deferred/multiPointLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/multiPointLightF.glsl";
+ }
+
gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader";
gDeferredMultiLightProgram.mShaderFiles.clear();
gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredMultiLightProgram.createShader(NULL, NULL);
}
if (success)
{
+ std::string fragment;
+
+ if (multisample)
+ {
+ fragment = "deferred/spotLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/multiSpotLightF.glsl";
+ }
+
gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader";
gDeferredSpotLightProgram.mShaderFiles.clear();
gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredSpotLightProgram.createShader(NULL, NULL);
}
if (success)
{
+ std::string fragment;
+
+ if (multisample)
+ {
+ fragment = "deferred/multiSpotLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/multiSpotLightF.glsl";
+ }
+
gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";
gDeferredMultiSpotLightProgram.mShaderFiles.clear();
gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL);
}
@@ -1083,11 +1212,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
{
- fragment = "deferred/sunLightSSAOF.glsl";
+ if (multisample)
+ {
+ fragment = "deferred/sunLightSSAOMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/sunLightSSAOF.glsl";
+ }
}
else
{
- fragment = "deferred/sunLightF.glsl";
+ if (multisample)
+ {
+ fragment = "deferred/sunLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/sunLightF.glsl";
+ }
}
gDeferredSunProgram.mName = "Deferred Sun Shader";
@@ -1100,10 +1243,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ std::string fragment;
+
+ if (multisample)
+ {
+ fragment = "deferred/blurLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/blurLightF.glsl";
+ }
+
gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
gDeferredBlurLightProgram.mShaderFiles.clear();
gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredBlurLightProgram.createShader(NULL, NULL);
}
@@ -1116,6 +1270,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAlphaProgram.mFeatures.hasGamma = true;
gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
gDeferredAlphaProgram.mFeatures.hasLighting = true;
+ gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
+ if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
+ {
+ gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits;
+ }
+ else
+ { //shave off some texture units for shadow maps
+ gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits - 6;
+ }
+
gDeferredAlphaProgram.mShaderFiles.clear();
gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1125,11 +1289,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ gDeferredAvatarEyesProgram.mName = "Deferred Avatar Eyes Shader";
+ gDeferredAvatarEyesProgram.mFeatures.calculatesAtmospherics = true;
+ gDeferredAvatarEyesProgram.mFeatures.hasGamma = true;
+ gDeferredAvatarEyesProgram.mFeatures.hasTransport = true;
+ gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true;
+ gDeferredAvatarEyesProgram.mShaderFiles.clear();
+ gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarEyesProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredAvatarEyesProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader";
gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true;
gDeferredFullbrightProgram.mFeatures.hasGamma = true;
gDeferredFullbrightProgram.mFeatures.hasTransport = true;
- gDeferredFullbrightProgram.mFeatures.isFullbright = true;
+ gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits;
gDeferredFullbrightProgram.mShaderFiles.clear();
gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1153,10 +1331,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ std::string fragment;
+
+ if (multisample)
+ {
+ fragment = "deferred/softenLightMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/softenLightF.glsl";
+ }
+
gDeferredSoftenProgram.mName = "Deferred Soften Shader";
gDeferredSoftenProgram.mShaderFiles.clear();
gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSoftenProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
@@ -1230,41 +1419,106 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
+ gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
gDeferredAvatarAlphaProgram.mShaderFiles.clear();
gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
}
if (success)
{
+ std::string fragment;
+ if (multisample)
+ {
+ fragment = "deferred/postDeferredMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/postDeferredF.glsl";
+ }
+
gDeferredPostProgram.mName = "Deferred Post Shader";
gDeferredPostProgram.mShaderFiles.clear();
gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredPostProgram.createShader(NULL, NULL);
}
if (success)
{
+ std::string fragment;
+ if (multisample)
+ {
+ fragment = "deferred/postDeferredNoDoFMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/postDeferredNoDoFF.glsl";
+ }
+
gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
gDeferredPostNoDoFProgram.mShaderFiles.clear();
gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredPostNoDoFProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader";
+ //gWLSkyProgram.mFeatures.hasGamma = true;
+ gDeferredWLSkyProgram.mShaderFiles.clear();
+ gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ success = gDeferredWLSkyProgram.createShader(NULL, &mWLUniforms);
+ }
+
+ if (success)
+ {
+ gDeferredWLCloudProgram.mName = "Deferred Windlight Cloud Program";
+ gDeferredWLCloudProgram.mShaderFiles.clear();
+ gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ success = gDeferredWLCloudProgram.createShader(NULL, &mWLUniforms);
+ }
+
+ if (success)
+ {
+ gDeferredStarProgram.mName = "Deferred Star Program";
+ gDeferredStarProgram.mShaderFiles.clear();
+ gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ success = gDeferredStarProgram.createShader(NULL, &mWLUniforms);
+ }
+
if (mVertexShaderLevel[SHADER_DEFERRED] > 1)
{
if (success)
{
+ std::string fragment;
+ if (multisample)
+ {
+ fragment = "deferred/edgeMSF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/edgeF.glsl";
+ }
+
gDeferredEdgeProgram.mName = "Deferred Edge Shader";
gDeferredEdgeProgram.mShaderFiles.clear();
gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredEdgeProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredEdgeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredEdgeProgram.createShader(NULL, NULL);
}
@@ -1272,8 +1526,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (mVertexShaderLevel[SHADER_DEFERRED] > 2)
{
-
-
if (success)
{
gDeferredPostGIProgram.mName = "Deferred Post GI Shader";
@@ -1321,7 +1573,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
BOOL LLViewerShaderMgr::loadShadersObject()
{
BOOL success = TRUE;
-
+
if (mVertexShaderLevel[SHADER_OBJECT] == 0)
{
gObjectShinyProgram.unload();
@@ -1332,6 +1584,14 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterProgram.unload();
gObjectFullbrightProgram.unload();
gObjectFullbrightWaterProgram.unload();
+ gObjectShinyNonIndexedProgram.unload();
+ gObjectFullbrightShinyNonIndexedProgram.unload();
+ gObjectFullbrightShinyNonIndexedWaterProgram.unload();
+ gObjectShinyNonIndexedWaterProgram.unload();
+ gObjectSimpleNonIndexedProgram.unload();
+ gObjectSimpleNonIndexedWaterProgram.unload();
+ gObjectFullbrightNonIndexedProgram.unload();
+ gObjectFullbrightNonIndexedWaterProgram.unload();
gSkinnedObjectSimpleProgram.unload();
gSkinnedObjectFullbrightProgram.unload();
gSkinnedObjectFullbrightShinyProgram.unload();
@@ -1346,12 +1606,144 @@ BOOL LLViewerShaderMgr::loadShadersObject()
if (success)
{
+ gObjectSimpleNonIndexedProgram.mName = "Non indexed Shader";
+ gObjectSimpleNonIndexedProgram.mFeatures.calculatesLighting = true;
+ gObjectSimpleNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true;
+ gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true;
+ gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true;
+ gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true;
+ gObjectSimpleNonIndexedProgram.mShaderFiles.clear();
+ gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectSimpleNonIndexedWaterProgram.mName = "Non indexed Water Shader";
+ gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesLighting = true;
+ gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectSimpleNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectSimpleNonIndexedWaterProgram.mFeatures.hasAtmospherics = true;
+ gObjectSimpleNonIndexedWaterProgram.mFeatures.hasLighting = true;
+ gObjectSimpleNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+ gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear();
+ gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader";
+ gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightNonIndexedProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightNonIndexedProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightNonIndexedProgram.mFeatures.disableTextureIndex = true;
+ gObjectFullbrightNonIndexedProgram.mShaderFiles.clear();
+ gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightNonIndexedWaterProgram.mName = "Non Indexed Fullbright Water Shader";
+ gObjectFullbrightNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightNonIndexedWaterProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+ gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear();
+ gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectShinyNonIndexedProgram.mName = "Non Indexed Shiny Shader";
+ gObjectShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectShinyNonIndexedProgram.mFeatures.calculatesLighting = true;
+ gObjectShinyNonIndexedProgram.mFeatures.hasGamma = true;
+ gObjectShinyNonIndexedProgram.mFeatures.hasAtmospherics = true;
+ gObjectShinyNonIndexedProgram.mFeatures.isShiny = true;
+ gObjectShinyNonIndexedProgram.mFeatures.disableTextureIndex = true;
+ gObjectShinyNonIndexedProgram.mShaderFiles.clear();
+ gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+ if (success)
+ {
+ gObjectShinyNonIndexedWaterProgram.mName = "Non Indexed Shiny Water Shader";
+ gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesLighting = true;
+ gObjectShinyNonIndexedWaterProgram.mFeatures.isShiny = true;
+ gObjectShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectShinyNonIndexedWaterProgram.mFeatures.hasAtmospherics = true;
+ gObjectShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+ gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear();
+ gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader";
+ gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightShinyNonIndexedProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightShinyNonIndexedProgram.mFeatures.isShiny = true;
+ gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightShinyNonIndexedProgram.mFeatures.disableTextureIndex = true;
+ gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear();
+ gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightShinyNonIndexedWaterProgram.mName = "Non Indexed Fullbright Shiny Water Shader";
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isShiny = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+ gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear();
+ gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+ if (success)
+ {
gObjectSimpleProgram.mName = "Simple Shader";
gObjectSimpleProgram.mFeatures.calculatesLighting = true;
gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true;
gObjectSimpleProgram.mFeatures.hasGamma = true;
gObjectSimpleProgram.mFeatures.hasAtmospherics = true;
gObjectSimpleProgram.mFeatures.hasLighting = true;
+ gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectSimpleProgram.mShaderFiles.clear();
gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1367,6 +1759,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterProgram.mFeatures.hasWaterFog = true;
gObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true;
gObjectSimpleWaterProgram.mFeatures.hasLighting = true;
+ gObjectSimpleWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectSimpleWaterProgram.mShaderFiles.clear();
gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1382,6 +1775,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightProgram.mFeatures.hasGamma = true;
gObjectFullbrightProgram.mFeatures.hasTransport = true;
gObjectFullbrightProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightProgram.mShaderFiles.clear();
gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1396,6 +1790,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
gObjectFullbrightWaterProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightWaterProgram.mShaderFiles.clear();
gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1412,6 +1807,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectShinyProgram.mFeatures.hasGamma = true;
gObjectShinyProgram.mFeatures.hasAtmospherics = true;
gObjectShinyProgram.mFeatures.isShiny = true;
+ gObjectShinyProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectShinyProgram.mShaderFiles.clear();
gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1427,6 +1823,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectShinyWaterProgram.mFeatures.isShiny = true;
gObjectShinyWaterProgram.mFeatures.hasWaterFog = true;
gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true;
+ gObjectShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectShinyWaterProgram.mShaderFiles.clear();
gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1443,6 +1840,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightShinyProgram.mFeatures.isShiny = true;
gObjectFullbrightShinyProgram.mFeatures.hasGamma = true;
gObjectFullbrightShinyProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightShinyProgram.mShaderFiles.clear();
gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1459,6 +1857,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true;
gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true;
gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1478,6 +1877,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true;
gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true;
gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedObjectSimpleProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectSimpleProgram.mShaderFiles.clear();
gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1493,6 +1893,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true;
gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectFullbrightProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1509,6 +1910,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedObjectFullbrightShinyProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1525,6 +1927,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true;
gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true;
+ gSkinnedObjectShinySimpleProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectShinySimpleProgram.mShaderFiles.clear();
gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1540,9 +1943,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true;
+ gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true;
gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1559,6 +1964,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
+ gSkinnedObjectFullbrightWaterProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1577,6 +1983,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
+ gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1595,6 +2002,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true;
+ gSkinnedObjectShinySimpleWaterProgram.mFeatures.disableTextureIndex = true;
gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear();
gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1635,6 +2043,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarProgram.mFeatures.hasGamma = true;
gAvatarProgram.mFeatures.hasAtmospherics = true;
gAvatarProgram.mFeatures.hasLighting = true;
+ gAvatarProgram.mFeatures.disableTextureIndex = true;
gAvatarProgram.mShaderFiles.clear();
gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1650,6 +2059,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarWaterProgram.mFeatures.hasWaterFog = true;
gAvatarWaterProgram.mFeatures.hasAtmospherics = true;
gAvatarWaterProgram.mFeatures.hasLighting = true;
+ gAvatarWaterProgram.mFeatures.disableTextureIndex = true;
gAvatarWaterProgram.mShaderFiles.clear();
gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1670,6 +2080,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
{
gAvatarPickProgram.mName = "Avatar Pick Shader";
gAvatarPickProgram.mFeatures.hasSkinning = true;
+ gAvatarPickProgram.mFeatures.disableTextureIndex = true;
gAvatarPickProgram.mShaderFiles.clear();
gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));
gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1686,6 +2097,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
gAvatarEyeballProgram.mFeatures.hasGamma = true;
gAvatarEyeballProgram.mFeatures.hasAtmospherics = true;
gAvatarEyeballProgram.mFeatures.hasLighting = true;
+ gAvatarEyeballProgram.mFeatures.disableTextureIndex = true;
gAvatarEyeballProgram.mShaderFiles.clear();
gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB));
gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1777,6 +2189,16 @@ std::string LLViewerShaderMgr::getShaderDirPrefix(void)
void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader)
{
- LLWLParamManager::instance()->updateShaderUniforms(shader);
- LLWaterParamManager::instance()->updateShaderUniforms(shader);
+ LLWLParamManager::getInstance()->updateShaderUniforms(shader);
+ LLWaterParamManager::getInstance()->updateShaderUniforms(shader);
+}
+
+LLViewerShaderMgr::shader_iter LLViewerShaderMgr::beginShaders() const
+{
+ return mShaderList.begin();
+}
+
+LLViewerShaderMgr::shader_iter LLViewerShaderMgr::endShaders() const
+{
+ return mShaderList.end();
}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 72ac5e02ee..efef9ec5b2 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -241,20 +241,12 @@ public:
base_iter_t mIter;
};
- shader_iter beginShaders() const
- {
- return mShaderList.begin();
- }
-
- shader_iter endShaders() const
- {
- return mShaderList.end();
- }
+ shader_iter beginShaders() const;
+ shader_iter endShaders() const;
+ /* virtual */ std::string getShaderDirPrefix(void);
- /* virtual */ std::string getShaderDirPrefix(void); // Virtual
-
- /* virtual */ void updateShaderUniforms(LLGLSLShader * shader); // Virtual
+ /* virtual */ void updateShaderUniforms(LLGLSLShader * shader);
private:
@@ -298,16 +290,25 @@ extern LLVector4 gShinyOrigin;
//object shaders
extern LLGLSLShader gObjectSimpleProgram;
extern LLGLSLShader gObjectSimpleWaterProgram;
+extern LLGLSLShader gObjectSimpleNonIndexedProgram;
+extern LLGLSLShader gObjectSimpleNonIndexedWaterProgram;
extern LLGLSLShader gObjectFullbrightProgram;
extern LLGLSLShader gObjectFullbrightWaterProgram;
+extern LLGLSLShader gObjectFullbrightNonIndexedProgram;
+extern LLGLSLShader gObjectFullbrightNonIndexedWaterProgram;
extern LLGLSLShader gObjectSimpleLODProgram;
extern LLGLSLShader gObjectFullbrightLODProgram;
extern LLGLSLShader gObjectFullbrightShinyProgram;
extern LLGLSLShader gObjectFullbrightShinyWaterProgram;
+extern LLGLSLShader gObjectFullbrightShinyNonIndexedProgram;
+extern LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram;
+
extern LLGLSLShader gObjectShinyProgram;
extern LLGLSLShader gObjectShinyWaterProgram;
+extern LLGLSLShader gObjectShinyNonIndexedProgram;
+extern LLGLSLShader gObjectShinyNonIndexedWaterProgram;
extern LLGLSLShader gSkinnedObjectSimpleProgram;
extern LLGLSLShader gSkinnedObjectFullbrightProgram;
@@ -349,6 +350,7 @@ extern LLGLSLShader gDeferredImpostorProgram;
extern LLGLSLShader gDeferredEdgeProgram;
extern LLGLSLShader gDeferredWaterProgram;
extern LLGLSLShader gDeferredDiffuseProgram;
+extern LLGLSLShader gDeferredNonIndexedDiffuseProgram;
extern LLGLSLShader gDeferredSkinnedDiffuseProgram;
extern LLGLSLShader gDeferredSkinnedBumpProgram;
extern LLGLSLShader gDeferredSkinnedAlphaProgram;
@@ -373,8 +375,11 @@ extern LLGLSLShader gDeferredAvatarShadowProgram;
extern LLGLSLShader gDeferredAttachmentShadowProgram;
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredFullbrightProgram;
+extern LLGLSLShader gDeferredAvatarEyesProgram;
extern LLGLSLShader gDeferredAvatarAlphaProgram;
-
+extern LLGLSLShader gDeferredWLSkyProgram;
+extern LLGLSLShader gDeferredWLCloudProgram;
+extern LLGLSLShader gDeferredStarProgram;
extern LLGLSLShader gLuminanceGatherProgram;
//current avatar shader parameter pointer
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index af06421bf9..4da0f80a00 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1168,6 +1168,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
mSavedRawDiscardLevel = -1 ;
mDesiredSavedRawDiscardLevel = -1 ;
mLastReferencedSavedRawImageTime = 0.0f ;
+ mKeptSavedRawImageTime = 0.f ;
mLastCallBackActiveTime = 0.f;
}
@@ -2696,8 +2697,16 @@ void LLViewerFetchedTexture::saveRawImage()
mLastReferencedSavedRawImageTime = sCurrentTime ;
}
-void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard)
+void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time)
{
+ mKeptSavedRawImageTime = kept_time ;
+ mLastReferencedSavedRawImageTime = sCurrentTime ;
+
+ if(mSavedRawDiscardLevel > -1 && mSavedRawDiscardLevel <= desired_discard)
+ {
+ return ; //raw imge is ready.
+ }
+
if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)
{
mForceToSaveRawImage = TRUE ;
@@ -2713,11 +2722,16 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard)
mRawImage = NULL ;
mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
- }
+ }
}
}
void LLViewerFetchedTexture::destroySavedRawImage()
{
+ if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime)
+ {
+ return ; //keep the saved raw image.
+ }
+
mForceToSaveRawImage = FALSE ;
mSaveRawImage = FALSE ;
@@ -2729,6 +2743,7 @@ void LLViewerFetchedTexture::destroySavedRawImage()
mSavedRawDiscardLevel = -1 ;
mDesiredSavedRawDiscardLevel = -1 ;
mLastReferencedSavedRawImageTime = 0.0f ;
+ mKeptSavedRawImageTime = 0.f ;
}
LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index d512f8ec3a..c5b8c8923a 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -465,7 +465,7 @@ public:
S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
BOOL isRawImageValid()const { return mIsRawImageValid ; }
- void forceToSaveRawImage(S32 desired_discard = 0) ;
+ void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
void destroySavedRawImage() ;
LLImageRaw* getSavedRawImage() ;
@@ -550,6 +550,7 @@ protected:
S32 mSavedRawDiscardLevel;
S32 mDesiredSavedRawDiscardLevel;
F32 mLastReferencedSavedRawImageTime ;
+ F32 mKeptSavedRawImageTime ;
//a small version of the copy of the raw image (<= 64 * 64)
LLPointer<LLImageRaw> mCachedRawImage;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index d9ff931575..d24174adea 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -76,7 +76,6 @@ LLStat LLViewerTextureList::sFormattedMemStat(32, TRUE);
LLViewerTextureList gTextureList;
static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images");
-U32 LLViewerTextureList::sRenderThreadID = 0 ;
///////////////////////////////////////////////////////////////////////////////
LLViewerTextureList::LLViewerTextureList()
@@ -89,16 +88,13 @@ LLViewerTextureList::LLViewerTextureList()
}
void LLViewerTextureList::init()
-{
- sRenderThreadID = LLThread::currentID() ;
-
+{
mInitialized = TRUE ;
sNumImages = 0;
+ mUpdateStats = TRUE;
mMaxResidentTexMemInMegaBytes = 0;
mMaxTotalTextureMemInMegaBytes = 0 ;
- mUpdateStats = TRUE;
-
// Update how much texture RAM we're allowed to use.
updateMaxResidentTexMem(0); // 0 = use current
@@ -110,8 +106,8 @@ void LLViewerTextureList::doPreloadImages()
{
LL_DEBUGS("ViewerImages") << "Preloading images..." << LL_ENDL;
- llassert_always(mInitialized) ;
- llassert_always(mImageList.empty()) ;
+ llassert_always(mInitialized) ;
+ llassert_always(mImageList.empty()) ;
llassert_always(mUUIDMap.empty()) ;
// Set the "missing asset" image
@@ -283,6 +279,8 @@ void LLViewerTextureList::shutdown()
mUUIDMap.clear();
mImageList.clear();
+
+ mInitialized = FALSE ; //prevent loading textures again.
}
void LLViewerTextureList::dump()
@@ -330,6 +328,11 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
LLGLenum primary_format,
const LLUUID& force_id)
{
+ if(!mInitialized)
+ {
+ return NULL ;
+ }
+
std::string full_path = gDirUtilp->findSkinnedFilename("textures", filename);
if (full_path.empty())
{
@@ -350,6 +353,11 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string&
LLGLenum primary_format,
const LLUUID& force_id)
{
+ if(!mInitialized)
+ {
+ return NULL ;
+ }
+
// generate UUID based on hash of filename
LLUUID new_id;
if (force_id.notNull())
@@ -409,6 +417,11 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
LLGLenum primary_format,
LLHost request_from_host)
{
+ if(!mInitialized)
+ {
+ return NULL ;
+ }
+
// Return the image with ID image_id
// If the image is not found, creates new image and
// enqueues a request for transmission
@@ -487,10 +500,9 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id)
return iter->second;
}
-void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image, U32 thread_id)
+void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
{
llassert_always(mInitialized) ;
- llassert_always(sRenderThreadID == thread_id);
llassert(image);
if (image->isInImageList())
{
@@ -504,10 +516,9 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image, U32 thre
image->setInImageList(TRUE) ;
}
-void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image, U32 thread_id)
+void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
{
llassert_always(mInitialized) ;
- llassert_always(sRenderThreadID == thread_id);
llassert(image);
if (!image->isInImageList())
{
@@ -644,10 +655,7 @@ void LLViewerTextureList::updateImagesDecodePriorities()
const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding
const F32 MAX_INACTIVE_TIME = 50.f; // actually delete
S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
- if (imagep->hasCallbacks())
- {
- min_refs++; // Add an extra reference if we're on the loaded callback list
- }
+
S32 num_refs = imagep->getNumRefs();
if (num_refs == min_refs)
{
@@ -704,9 +712,9 @@ void LLViewerTextureList::updateImagesDecodePriorities()
if ((decode_priority_test < old_priority_test * .8f) ||
(decode_priority_test > old_priority_test * 1.25f))
{
- removeImageFromList(imagep, sRenderThreadID);
+ removeImageFromList(imagep);
imagep->setDecodePriority(decode_priority);
- addImageToList(imagep, sRenderThreadID);
+ addImageToList(imagep);
}
update_counter--;
}
@@ -878,8 +886,6 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
{
LLTimer timer;
- llassert_always(sRenderThreadID == LLThread::currentID());
-
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
for (image_priority_list_t::iterator iter = mImageList.begin();
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index d02b6be6b5..7f4dd0ae88 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -121,8 +121,8 @@ private:
void addImage(LLViewerFetchedTexture *image);
void deleteImage(LLViewerFetchedTexture *image);
- void addImageToList(LLViewerFetchedTexture *image, U32 thread_id = LLThread::currentID());
- void removeImageFromList(LLViewerFetchedTexture *image, U32 thread_id = LLThread::currentID());
+ void addImageToList(LLViewerFetchedTexture *image);
+ void removeImageFromList(LLViewerFetchedTexture *image);
LLViewerFetchedTexture * getImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
@@ -208,9 +208,6 @@ public:
private:
static S32 sNumImages;
static void (*sUUIDCallback)(void**, const LLUUID &);
-
- //debug use
- static U32 sRenderThreadID;
};
class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIImageList>
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 6fe79c2e85..cff166b825 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -601,7 +601,7 @@ public:
ypos += y_inc;
- if (gSavedSettings.getBOOL("MeshEnabled"))
+ if (gMeshRepo.meshRezEnabled())
{
addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f)));
@@ -1638,6 +1638,7 @@ LLViewerWindow::LLViewerWindow(
gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
}
LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+ LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ;
if (LLFeatureManager::getInstance()->isSafe()
|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
@@ -1978,7 +1979,10 @@ void LLViewerWindow::shutdownViews()
// destroy the nav bar, not currently part of gViewerWindow
// *TODO: Make LLNavigationBar part of gViewerWindow
+ if (LLNavigationBar::instanceExists())
+ {
delete LLNavigationBar::getInstance();
+ }
// destroy menus after instantiating navbar above, as it needs
// access to gMenuHolder
@@ -4511,6 +4515,14 @@ void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
}
+void LLViewerWindow::revealIntroPanel()
+{
+ if (mProgressView)
+ {
+ mProgressView->revealIntroPanel();
+ }
+}
+
void LLViewerWindow::setShowProgress(const BOOL show)
{
if (mProgressView)
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index df6928aa1d..ff49ed1f62 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -271,6 +271,7 @@ public:
void setProgressMessage(const std::string& msg);
void setProgressCancelButtonVisible( BOOL b, const std::string& label = LLStringUtil::null );
LLProgressView *getProgressView() const;
+ void revealIntroPanel();
void updateObjectUnderCursor();
diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp
index 25f2687fe2..d8de979f56 100644
--- a/indra/newview/llvlmanager.cpp
+++ b/indra/newview/llvlmanager.cpp
@@ -94,7 +94,7 @@ void LLVLManager::unpackData(const S32 num_packets)
}
else if (CLOUD_LAYER_CODE == datap->mType)
{
- datap->mRegionp->mCloudLayer.decompress(bit_pack, &goph);
+
}
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index ec2b5a4c98..3f98df9eb9 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -56,6 +56,7 @@
#include "lleditingmotion.h"
#include "llemote.h"
//#include "llfirstuse.h"
+#include "llfloatertools.h"
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
@@ -1541,7 +1542,35 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
return TRUE;
}
}
+
+ if (isSelf())
+ {
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = (*attachment_iter);
+
+ if (attached_object && !attached_object->isDead() && attachment->getValid())
+ {
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable->isState(LLDrawable::RIGGED))
+ { //regenerate octree for rigged attachment
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
+ }
+ }
+ }
+ }
+ }
}
+
+
LLVector3 position;
if (mNameText.notNull() && mNameText->lineSegmentIntersect(start, end, position))
@@ -1557,6 +1586,56 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
return FALSE;
}
+LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end,
+ S32 face,
+ BOOL pick_transparent,
+ S32* face_hit,
+ LLVector3* intersection,
+ LLVector2* tex_coord,
+ LLVector3* normal,
+ LLVector3* bi_normal)
+{
+ if (isSelf() && !gAgent.needsRenderAvatar())
+ {
+ return NULL;
+ }
+
+ LLViewerObject* hit = NULL;
+
+ if (lineSegmentBoundingBox(start, end))
+ {
+ LLVector3 local_end = end;
+ LLVector3 local_intersection;
+
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ LLViewerObject* attached_object = (*attachment_iter);
+
+ if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, face_hit, &local_intersection, tex_coord, normal, bi_normal))
+ {
+ local_end = local_intersection;
+ if (intersection)
+ {
+ *intersection = local_intersection;
+ }
+
+ hit = attached_object;
+ }
+ }
+ }
+ }
+
+ return hit;
+}
+
//-----------------------------------------------------------------------------
// parseSkeletonFile()
//-----------------------------------------------------------------------------
@@ -4968,19 +5047,6 @@ void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
//-----------------------------------------------------------------------------
void LLVOAvatar::resetJointPositionsToDefault( void )
{
- const LLVector3& avPos = getCharacterPosition();
-
- //Reposition the pelvis
- LLJoint* pPelvis = mRoot.findJoint("mPelvis");
- if ( pPelvis )
- {
- pPelvis->setPosition( avPos + pPelvis->getPosition() );
- }
- else
- {
- llwarns<<"Can't get pelvis joint."<<llendl;
- return;
- }
//Subsequent joints are relative to pelvis
for( S32 i = 0; i < (S32)mNumJoints; ++i )
@@ -4991,7 +5057,7 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
pJoint->setId( LLUUID::null );
//restore joints to default positions, however skip over the pelvis
- if ( pJoint && pPelvis != pJoint )
+ if ( pJoint )
{
pJoint->restoreOldXform();
}
@@ -6017,7 +6083,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
if ( pVObj )
{
- const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID() );
+ const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
if ( pSkinData )
{
const int jointCnt = pSkinData->mJointNames.size();
@@ -6028,6 +6094,14 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
if ( bindCnt > 0 )
{
LLVOAvatar::resetJointPositionsToDefault();
+ //Need to handle the repositioning of the cam, updating rig data etc during outfit editing
+ //This handles the case where we detach a replacement rig.
+ if ( gAgentCamera.cameraCustomizeAvatar() )
+ {
+ gAgent.unpauseAnimation();
+ //Still want to refocus on head bone
+ gAgentCamera.changeCameraToCustomizeAvatar();
+ }
}
}
}
@@ -7196,9 +7270,9 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
llinfos << "Re-requesting AvatarAppearance for object: " << getID() << llendl;
LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
mRuthTimer.reset();
- }
- else
- {
+ }
+ else
+ {
llinfos << "That's okay, we already have a non-default shape for object: " << getID() << llendl;
// we don't really care.
}
@@ -8168,6 +8242,8 @@ U32 LLVOAvatar::getPartitionType() const
//static
void LLVOAvatar::updateImpostors()
{
+ LLCharacter::sAllowInstancesChange = FALSE ;
+
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
{
@@ -8177,6 +8253,8 @@ void LLVOAvatar::updateImpostors()
gPipeline.generateImpostor(avatar);
}
}
+
+ LLCharacter::sAllowInstancesChange = TRUE ;
}
BOOL LLVOAvatar::isImpostor() const
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 295799fd24..03c0498a2a 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -145,6 +145,14 @@ public:
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
LLVector3* normal = NULL, // return the surface normal at the intersection point
LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point
+ LLViewerObject* lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end,
+ S32 face = -1, // which face to check, -1 = ALL_SIDES
+ BOOL pick_transparent = FALSE,
+ S32* face_hit = NULL, // which face was hit
+ LLVector3* intersection = NULL, // return the intersection point
+ LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
+ LLVector3* normal = NULL, // return the surface normal at the intersection point
+ LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point
//--------------------------------------------------------------------
// LLCharacter interface and related
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index b888a263d0..f0b5b50feb 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -76,6 +76,7 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
S32 size = -1;
BOOL success;
+ mDP.assignBuffer(mBuffer, 0);
success = check_read(apr_file, &mLocalID, sizeof(U32));
if(success)
{
@@ -136,10 +137,7 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
LLVOCacheEntry::~LLVOCacheEntry()
{
- if(mBuffer)
- {
- delete[] mBuffer;
- }
+ mDP.freeBuffer();
}
@@ -285,8 +283,6 @@ LLVOCache::~LLVOCache()
void LLVOCache::setDirNames(ELLPath location)
{
- std::string delem = gDirUtilp->getDirDelimiter();
-
mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename);
mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
}
@@ -339,8 +335,7 @@ void LLVOCache::removeCache(ELLPath location)
llinfos << "about to remove the object cache due to settings." << llendl ;
- std::string delem = gDirUtilp->getDirDelimiter();
- std::string mask = delem + "*";
+ std::string mask = "*";
std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
llinfos << "Removing cache at " << cache_dir << llendl;
gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files
@@ -361,8 +356,7 @@ void LLVOCache::removeCache()
llinfos << "about to remove the object cache due to some error." << llendl ;
- std::string delem = gDirUtilp->getDirDelimiter();
- std::string mask = delem + "*";
+ std::string mask = "*";
llinfos << "Removing cache at " << mObjectCacheDirName << llendl;
gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);
diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp
deleted file mode 100644
index 78aa6e6ab8..0000000000
--- a/indra/newview/llvoclouds.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/**
- * @file llvoclouds.cpp
- * @brief Implementation of LLVOClouds class which is a derivation fo LLViewerObject
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llvoclouds.h"
-
-#include "lldrawpoolalpha.h"
-
-#include "llviewercontrol.h"
-
-#include "llagent.h" // to get camera position
-#include "lldrawable.h"
-#include "llface.h"
-#include "llprimitive.h"
-#include "llsky.h"
-#include "llviewercamera.h"
-#include "llviewertexturelist.h"
-#include "llviewerobjectlist.h"
-#include "llviewerregion.h"
-#include "llvosky.h"
-#include "llworld.h"
-#include "pipeline.h"
-#include "llspatialpartition.h"
-
-LLUUID gCloudTextureID = IMG_CLOUD_POOF;
-
-
-LLVOClouds::LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLAlphaObject(id, LL_VO_CLOUDS, regionp)
-{
- mCloudGroupp = NULL;
- mbCanSelect = FALSE;
- setNumTEs(1);
- LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(gCloudTextureID);
- image->setBoostLevel(LLViewerTexture::BOOST_CLOUDS);
- setTEImage(0, image);
-}
-
-
-LLVOClouds::~LLVOClouds()
-{
-}
-
-
-BOOL LLVOClouds::isActive() const
-{
- return TRUE;
-}
-
-BOOL LLVOClouds::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
-{
- static LLFastTimer::DeclareTimer ftm("Idle Clouds");
- LLFastTimer t(ftm);
-
- if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
- {
- return TRUE;
- }
-
- // Set dirty flag (so renderer will rebuild primitive)
- if (mDrawable)
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- }
-
- return TRUE;
-}
-
-
-void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent)
-{
- mAppAngle = 50;
- mPixelArea = 1500*100;
-}
-
-void LLVOClouds::updateTextures()
-{
- getTEImage(0)->addTextureStats(mPixelArea);
-}
-
-LLDrawable* LLVOClouds::createDrawable(LLPipeline *pipeline)
-{
- pipeline->allocDrawable(this);
- mDrawable->setLit(FALSE);
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_CLOUDS);
-
- return mDrawable;
-}
-
-static LLFastTimer::DeclareTimer FTM_UPDATE_CLOUDS("Update Clouds");
-
-BOOL LLVOClouds::updateGeometry(LLDrawable *drawable)
-{
- LLFastTimer ftm(FTM_UPDATE_CLOUDS);
- if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS)))
- {
- return TRUE;
- }
-
- if (drawable->isVisible())
- {
- dirtySpatialGroup(TRUE);
- }
-
- LLFace *facep;
-
- S32 num_faces = mCloudGroupp->getNumPuffs();
-
- if (num_faces > drawable->getNumFaces())
- {
- drawable->setNumFacesFast(num_faces, NULL, getTEImage(0));
- }
-
- mDepth = (getPositionAgent()-LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();
-
- S32 face_indx = 0;
- for ( ; face_indx < num_faces; face_indx++)
- {
- facep = drawable->getFace(face_indx);
- if (!facep)
- {
- llwarns << "No facep for index " << face_indx << llendl;
- continue;
- }
-
- facep->setSize(4, 6);
-
- facep->setTEOffset(face_indx);
- facep->setTexture(getTEImage(0));
- const LLCloudPuff &puff = mCloudGroupp->getPuff(face_indx);
- const LLVector3 puff_pos_agent = gAgent.getPosAgentFromGlobal(puff.getPositionGlobal());
- facep->mCenterLocal = puff_pos_agent;
- /// Update cloud color based on sun color.
- LLColor4 float_color(LLColor3(gSky.getSunDiffuseColor() + gSky.getSunAmbientColor()),puff.getAlpha());
- facep->setFaceColor(float_color);
- }
- for ( ; face_indx < drawable->getNumFaces(); face_indx++)
- {
- facep = drawable->getFace(face_indx);
- if (!facep)
- {
- llwarns << "No facep for index " << face_indx << llendl;
- continue;
- }
-
- facep->setTEOffset(face_indx);
- facep->setSize(0,0);
- }
-
- drawable->movePartition();
-
- return TRUE;
-}
-
-F32 LLVOClouds::getPartSize(S32 idx)
-{
- return (CLOUD_PUFF_HEIGHT+CLOUD_PUFF_WIDTH)*0.5f;
-}
-
-void LLVOClouds::getGeometry(S32 te,
- LLStrider<LLVector3>& verticesp,
- LLStrider<LLVector3>& normalsp,
- LLStrider<LLVector2>& texcoordsp,
- LLStrider<LLColor4U>& colorsp,
- LLStrider<U16>& indicesp)
-{
-
- if (te >= mCloudGroupp->getNumPuffs())
- {
- return;
- }
-
- LLDrawable* drawable = mDrawable;
- LLFace *facep = drawable->getFace(te);
-
- if (!facep->hasGeometry())
- {
- return;
- }
-
- LLVector3 normal(0.f,0.f,-1.f);
-
- const LLCloudPuff &puff = mCloudGroupp->getPuff(te);
- S32 index_offset = facep->getGeomIndex();
- LLColor4 float_color(LLColor3(gSky.getSunDiffuseColor() + gSky.getSunAmbientColor()),puff.getAlpha());
- LLColor4U color;
- color.setVec(float_color);
- facep->setFaceColor(float_color);
-
-
- LLVector3 up;
- LLVector3 right;
- LLVector3 at;
-
- const LLVector3& puff_pos_agent = facep->mCenterLocal;
- LLVector2 uvs[4];
-
- uvs[0].setVec(0.f, 1.f);
- uvs[1].setVec(0.f, 0.f);
- uvs[2].setVec(1.f, 1.f);
- uvs[3].setVec(1.f, 0.f);
-
- LLVector3 vtx[4];
-
- at = LLViewerCamera::getInstance()->getAtAxis();
- right = at % LLVector3(0.f, 0.f, 1.f);
- right.normVec();
- up = right % at;
- up.normVec();
- right *= 0.5f*CLOUD_PUFF_WIDTH;
- up *= 0.5f*CLOUD_PUFF_HEIGHT;;
-
- *colorsp++ = color;
- *colorsp++ = color;
- *colorsp++ = color;
- *colorsp++ = color;
-
- vtx[0] = puff_pos_agent - right + up;
- vtx[1] = puff_pos_agent - right - up;
- vtx[2] = puff_pos_agent + right + up;
- vtx[3] = puff_pos_agent + right - up;
-
- *verticesp++ = vtx[0];
- *verticesp++ = vtx[1];
- *verticesp++ = vtx[2];
- *verticesp++ = vtx[3];
-
- *texcoordsp++ = uvs[0];
- *texcoordsp++ = uvs[1];
- *texcoordsp++ = uvs[2];
- *texcoordsp++ = uvs[3];
-
- *normalsp++ = normal;
- *normalsp++ = normal;
- *normalsp++ = normal;
- *normalsp++ = normal;
-
- *indicesp++ = index_offset + 0;
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 2;
-
- *indicesp++ = index_offset + 1;
- *indicesp++ = index_offset + 3;
- *indicesp++ = index_offset + 2;
-}
-
-U32 LLVOClouds::getPartitionType() const
-{
- return LLViewerRegion::PARTITION_CLOUD;
-}
-
-// virtual
-void LLVOClouds::updateDrawable(BOOL force_damped)
-{
- // Force an immediate rebuild on any update
- if (mDrawable.notNull())
- {
- mDrawable->updateXform(TRUE);
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
- }
- clearChanged(SHIFTED);
-}
-
-LLCloudPartition::LLCloudPartition()
-{
- mDrawableType = LLPipeline::RENDER_TYPE_CLOUDS;
- mPartitionType = LLViewerRegion::PARTITION_CLOUD;
-}
-
diff --git a/indra/newview/llvoclouds.h b/indra/newview/llvoclouds.h
deleted file mode 100644
index 430923a108..0000000000
--- a/indra/newview/llvoclouds.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file llvoclouds.h
- * @brief Description of LLVOClouds class
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLVOCLOUDS_H
-#define LL_LLVOCLOUDS_H
-
-#include "llviewerobject.h"
-#include "lltable.h"
-#include "v4coloru.h"
-
-class LLViewerTexture;
-class LLViewerCloudGroup;
-
-class LLCloudGroup;
-
-
-class LLVOClouds : public LLAlphaObject
-{
-public:
- LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp );
-
- // Initialize data that's only inited once per class.
- static void initClass();
-
- void updateDrawable(BOOL force_damped);
-
- /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
- /*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
- /*virtual*/ void getGeometry(S32 te,
- LLStrider<LLVector3>& verticesp,
- LLStrider<LLVector3>& normalsp,
- LLStrider<LLVector2>& texcoordsp,
- LLStrider<LLColor4U>& colorsp,
- LLStrider<U16>& indicesp);
-
- /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
- F32 getPartSize(S32 idx);
-
- /*virtual*/ void updateTextures();
- /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area
-
- void updateFaceSize(S32 idx) { }
- BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
-
- virtual U32 getPartitionType() const;
-
- void setCloudGroup(LLCloudGroup *cgp) { mCloudGroupp = cgp; }
-protected:
- virtual ~LLVOClouds();
-
- LLCloudGroup *mCloudGroupp;
-};
-
-extern LLUUID gCloudTextureID;
-
-#endif // LL_VO_CLOUDS_H
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 6ee6822e2f..cd2bbad620 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -195,12 +195,13 @@ static LLVivoxVoiceClientFriendsObserver *friendslist_listener = NULL;
class LLVivoxVoiceClientCapResponder : public LLHTTPClient::Responder
{
public:
- LLVivoxVoiceClientCapResponder(void){};
+ LLVivoxVoiceClientCapResponder(LLVivoxVoiceClient::state requesting_state) : mRequestingState(requesting_state) {};
virtual void error(U32 status, const std::string& reason); // called with bad status codes
virtual void result(const LLSD& content);
private:
+ LLVivoxVoiceClient::state mRequestingState; // state
};
void LLVivoxVoiceClientCapResponder::error(U32 status, const std::string& reason)
@@ -208,6 +209,7 @@ void LLVivoxVoiceClientCapResponder::error(U32 status, const std::string& reason
LL_WARNS("Voice") << "LLVivoxVoiceClientCapResponder::error("
<< status << ": " << reason << ")"
<< LL_ENDL;
+ LLVivoxVoiceClient::getInstance()->sessionTerminate();
}
void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
@@ -216,12 +218,12 @@ void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest response:" << ll_pretty_print_sd(content) << LL_ENDL;
+ std::string uri;
+ std::string credentials;
+
if ( content.has("voice_credentials") )
{
LLSD voice_credentials = content["voice_credentials"];
- std::string uri;
- std::string credentials;
-
if ( voice_credentials.has("channel_uri") )
{
uri = voice_credentials["channel_uri"].asString();
@@ -231,7 +233,12 @@ void LLVivoxVoiceClientCapResponder::result(const LLSD& content)
credentials =
voice_credentials["channel_credentials"].asString();
}
-
+ }
+
+ // set the spatial channel. If no voice credentials or uri are
+ // available, then we simply drop out of voice spatially.
+ if(LLVivoxVoiceClient::getInstance()->parcelVoiceInfoReceived(mRequestingState))
+ {
LLVivoxVoiceClient::getInstance()->setSpatialChannel(uri, credentials);
}
}
@@ -551,18 +558,27 @@ void LLVivoxVoiceClient::userAuthorized(const std::string& user_id, const LLUUID
void LLVivoxVoiceClient::requestVoiceAccountProvision(S32 retries)
{
- if ( gAgent.getRegion() && mVoiceEnabled )
+ LLViewerRegion *region = gAgent.getRegion();
+
+ if ( region && mVoiceEnabled )
{
std::string url =
- gAgent.getRegion()->getCapability(
- "ProvisionVoiceAccountRequest");
-
- if ( url == "" ) return;
-
+ region->getCapability("ProvisionVoiceAccountRequest");
+
+ if ( url.empty() )
+ {
+ // we've not received the capability yet, so return.
+ // the password will remain empty, so we'll remain in
+ // stateIdle
+ return;
+ }
+
LLHTTPClient::post(
- url,
- LLSD(),
- new LLVivoxVoiceAccountProvisionResponder(retries));
+ url,
+ LLSD(),
+ new LLVivoxVoiceAccountProvisionResponder(retries));
+
+ setState(stateConnectorStart);
}
}
@@ -673,7 +689,8 @@ std::string LLVivoxVoiceClient::state2string(LLVivoxVoiceClient::state inState)
CASE(stateVoiceFontsWait);
CASE(stateVoiceFontsReceived);
CASE(stateCreatingSessionGroup);
- CASE(stateNoChannel);
+ CASE(stateNoChannel);
+ CASE(stateRetrievingParcelVoiceInfo);
CASE(stateJoiningSession);
CASE(stateSessionJoined);
CASE(stateRunning);
@@ -741,42 +758,6 @@ void LLVivoxVoiceClient::stateMachine()
}
}
- // Check for parcel boundary crossing
- {
- LLViewerRegion *region = gAgent.getRegion();
- LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-
- if(region && parcel)
- {
- S32 parcelLocalID = parcel->getLocalID();
- std::string regionName = region->getName();
- std::string capURI = region->getCapability("ParcelVoiceInfoRequest");
-
-// LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL;
-
- // The region name starts out empty and gets filled in later.
- // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
- // If either is empty, wait for the next time around.
- if(!regionName.empty())
- {
- if(!capURI.empty())
- {
- if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName))
- {
- // We have changed parcels. Initiate a parcel channel lookup.
- mCurrentParcelLocalID = parcelLocalID;
- mCurrentRegionName = regionName;
-
- parcelChanged();
- }
- }
- else
- {
- LL_WARNS_ONCE("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
- }
- }
- }
- }
switch(getState())
{
@@ -1026,22 +1007,9 @@ void LLVivoxVoiceClient::stateMachine()
}
else if(!mAccountName.empty())
{
- LLViewerRegion *region = gAgent.getRegion();
-
- if(region)
+ if ( mAccountPassword.empty() )
{
- if ( region->getCapability("ProvisionVoiceAccountRequest") != "" )
- {
- if ( mAccountPassword.empty() )
- {
- requestVoiceAccountProvision();
- }
- setState(stateConnectorStart);
- }
- else
- {
- LL_WARNS_ONCE("Voice") << "region doesn't have ProvisionVoiceAccountRequest capability!" << LL_ENDL;
- }
+ requestVoiceAccountProvision();
}
}
break;
@@ -1382,11 +1350,7 @@ void LLVivoxVoiceClient::stateMachine()
setState(stateCreatingSessionGroup);
sessionGroupCreateSendMessage();
#else
- // Not using session groups -- skip the stateCreatingSessionGroup state.
- setState(stateNoChannel);
-
- // Initial kick-off of channel lookup logic
- parcelChanged();
+ setState(stateNoChannel);
#endif
break;
@@ -1399,19 +1363,29 @@ void LLVivoxVoiceClient::stateMachine()
}
else if(!mMainSessionGroupHandle.empty())
{
- setState(stateNoChannel);
-
// Start looped recording (needed for "panic button" anti-griefing tool)
recordingLoopStart();
-
- // Initial kick-off of channel lookup logic
- parcelChanged();
+ setState(stateNoChannel);
}
break;
+
+ //MARK: stateRetrievingParcelVoiceInfo
+ case stateRetrievingParcelVoiceInfo:
+ // wait until parcel voice info is received.
+ if(mSessionTerminateRequested || !mVoiceEnabled)
+ {
+ // if a terminate request has been received,
+ // bail and go to the stateSessionTerminated
+ // state. If the cap request is still pending,
+ // the responder will check to see if we've moved
+ // to a new session and won't change any state.
+ setState(stateSessionTerminated);
+ }
+ break;
+
//MARK: stateNoChannel
case stateNoChannel:
-
LL_DEBUGS("Voice") << "State No Channel" << LL_ENDL;
mSpatialJoiningNum = 0;
// Do this here as well as inside sendPositionalUpdate().
@@ -1432,6 +1406,16 @@ void LLVivoxVoiceClient::stateMachine()
{
setState(stateCaptureBufferPaused);
}
+ else if(checkParcelChanged() || (mNextAudioSession == NULL))
+ {
+ // the parcel is changed, or we have no pending audio sessions,
+ // so try to request the parcel voice info
+ // if we have the cap, we move to the appropriate state
+ if(requestParcelVoiceInfo())
+ {
+ setState(stateRetrievingParcelVoiceInfo);
+ }
+ }
else if(sessionNeedsRelog(mNextAudioSession))
{
requestRelog();
@@ -1466,32 +1450,28 @@ void LLVivoxVoiceClient::stateMachine()
notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_JOINING);
setState(stateJoiningSession);
}
- else if(!mSpatialSessionURI.empty())
- {
- // If we're not headed elsewhere and have a spatial URI, return to spatial.
- switchChannel(mSpatialSessionURI, true, false, false, mSpatialSessionCredentials);
- }
break;
-
+
//MARK: stateJoiningSession
case stateJoiningSession: // waiting for session handle
-
- // If this is true we have problem with connection to voice server (EXT-4313).
- // See descriptions of mSpatialJoiningNum and MAX_NORMAL_JOINING_SPATIAL_NUM.
- if(mSpatialJoiningNum == MAX_NORMAL_JOINING_SPATIAL_NUM)
+
+ // If this is true we have problem with connection to voice server (EXT-4313).
+ // See descriptions of mSpatialJoiningNum and MAX_NORMAL_JOINING_SPATIAL_NUM.
+ if(mSpatialJoiningNum == MAX_NORMAL_JOINING_SPATIAL_NUM)
{
- // Notify observers to let them know there is problem with voice
- notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
- llwarns << "There seems to be problem with connection to voice server. Disabling voice chat abilities." << llendl;
+ // Notify observers to let them know there is problem with voice
+ notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
+ llwarns << "There seems to be problem with connection to voice server. Disabling voice chat abilities." << llendl;
}
-
- // Increase mSpatialJoiningNum only for spatial sessions- it's normal to reach this case for
- // example for p2p many times while waiting for response, so it can't be used to detect errors
- if(mAudioSession && mAudioSession->mIsSpatial)
+
+ // Increase mSpatialJoiningNum only for spatial sessions- it's normal to reach this case for
+ // example for p2p many times while waiting for response, so it can't be used to detect errors
+ if(mAudioSession && mAudioSession->mIsSpatial)
{
- mSpatialJoiningNum++;
+
+ mSpatialJoiningNum++;
}
-
+
// joinedAudioSession() will transition from here to stateSessionJoined.
if(!mVoiceEnabled)
{
@@ -1511,12 +1491,13 @@ void LLVivoxVoiceClient::stateMachine()
}
}
}
- break;
-
+ break;
+
//MARK: stateSessionJoined
case stateSessionJoined: // session handle received
- mSpatialJoiningNum = 0;
+
+ mSpatialJoiningNum = 0;
// It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4
// before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck.
// For now, the SessionGroup.AddSession response handler sets mSessionHandle and the SessionStateChangeEvent handler transitions to stateSessionJoined.
@@ -1553,7 +1534,7 @@ void LLVivoxVoiceClient::stateMachine()
sessionMediaDisconnectSendMessage(mAudioSession);
setState(stateSessionTerminated);
}
- }
+ }
break;
//MARK: stateRunning
@@ -1565,6 +1546,7 @@ void LLVivoxVoiceClient::stateMachine()
}
else
{
+
if(!inSpatialChannel())
{
// When in a non-spatial channel, never send positional updates.
@@ -1572,8 +1554,22 @@ void LLVivoxVoiceClient::stateMachine()
}
else
{
+ if(checkParcelChanged())
+ {
+ // if the parcel has changed, attempted to request the
+ // cap for the parcel voice info. If we can't request it
+ // then we don't have the cap URL so we do nothing and will
+ // recheck next time around
+ if(requestParcelVoiceInfo())
+ {
+ // we did get the cap, and we made the request,
+ // so go wait for the response.
+ setState(stateRetrievingParcelVoiceInfo);
+ }
+ }
// Do the calculation that enforces the listener<->speaker tether (and also updates the real camera position)
enforceTether();
+
}
// Do notifications for expiring Voice Fonts.
@@ -3840,7 +3836,7 @@ void LLVivoxVoiceClient::participantUpdatedEvent(
// also initialize voice moderate_mode depend on Agent's participant. See EXT-6937.
// *TODO: remove once a way to request the current voice channel moderation mode is implemented.
- if (gAgentID == participant->mAvatarID)
+ if (gAgent.getID() == participant->mAvatarID)
{
speaker_manager->initVoiceModerateMode();
}
@@ -4073,7 +4069,7 @@ void LLVivoxVoiceClient::messageEvent(
}
LL_DEBUGS("Voice") << "adding message, name " << session->mName << " session " << session->mIMSessionID << ", target " << session->mCallerID << LL_ENDL;
- gIMMgr->addMessage(session->mIMSessionID,
+ LLIMMgr::getInstance()->addMessage(session->mIMSessionID,
session->mCallerID,
session->mName.c_str(),
message.c_str(),
@@ -4447,24 +4443,91 @@ LLVivoxVoiceClient::participantState* LLVivoxVoiceClient::findParticipantByID(co
}
-void LLVivoxVoiceClient::parcelChanged()
+
+// Check for parcel boundary crossing
+bool LLVivoxVoiceClient::checkParcelChanged(bool update)
{
- if(getState() >= stateNoChannel)
+ LLViewerRegion *region = gAgent.getRegion();
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ if(region && parcel)
{
- // If the user is logged in, start a channel lookup.
- LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
+ S32 parcelLocalID = parcel->getLocalID();
+ std::string regionName = region->getName();
+
+ // LL_DEBUGS("Voice") << "Region name = \"" << regionName << "\", parcel local ID = " << parcelLocalID << ", cap URI = \"" << capURI << "\"" << LL_ENDL;
+
+ // The region name starts out empty and gets filled in later.
+ // Also, the cap gets filled in a short time after the region cross, but a little too late for our purposes.
+ // If either is empty, wait for the next time around.
+ if(!regionName.empty())
+ {
+ if((parcelLocalID != mCurrentParcelLocalID) || (regionName != mCurrentRegionName))
+ {
+ // We have changed parcels. Initiate a parcel channel lookup.
+ if (update)
+ {
+ mCurrentParcelLocalID = parcelLocalID;
+ mCurrentRegionName = regionName;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool LLVivoxVoiceClient::parcelVoiceInfoReceived(state requesting_state)
+{
+ // pop back to the state we were in when the parcel changed and we managed to
+ // do the request.
+ if(getState() == stateRetrievingParcelVoiceInfo)
+ {
+ setState(requesting_state);
+ return true;
+ }
+ else
+ {
+ // we've dropped out of stateRetrievingParcelVoiceInfo
+ // before we received the cap result, due to a terminate
+ // or transition to a non-voice channel. Don't switch channels.
+ return false;
+ }
+}
+
- std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest");
+bool LLVivoxVoiceClient::requestParcelVoiceInfo()
+{
+ LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
+
+ // grab the cap for parcel voice info from the region.
+ LLViewerRegion * region = gAgent.getRegion();
+ if (region == NULL)
+ {
+ return false;
+ }
+ // grab the cap.
+ std::string url = gAgent.getRegion()->getCapability("ParcelVoiceInfoRequest");
+ if (!url.empty())
+ {
+ // if we've already retrieved the cap from the region, go ahead and make the request,
+ // and return true so we can go into the state that waits for the response.
+ checkParcelChanged(true);
LLSD data;
+ LL_DEBUGS("Voice") << "sending ParcelVoiceInfoRequest (" << mCurrentRegionName << ", " << mCurrentParcelLocalID << ")" << LL_ENDL;
+
LLHTTPClient::post(
- url,
- data,
- new LLVivoxVoiceClientCapResponder);
+ url,
+ data,
+ new LLVivoxVoiceClientCapResponder(getState()));
+ return true;
}
- else
+ else
{
- // The transition to stateNoChannel needs to kick this off again.
- LL_INFOS("Voice") << "not logged in yet, deferring" << LL_ENDL;
+
+ // we don't have the cap yet, so return false so the caller can try again later.
+ LL_DEBUGS("Voice") << "ParcelVoiceInfoRequest cap not yet available, deferring" << LL_ENDL;
+ return false;
}
}
@@ -4488,6 +4551,7 @@ void LLVivoxVoiceClient::switchChannel(
case stateJoinSessionFailed:
case stateJoinSessionFailedWaiting:
case stateNoChannel:
+ case stateRetrievingParcelVoiceInfo:
// Always switch to the new URI from these states.
needsSwitch = true;
break;
@@ -4560,13 +4624,10 @@ void LLVivoxVoiceClient::switchChannel(
mNextAudioSession->mIsP2P = is_p2p;
}
- if(getState() <= stateNoChannel)
- {
- // We're already set up to join a channel, just needed to fill in the session URI
- }
- else
+ if(getState() >= stateRetrievingParcelVoiceInfo)
{
- // State machine will come around and rejoin if uri/handle is not empty.
+ // If we're already in a channel, or if we're joining one, terminate
+ // so we can rejoin with the new session data.
sessionTerminate();
}
}
@@ -6267,13 +6328,13 @@ void LLVivoxVoiceClient::avatarNameResolved(const LLUUID &id, const std::string
{
session->mTextInvitePending = false;
- // We don't need to call gIMMgr->addP2PSession() here. The first incoming message will create the panel.
+ // We don't need to call LLIMMgr::getInstance()->addP2PSession() here. The first incoming message will create the panel.
}
if(session->mVoiceInvitePending)
{
session->mVoiceInvitePending = false;
- gIMMgr->inviteToSession(
+ LLIMMgr::getInstance()->inviteToSession(
session->mIMSessionID,
session->mName,
session->mCallerID,
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 471545de56..1142a1a49c 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -380,7 +380,8 @@ protected:
stateVoiceFontsWait, // Awaiting the list of voice fonts
stateVoiceFontsReceived, // List of voice fonts received
stateCreatingSessionGroup, // Creating the main session group
- stateNoChannel, //
+ stateNoChannel, // Need to join a channel
+ stateRetrievingParcelVoiceInfo, // waiting for parcel voice info request to return with spatial credentials
stateJoiningSession, // waiting for session handle
stateSessionJoined, // session handle received
stateRunning, // in session, steady state
@@ -620,6 +621,8 @@ protected:
void sessionMediaDisconnectSendMessage(sessionState *session);
void sessionTextDisconnectSendMessage(sessionState *session);
+
+
// Pokes the state machine to leave the audio session next time around.
void sessionTerminate();
@@ -629,6 +632,12 @@ protected:
// Does the actual work to get out of the audio session
void leaveAudioSession();
+ // notifies the voice client that we've received parcel voice info
+ bool parcelVoiceInfoReceived(state requesting_state);
+
+ friend class LLVivoxVoiceClientCapResponder;
+
+
void lookupName(const LLUUID &id);
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
void avatarNameResolved(const LLUUID &id, const std::string &name);
@@ -733,9 +742,11 @@ private:
bool mCaptureDeviceDirty;
bool mRenderDeviceDirty;
+
+ bool checkParcelChanged(bool update = false);
// This should be called when the code detects we have changed parcels.
// It initiates the call to the server that gets the parcel channel.
- void parcelChanged();
+ bool requestParcelVoiceInfo();
void switchChannel(std::string uri = std::string(), bool spatial = true, bool no_reconnect = false, bool is_p2p = false, std::string hash = "");
void joinSession(sessionState *session);
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 6f354b78b1..a4b0910c92 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -324,10 +324,18 @@ void LLVOPartGroup::getGeometry(S32 idx,
LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis();
-
+
+ //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
+ // this works because there is actually a 4th float stored after the vertex position which is used as a texture index
+ // also, somebody please VECTORIZE THIS
+
+ verticesp->mV[3] = 0.f;
*verticesp++ = part_pos_agent + up - right;
+ verticesp->mV[3] = 0.f;
*verticesp++ = part_pos_agent - up - right;
+ verticesp->mV[3] = 0.f;
*verticesp++ = part_pos_agent + up + right;
+ verticesp->mV[3] = 0.f;
*verticesp++ = part_pos_agent - up + right;
*colorsp++ = part.mColor;
@@ -360,7 +368,7 @@ U32 LLVOPartGroup::getPartitionType() const
}
LLParticlePartition::LLParticlePartition()
-: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_STREAM_DRAW_ARB)
+: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)
{
mRenderPass = LLRenderPass::PASS_ALPHA;
mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
@@ -418,6 +426,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co
mFaceList.push_back(facep);
vertex_count += facep->getGeomCount();
index_count += facep->getIndicesCount();
+ llassert(facep->getIndicesCount() < 65536);
}
obj->mDepth /= count;
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 6396bc042d..66ba6249d3 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -370,7 +370,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
mAtmHeight = ATM_HEIGHT;
mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
- mSunDefaultPosition = LLVector3(LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error));
+ mSunDefaultPosition = LLVector3(LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error));
if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition"))
{
initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0));
@@ -646,24 +646,24 @@ void LLVOSky::initAtmospherics(void)
bool error;
// uniform parameters for convenience
- dome_radius = LLWLParamManager::instance()->getDomeRadius();
- dome_offset_ratio = LLWLParamManager::instance()->getDomeOffset();
- sunlight_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("sunlight_color", error));
- ambient = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("ambient", error));
- //lightnorm = LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error);
- gamma = LLWLParamManager::instance()->mCurParams.getVector("gamma", error)[0];
- blue_density = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_density", error));
- blue_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_horizon", error));
- haze_density = LLWLParamManager::instance()->mCurParams.getVector("haze_density", error)[0];
- haze_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("haze_horizon", error));
- density_multiplier = LLWLParamManager::instance()->mCurParams.getVector("density_multiplier", error)[0];
- max_y = LLWLParamManager::instance()->mCurParams.getVector("max_y", error)[0];
- glow = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("glow", error));
- cloud_shadow = LLWLParamManager::instance()->mCurParams.getVector("cloud_shadow", error)[0];
- cloud_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_color", error));
- cloud_scale = LLWLParamManager::instance()->mCurParams.getVector("cloud_scale", error)[0];
- cloud_pos_density1 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density1", error));
- cloud_pos_density2 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density2", error));
+ dome_radius = LLWLParamManager::getInstance()->getDomeRadius();
+ dome_offset_ratio = LLWLParamManager::getInstance()->getDomeOffset();
+ sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error));
+ ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error));
+ //lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error);
+ gamma = LLWLParamManager::getInstance()->mCurParams.getVector("gamma", error)[0];
+ blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error));
+ blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error));
+ haze_density = LLWLParamManager::getInstance()->mCurParams.getVector("haze_density", error)[0];
+ haze_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("haze_horizon", error));
+ density_multiplier = LLWLParamManager::getInstance()->mCurParams.getVector("density_multiplier", error)[0];
+ max_y = LLWLParamManager::getInstance()->mCurParams.getVector("max_y", error)[0];
+ glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error));
+ cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_shadow", error)[0];
+ cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error));
+ cloud_scale = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_scale", error)[0];
+ cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error));
+ cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error));
// light norm is different. We need the sun's direction, not the light direction
// which could be from the moon. And we need to clamp it
@@ -1033,7 +1033,7 @@ void LLVOSky::calcAtmospherics(void)
// Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
// between sunlight and point lights in windlight to normalize point lights.
F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
- LLWLParamManager::instance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
+ LLWLParamManager::getInstance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
mSunDiffuse = vary_SunlightColor;
mSunAmbient = vary_AmbientColor;
@@ -1483,6 +1483,8 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
facep->setVertexBuffer(buff);
}
+ llassert(facep->getVertexBuffer()->getNumIndices() == 6);
+
index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
if (-1 == index_offset)
@@ -2127,7 +2129,7 @@ void LLVOSky::updateFog(const F32 distance)
F32 depth = water_height - camera_height;
// get the water param manager variables
- float water_fog_density = LLWaterParamManager::instance()->getFogDensity();
+ float water_fog_density = LLWaterParamManager::getInstance()->getFogDensity();
LLColor4 water_fog_color = LLDrawPoolWater::sWaterFogColor.mV;
// adjust the color based on depth. We're doing linear approximations
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index dbcd4f50ca..510525259f 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -375,6 +375,8 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
S32 num_vertices, num_indices;
U32 index;
+ llassert(mLastStride > 0);
+
render_stride = mLastStride;
patch_size = mPatchp->getSurface()->getGridsPerPatchEdge();
S32 vert_size = patch_size / render_stride;
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 8946d4e0b6..3c7fe708e6 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -980,11 +980,6 @@ void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
for (S32 i = 0; i < index_count; i++)
{
U16 index = index_offset + i;
- if (idx[index] >= vert_start + vert_count ||
- idx[index] < vert_start)
- {
- llerrs << "WTF?" << llendl;
- }
*indices++ = idx[index]-vert_start+cur_idx;
}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e9a8c9b80a..e6da8eb89d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -73,6 +73,7 @@
#include "llagent.h"
#include "llviewermediafocus.h"
#include "lldatapacker.h"
+#include "llviewershadermgr.h"
#include "llvoavatar.h"
#include "llvocache.h"
@@ -1095,8 +1096,6 @@ void LLVOVolume::updateSculptTexture()
}
-
-
void LLVOVolume::notifyMeshLoaded()
{
mSculptChanged = TRUE;
@@ -1222,7 +1221,7 @@ BOOL LLVOVolume::calcLOD()
}
//hold onto unmodified distance for debugging
- F32 debug_distance = distance;
+ //F32 debug_distance = distance;
distance *= sDistanceFactor;
@@ -1245,7 +1244,9 @@ BOOL LLVOVolume::calcLOD()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO))
{
- setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
+ //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
+
+ setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
}
if (cur_detail != mLOD)
@@ -1274,6 +1275,15 @@ BOOL LLVOVolume::updateLOD()
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
mLODChanged = TRUE;
}
+ else
+ {
+ F32 new_radius = getBinRadius();
+ F32 old_radius = mDrawable->getBinRadius();
+ if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f)
+ {
+ gPipeline.markPartitionMove(mDrawable);
+ }
+ }
lod_changed = lod_changed || LLViewerObject::updateLOD();
@@ -3086,16 +3096,28 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes)
{
+ F32 radius = getScale().length();
+
if (isMesh())
{
LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID());
- F32 radius = getScale().length();
-
return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD);
}
-
- return 0.f;
+ else
+ {
+ LLVolume* volume = getVolume();
+ S32 counts[4];
+ LLVolume::getLoDTriangleCounts(volume->getParams(), counts);
+
+ LLSD header;
+ header["lowest_lod"]["size"] = counts[0] * 10;
+ header["low_lod"]["size"] = counts[1] * 10;
+ header["medium_lod"]["size"] = counts[2] * 10;
+ header["high_lod"]["size"] = counts[3] * 10;
+
+ return LLMeshRepository::getStreamingCost(header, radius);
+ }
}
U32 LLVOVolume::getTriangleCount()
@@ -3187,6 +3209,10 @@ F32 LLVOVolume::getBinRadius()
F32 scale = 1.f;
+ S32 size_factor = llmax(gSavedSettings.getS32("OctreeStaticObjectSizeFactor"), 1);
+ S32 attachment_size_factor = llmax(gSavedSettings.getS32("OctreeAttachmentSizeFactor"), 1);
+ LLVector3 distance_factor = gSavedSettings.getVector3("OctreeDistanceFactor");
+ LLVector3 alpha_distance_factor = gSavedSettings.getVector3("OctreeAlphaDistanceFactor");
const LLVector4a* ext = mDrawable->getSpatialExtents();
BOOL shrink_wrap = mDrawable->isAnimating();
@@ -3216,6 +3242,8 @@ F32 LLVOVolume::getBinRadius()
radius = llmin(bounds.mV[1], bounds.mV[2]);
radius = llmin(radius, bounds.mV[0]);
radius *= 0.5f;
+ radius *= 1.f+mDrawable->mDistanceWRTCamera*alpha_distance_factor[1];
+ radius += mDrawable->mDistanceWRTCamera*alpha_distance_factor[0];
}
else if (shrink_wrap)
{
@@ -3226,24 +3254,19 @@ F32 LLVOVolume::getBinRadius()
}
else if (mDrawable->isStatic())
{
- /*if (mDrawable->getRadius() < 2.0f)
- {
- radius = 16.f;
- }
- else
- {
- radius = llmax(mDrawable->getRadius(), 32.f);
- }*/
-
- radius = (((S32) mDrawable->getRadius())/2+1)*8;
+ radius = llmax((S32) mDrawable->getRadius(), 1)*size_factor;
+ radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
+ radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
}
else if (mDrawable->getVObj()->isAttachment())
{
- radius = (((S32) (mDrawable->getRadius()*4)+1))*2;
+ radius = llmax((S32) mDrawable->getRadius(),1)*attachment_size_factor;
}
else
{
- radius = 8.f;
+ radius = mDrawable->getRadius();
+ radius *= 1.f + mDrawable->mDistanceWRTCamera * distance_factor[1];
+ radius += mDrawable->mDistanceWRTCamera * distance_factor[0];
}
return llclamp(radius*scale, 0.5f, 256.f);
@@ -3342,7 +3365,8 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
{
if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf())
{
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
+ updateRiggedVolume();
+ genBBoxes(FALSE);
volume = mRiggedVolume;
transform = false;
}
@@ -3521,7 +3545,7 @@ void LLVOVolume::updateRiggedVolume()
LLVolume* volume = getVolume();
- const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID());
+ const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID(), this);
if (!skin)
{
@@ -3712,6 +3736,21 @@ LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
mSlopRatio = 0.25f;
}
+bool can_batch_texture(LLFace* facep)
+{
+ if (facep->getTextureEntry()->getBumpmap())
+ { //bump maps aren't worked into texture batching yet
+ return false;
+ }
+
+ if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
+ { //texture animation breaks batches
+ return false;
+ }
+
+ return true;
+}
+
void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -3762,12 +3801,36 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LLViewerTexture* tex = facep->getTexture();
+ U8 index = facep->getTextureIndex();
+
+ bool batchable = false;
+
+ if (index < 255 && idx >= 0)
+ {
+ if (index < draw_vec[idx]->mTextureList.size())
+ {
+ if (draw_vec[idx]->mTextureList[index].isNull())
+ {
+ batchable = true;
+ draw_vec[idx]->mTextureList[index] = tex;
+ }
+ else if (draw_vec[idx]->mTextureList[index] == tex)
+ { //this face's texture index can be used with this batch
+ batchable = true;
+ }
+ }
+ else
+ { //texture list can be expanded to fit this texture index
+ batchable = true;
+ }
+ }
+
U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255);
if (idx >= 0 &&
draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() &&
draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
- (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) &&
+ (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) &&
#if LL_DARWIN
draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
@@ -3781,6 +3844,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mCount += facep->getIndicesCount();
draw_vec[idx]->mEnd += facep->getGeomCount();
draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
+
+ if (index >= draw_vec[idx]->mTextureList.size())
+ {
+ draw_vec[idx]->mTextureList.resize(index+1);
+ draw_vec[idx]->mTextureList[index] = tex;
+ }
draw_vec[idx]->validate();
update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]);
update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]);
@@ -3811,6 +3880,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_info->mDrawMode = LLRender::TRIANGLE_STRIP;
}
+ if (index < 255)
+ { //initialize texture list for texture batching
+ draw_info->mTextureList.resize(index+1);
+ draw_info->mTextureList[index] = tex;
+ }
draw_info->validate();
}
}
@@ -3910,7 +3984,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLVOVolume* vobj = drawablep->getVOVolume();
- if (vobj->getVolume() && vobj->getVolume()->isTetrahedron())
+ if (vobj->getVolume() && vobj->getVolume()->isTetrahedron() || (vobj->isMesh() && !gMeshRepo.meshRezEnabled()))
{
continue;
}
@@ -3923,7 +3997,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
bool rigged = vobj->isAttachment() &&
vobj->isMesh() &&
- gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID());
+ gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj);
bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic();
@@ -3965,7 +4039,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if ( pAvatarVO )
{
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
- const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId );
+ const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
if ( pSkinData )
{
@@ -4233,15 +4307,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
- if (LLPipeline::sRenderDeferred)
+ bool batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+
+ if (batch_textures)
{
bump_mask |= LLVertexBuffer::MAP_BINORMAL;
+ genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE);
+ genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE);
+ genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, TRUE);
+ genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE);
+ }
+ else
+ {
+ genDrawInfo(group, simple_mask, simple_faces);
+ genDrawInfo(group, fullbright_mask, fullbright_faces);
+ genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE);
+ genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
}
- genDrawInfo(group, simple_mask, simple_faces);
- genDrawInfo(group, bump_mask, bump_faces);
- genDrawInfo(group, fullbright_mask, fullbright_faces);
- genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
if (!LLPipeline::sDelayVBUpdate)
{
@@ -4297,11 +4380,6 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
face->getGeometryVolume(*volume, face->getTEOffset(),
vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
}
-
- if (!face)
- {
- llerrs << "WTF?" << llendl;
- }
}
drawablep->clearState(LLDrawable::REBUILD_ALL);
@@ -4356,13 +4434,37 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO);
}
- if (group && group->isState(LLSpatialGroup::NEW_DRAWINFO))
+ llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO));
+}
+
+struct CompareBatchBreakerModified
+{
+ bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
{
- llerrs << "WTF?" << llendl;
+ const LLTextureEntry* lte = lhs->getTextureEntry();
+ const LLTextureEntry* rte = rhs->getTextureEntry();
+
+ if (lte->getBumpmap() != rte->getBumpmap())
+ {
+ return lte->getBumpmap() < rte->getBumpmap();
+ }
+ else if (lte->getFullbright() != rte->getFullbright())
+ {
+ return lte->getFullbright() < rte->getFullbright();
+ }
+ else if (lte->getGlow() != rte->getGlow())
+ {
+ return lte->getGlow() < rte->getGlow();
+ }
+ else
+ {
+ return lhs->getTexture() < rhs->getTexture();
+ }
+
}
-}
+};
-void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort)
+void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures)
{
//calculate maximum number of vertices to store in a single buffer
U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask);
@@ -4371,7 +4473,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
if (!distance_sort)
{
//sort faces by things that break batches
- std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker());
+ std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified());
}
else
{
@@ -4391,6 +4493,21 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
buffer_index = -1;
}
+ S32 texture_index_channels = gGLManager.mNumTextureImageUnits-1; //always reserve one for shiny for now just for simplicity
+
+ if (gGLManager.mGLVersion < 3.1f)
+ {
+ texture_index_channels = 1;
+ }
+
+ if (LLPipeline::sRenderDeferred && distance_sort)
+ {
+ texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;
+ }
+
+ texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex"));
+
+
while (face_iter != faces.end())
{
//pull off next face
@@ -4421,24 +4538,101 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
std::vector<LLFace*>::iterator i = face_iter;
++i;
- while (i != faces.end() &&
- (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))
+ std::vector<LLViewerTexture*> texture_list;
+
+ if (batch_textures)
{
- facep = *i;
-
- if (geom_count + facep->getGeomCount() > max_vertices)
- { //cut batches on geom count too big
- break;
+ U8 cur_tex = 0;
+ facep->setTextureIndex(cur_tex);
+ texture_list.push_back(tex);
+
+ //if (can_batch_texture(facep))
+ {
+ while (i != faces.end())
+ {
+ facep = *i;
+ if (facep->getTexture() != tex)
+ {
+ if (distance_sort)
+ { //textures might be out of order, see if texture exists in current batch
+ bool found = false;
+ for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx)
+ {
+ if (facep->getTexture() == texture_list[tex_idx])
+ {
+ cur_tex = tex_idx;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ cur_tex = texture_list.size();
+ }
+ }
+ else
+ {
+ cur_tex++;
+ }
+
+ if (!can_batch_texture(facep))
+ { //face is bump mapped or has an animated texture matrix -- can't
+ //batch more than 1 texture at a time
+ break;
+ }
+
+ if (cur_tex >= texture_index_channels)
+ { //cut batches when index channels are depleted
+ break;
+ }
+
+ tex = facep->getTexture();
+
+ texture_list.push_back(tex);
+ }
+
+ if (geom_count + facep->getGeomCount() > max_vertices)
+ { //cut batches on geom count too big
+ break;
+ }
+
+ ++i;
+ index_count += facep->getIndicesCount();
+ geom_count += facep->getGeomCount();
+
+ facep->setTextureIndex(cur_tex);
+ }
}
- ++i;
- index_count += facep->getIndicesCount();
- geom_count += facep->getGeomCount();
+ tex = texture_list[0];
+ }
+ else
+ {
+ while (i != faces.end() &&
+ (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))
+ {
+ facep = *i;
+
+
+ //face has no texture index
+ facep->mDrawInfo = NULL;
+ facep->setTextureIndex(255);
+
+ if (geom_count + facep->getGeomCount() > max_vertices)
+ { //cut batches on geom count too big
+ break;
+ }
+
+ ++i;
+ index_count += facep->getIndicesCount();
+ geom_count += facep->getGeomCount();
+ }
}
//create/delete/resize vertex buffer if needed
LLVertexBuffer* buffer = NULL;
- LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex);
+ LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter);
if (found_iter != group->mBufferMap[mask].end())
{
@@ -4469,7 +4663,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
}
- buffer_map[mask][tex].push_back(buffer);
+ buffer_map[mask][*face_iter].push_back(buffer);
//add face geometry
@@ -4483,6 +4677,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
facep->setGeomIndex(index_offset);
facep->setVertexBuffer(buffer);
+ if (batch_textures && facep->getTextureIndex() == 255)
+ {
+ llerrs << "Invalid texture index." << llendl;
+ }
+
{
//for debugging, set last time face was updated vs moved
facep->updateRebuildFlags();
@@ -4495,12 +4694,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
U32 te_idx = facep->getTEOffset();
- if (facep->getGeometryVolume(*volume, te_idx,
- vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
- {
- buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(),
- facep->getIndicesStart(), facep->getIndicesCount());
- }
+ facep->getGeometryVolume(*volume, te_idx,
+ vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset);
}
}
@@ -4681,7 +4876,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
{
vertex_count += facep->getGeomCount();
index_count += facep->getIndicesCount();
-
+ llassert(facep->getIndicesCount() < 65536);
//remember face (for sorting)
mFaceList.push_back(facep);
}
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 51664cb31d..7b1c725483 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -568,7 +568,7 @@ void LLVOWLSky::buildFanBuffer(LLStrider<LLVector3> & vertices,
LLStrider<LLVector2> & texCoords,
LLStrider<U16> & indices)
{
- const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius();
+ const F32 RADIUS = LLWLParamManager::getInstance()->getDomeRadius();
U32 i, num_slices;
F32 phi0, theta, x0, y0, z0;
@@ -629,7 +629,7 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
LLStrider<LLVector2> & texCoords,
LLStrider<U16> & indices)
{
- const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius();
+ const F32 RADIUS = LLWLParamManager::getInstance()->getDomeRadius();
U32 i, j, num_slices, num_stacks;
F32 phi0, theta, x0, y0, z0;
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 67bb965f99..1a98d4c6c2 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -54,12 +54,9 @@
#include "llwlparammanager.h"
#include "llwaterparamset.h"
-#include "llfloaterwater.h"
#include "curl/curl.h"
-LLWaterParamManager * LLWaterParamManager::sInstance = NULL;
-
LLWaterParamManager::LLWaterParamManager() :
mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"),
mFogDensity(4, "waterFogDensity", 2),
@@ -73,8 +70,6 @@ LLWaterParamManager::LLWaterParamManager() :
mWave1Dir(.5f, .5f, "wave1Dir"),
mWave2Dir(.5f, .5f, "wave2Dir"),
mDensitySliderValue(1.0f),
- mPrevFogDensity(16.0f), // 2^4
- mPrevFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f),
mWaterFogKS(1.0f)
{
}
@@ -83,131 +78,73 @@ LLWaterParamManager::~LLWaterParamManager()
{
}
-void LLWaterParamManager::loadAllPresets(const std::string& file_name)
+void LLWaterParamManager::loadAllPresets()
{
- std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));
- LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
-
- bool found = true;
- LLDirIterator app_settings_iter(path_name, "*.xml");
- while(found)
- {
- std::string name;
- found = app_settings_iter.next(name);
- if(found)
- {
-
- name=name.erase(name.length()-4);
+ // First, load system (coming out of the box) water presets.
+ loadPresetsFromDir(getSysDir());
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_unescape(name.c_str(), name.size());
- std::string unescaped_name(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
-
- LL_DEBUGS2("AppInit", "Shaders") << "name: " << name << LL_ENDL;
- loadPreset(unescaped_name,FALSE);
- }
- }
+ // Then load user presets. Note that user day presets will modify any system ones already loaded.
+ loadPresetsFromDir(getUserDir());
+}
- // And repeat for user presets, note the user presets will modify any system presets already loaded
+void LLWaterParamManager::loadPresetsFromDir(const std::string& dir)
+{
+ LL_INFOS2("AppInit", "Shaders") << "Loading water presets from " << dir << LL_ENDL;
- std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
- LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
-
- found = true;
- LLDirIterator user_settings_iter(path_name2, "*.xml");
- while(found)
+ LLDirIterator dir_iter(dir, "*.xml");
+ while (1)
{
- std::string name;
- found = user_settings_iter.next(name);
- if(found)
+ std::string file;
+ if (!dir_iter.next(file))
{
- name=name.erase(name.length()-4);
-
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_unescape(name.c_str(), name.size());
- std::string unescaped_name(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
+ break; // no more files
+ }
- LL_DEBUGS2("AppInit", "Shaders") << "name: " << name << LL_ENDL;
- loadPreset(unescaped_name,FALSE);
+ std::string path = dir + file;
+ if (!loadPreset(path))
+ {
+ llwarns << "Error loading water preset from " << path << llendl;
}
}
-
}
-void LLWaterParamManager::loadPreset(const std::string & name,bool propagate)
+bool LLWaterParamManager::loadPreset(const std::string& path)
{
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_escape(name.c_str(), name.size());
- std::string escaped_filename(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
-
- escaped_filename += ".xml";
+ llifstream xml_file;
+ std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
- std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
- LL_DEBUGS2("AppInit", "Shaders") << "Loading water settings from " << pathName << LL_ENDL;
-
- llifstream presetsXML;
- presetsXML.open(pathName.c_str());
-
- // That failed, try loading from the users area instead.
- if(!presetsXML)
+ xml_file.open(path.c_str());
+ if (!xml_file)
{
- pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", escaped_filename);
- LL_DEBUGS2("AppInit", "Shaders") << "Loading User water setting from " << pathName << LL_ENDL;
- presetsXML.clear();
- presetsXML.open(pathName.c_str());
+ return false;
}
- if (presetsXML)
- {
- LLSD paramsData(LLSD::emptyMap());
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading water " << name << LL_ENDL;
- LLPointer<LLSDParser> parser = new LLSDXMLParser();
+ LLSD params_data;
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+ parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
+ xml_file.close();
- parser->parse(presetsXML, paramsData, LLSDSerialize::SIZE_UNLIMITED);
-
- std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
- if(mIt == mParamList.end())
- {
- addParamSet(name, paramsData);
- }
- else
- {
- setParamSet(name, paramsData);
- }
- presetsXML.close();
- }
- else
+ if (hasParamSet(name))
{
- llwarns << "Can't find " << name << llendl;
- return;
+ setParamSet(name, params_data);
}
-
- if(propagate)
+ else
{
- getParamSet(name, mCurParams);
- propagateParameters();
+ addParamSet(name, params_data);
}
-}
+
+ return true;
+}
void LLWaterParamManager::savePreset(const std::string & name)
{
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_escape(name.c_str(), name.size());
- std::string escaped_filename(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
-
- escaped_filename += ".xml";
+ llassert(!name.empty());
// make an empty llsd
LLSD paramsData(LLSD::emptyMap());
- std::string pathName(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", escaped_filename));
+ std::string pathName(getUserDir() + LLURI::escape(name) + ".xml");
// fill it with LLSD windlight params
paramsData = mParamList[name].getAll();
@@ -221,7 +158,6 @@ void LLWaterParamManager::savePreset(const std::string & name)
propagateParameters();
}
-
void LLWaterParamManager::propagateParameters(void)
{
// bind the variables only if we're using shaders
@@ -251,7 +187,7 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
{
if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
{
- shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::instance()->getRotatedLightDir().mV);
+ shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::getInstance()->getRotatedLightDir().mV);
shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV);
shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);
@@ -261,36 +197,33 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
}
}
-static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params");
-
-void LLWaterParamManager::update(LLViewerCamera * cam)
+void LLWaterParamManager::applyParams(const LLSD& params, bool interpolate)
{
- LLFastTimer ftm(FTM_UPDATE_WLPARAM);
-
- // update the shaders and the menu
- propagateParameters();
-
- // If water fog color has been changed, save it.
- if (mPrevFogColor != mFogColor)
+ if (params.size() == 0)
{
- gSavedSettings.setColor4("WaterFogColor", mFogColor);
- mPrevFogColor = mFogColor;
+ llwarns << "Undefined water params" << llendl;
+ return;
}
- // If water fog density has been changed, save it.
- if (mPrevFogDensity != mFogDensity)
+ if (interpolate)
{
- gSavedSettings.setF32("WaterFogDensity", mFogDensity);
- mPrevFogDensity = mFogDensity;
+ LLWLParamManager::getInstance()->mAnimator.startInterpolation(params);
}
-
- // sync menus if they exist
- LLFloaterWater* waterfloater = LLFloaterReg::findTypedInstance<LLFloaterWater>("env_water");
- if(waterfloater)
+ else
{
- waterfloater->syncMenu();
+ mCurParams.setAll(params);
}
+}
+static LLFastTimer::DeclareTimer FTM_UPDATE_WATERPARAM("Update Water Params");
+
+void LLWaterParamManager::update(LLViewerCamera * cam)
+{
+ LLFastTimer ftm(FTM_UPDATE_WATERPARAM);
+
+ // update the shaders and the menu
+ propagateParameters();
+
// only do this if we're dealing with shaders
if(gPipeline.canUseVertexShaders())
{
@@ -339,26 +272,14 @@ void LLWaterParamManager::update(LLViewerCamera * cam)
}
}
-// static
-void LLWaterParamManager::initClass(void)
-{
- instance();
-}
-
-// static
-void LLWaterParamManager::cleanupClass(void)
-{
- delete sInstance;
- sInstance = NULL;
-}
-
bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet& param)
{
// add a new one if not one there already
- std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
+ preset_map_t::iterator mIt = mParamList.find(name);
if(mIt == mParamList.end())
{
mParamList[name] = param;
+ mPresetListChangeSignal();
return true;
}
@@ -367,23 +288,15 @@ bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet&
BOOL LLWaterParamManager::addParamSet(const std::string& name, LLSD const & param)
{
- // add a new one if not one there already
- std::map<std::string, LLWaterParamSet>::const_iterator finder = mParamList.find(name);
- if(finder == mParamList.end())
- {
- mParamList[name].setAll(param);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ LLWaterParamSet param_set;
+ param_set.setAll(param);
+ return addParamSet(name, param_set);
}
bool LLWaterParamManager::getParamSet(const std::string& name, LLWaterParamSet& param)
{
// find it and set it
- std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
+ preset_map_t::iterator mIt = mParamList.find(name);
if(mIt != mParamList.end())
{
param = mParamList[name];
@@ -394,6 +307,12 @@ bool LLWaterParamManager::getParamSet(const std::string& name, LLWaterParamSet&
return false;
}
+bool LLWaterParamManager::hasParamSet(const std::string& name)
+{
+ LLWaterParamSet dummy;
+ return getParamSet(name, dummy);
+}
+
bool LLWaterParamManager::setParamSet(const std::string& name, LLWaterParamSet& param)
{
mParamList[name] = param;
@@ -417,29 +336,74 @@ bool LLWaterParamManager::setParamSet(const std::string& name, const LLSD & para
bool LLWaterParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
{
// remove from param list
- std::map<std::string, LLWaterParamSet>::iterator mIt = mParamList.find(name);
- if(mIt != mParamList.end())
+ preset_map_t::iterator it = mParamList.find(name);
+ if (it == mParamList.end())
{
- mParamList.erase(mIt);
+ LL_WARNS("WindLight") << "No water preset named " << name << LL_ENDL;
+ return false;
}
- if(delete_from_disk)
- {
+ mParamList.erase(it);
- std::string path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
-
- // use full curl escaped name
- char * curl_str = curl_escape(name.c_str(), name.size());
- std::string escaped_name(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
-
- gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml");
+ // remove from file system if requested
+ if (delete_from_disk)
+ {
+ if (gDirUtilp->deleteFilesInDir(getUserDir(), LLURI::escape(name) + ".xml") < 1)
+ {
+ LL_WARNS("WindLight") << "Error removing water preset " << name << " from disk" << LL_ENDL;
+ }
}
+ // signal interested parties
+ mPresetListChangeSignal();
return true;
}
+bool LLWaterParamManager::isSystemPreset(const std::string& preset_name) const
+{
+ // *TODO: file system access is excessive here.
+ return gDirUtilp->fileExists(getSysDir() + LLURI::escape(preset_name) + ".xml");
+}
+
+void LLWaterParamManager::getPresetNames(preset_name_list_t& presets) const
+{
+ presets.clear();
+
+ for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
+ {
+ presets.push_back(it->first);
+ }
+}
+
+void LLWaterParamManager::getPresetNames(preset_name_list_t& user_presets, preset_name_list_t& system_presets) const
+{
+ user_presets.clear();
+ system_presets.clear();
+
+ for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
+ {
+ if (isSystemPreset(it->first))
+ {
+ system_presets.push_back(it->first);
+ }
+ else
+ {
+ user_presets.push_back(it->first);
+ }
+ }
+}
+
+void LLWaterParamManager::getUserPresetNames(preset_name_list_t& user_presets) const
+{
+ preset_name_list_t dummy;
+ getPresetNames(user_presets, dummy);
+}
+
+boost::signals2::connection LLWaterParamManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb)
+{
+ return mPresetListChangeSignal.connect(cb);
+}
+
F32 LLWaterParamManager::getFogDensity(void)
{
bool err;
@@ -458,34 +422,22 @@ F32 LLWaterParamManager::getFogDensity(void)
return fogDensity;
}
-// static
-LLWaterParamManager * LLWaterParamManager::instance()
+// virtual static
+void LLWaterParamManager::initSingleton()
{
- if(NULL == sInstance)
- {
- sInstance = new LLWaterParamManager();
-
- sInstance->loadAllPresets(LLStringUtil::null);
-
- sInstance->getParamSet("Default", sInstance->mCurParams);
- sInstance->initOverrides();
- }
+ LL_DEBUGS("Windlight") << "Initializing water" << LL_ENDL;
+ loadAllPresets();
+ LLEnvManagerNew::instance().usePrefs();
+}
- return sInstance;
+// static
+std::string LLWaterParamManager::getSysDir()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "");
}
-void LLWaterParamManager::initOverrides()
+// static
+std::string LLWaterParamManager::getUserDir()
{
- // Override fog color from the current preset with the saved setting.
- LLColor4 fog_color_override = gSavedSettings.getColor4("WaterFogColor");
- mFogColor = fog_color_override;
- mPrevFogColor = fog_color_override;
- mCurParams.set("waterFogColor", fog_color_override);
-
- // Do the same with fog density.
- F32 fog_density = gSavedSettings.getF32("WaterFogDensity");
- mPrevFogDensity = fog_density;
- mFogDensity = fog_density;
- mCurParams.set("waterFogDensity", fog_density);
- setDensitySliderValue(mFogDensity.mExp);
+ return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/water", "");
}
diff --git a/indra/newview/llwaterparammanager.h b/indra/newview/llwaterparammanager.h
index f465034c39..dc7d41be2a 100644
--- a/indra/newview/llwaterparammanager.h
+++ b/indra/newview/llwaterparammanager.h
@@ -27,7 +27,7 @@
#ifndef LL_WATER_PARAMMANAGER_H
#define LL_WATER_PARAMMANAGER_H
-#include <vector>
+#include <list>
#include <map>
#include "llwaterparamset.h"
#include "llviewercamera.h"
@@ -212,19 +212,13 @@ struct WaterExpFloatControl
/// WindLight parameter manager class - what controls all the wind light shaders
-class LLWaterParamManager
+class LLWaterParamManager : public LLSingleton<LLWaterParamManager>
{
+ LOG_CLASS(LLWaterParamManager);
public:
-
- LLWaterParamManager();
- ~LLWaterParamManager();
-
- /// load a preset file
- void loadAllPresets(const std::string & fileName);
-
- /// load an individual preset into the sky
-
- void loadPreset(const std::string & name,bool propagate=true);
+ typedef std::list<std::string> preset_name_list_t;
+ typedef std::map<std::string, LLWaterParamSet> preset_map_t;
+ typedef boost::signals2::signal<void()> preset_list_signal_t;
/// save the parameter presets to file
void savePreset(const std::string & name);
@@ -232,18 +226,15 @@ public:
/// send the parameters to the shaders
void propagateParameters(void);
+ // display specified water
+ void applyParams(const LLSD& params, bool interpolate);
+
/// update information for the shader
void update(LLViewerCamera * cam);
/// Update shader uniforms that have changed.
void updateShaderUniforms(LLGLSLShader * shader);
- /// Perform global initialization for this class.
- static void initClass(void);
-
- // Cleanup of global data that's only inited once per class.
- static void cleanupClass();
-
/// add a param to the list
bool addParamSet(const std::string& name, LLWaterParamSet& param);
@@ -253,6 +244,9 @@ public:
/// get a param from the list
bool getParamSet(const std::string& name, LLWaterParamSet& param);
+ /// check whether the preset is in the list
+ bool hasParamSet(const std::string& name);
+
/// set the param in the list with a new param
bool setParamSet(const std::string& name, LLWaterParamSet& param);
@@ -263,6 +257,24 @@ public:
/// returns true if successful
bool removeParamSet(const std::string& name, bool delete_from_disk);
+ /// @return true if the preset comes out of the box
+ bool isSystemPreset(const std::string& preset_name) const;
+
+ /// @return all named water presets.
+ const preset_map_t& getPresets() const { return mParamList; }
+
+ /// @return user and system preset names as a single list
+ void getPresetNames(preset_name_list_t& presets) const;
+
+ /// @return user and system preset names separately
+ void getPresetNames(preset_name_list_t& user_presets, preset_name_list_t& system_presets) const;
+
+ /// @return list of user presets names
+ void getUserPresetNames(preset_name_list_t& user_presets) const;
+
+ /// Emitted when a preset gets added or deleted.
+ boost::signals2::connection setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb);
+
/// set the normap map we want for water
bool setNormalMapID(const LLUUID& img);
@@ -281,12 +293,6 @@ public:
F32 getFogDensity(void);
LLColor4 getFogColor(void);
- // singleton pattern implementation
- static LLWaterParamManager * instance();
-
-private:
- void initOverrides();
-
public:
LLWaterParamSet mCurParams;
@@ -308,20 +314,28 @@ public:
WaterFloatControl mScaleBelow;
WaterFloatControl mBlurMultiplier;
- // list of all the parameters, listed by name
- std::map<std::string, LLWaterParamSet> mParamList;
-
F32 mDensitySliderValue;
private:
+ friend class LLSingleton<LLWaterParamManager>;
+ /*virtual*/ void initSingleton();
+ LLWaterParamManager();
+ ~LLWaterParamManager();
+
+ void loadAllPresets();
+ void loadPresetsFromDir(const std::string& dir);
+ bool loadPreset(const std::string& path);
+
+ static std::string getSysDir();
+ static std::string getUserDir();
+
LLVector4 mWaterPlane;
F32 mWaterFogKS;
- LLColor4 mPrevFogColor;
- F32 mPrevFogDensity;
+ // list of all the parameters, listed by name
+ preset_map_t mParamList;
- // our parameter manager singleton instance
- static LLWaterParamManager * sInstance;
+ preset_list_signal_t mPresetListChangeSignal;
};
inline void LLWaterParamManager::setDensitySliderValue(F32 val)
diff --git a/indra/newview/llwaterparamset.cpp b/indra/newview/llwaterparamset.cpp
index 9457d631be..39d366b023 100644
--- a/indra/newview/llwaterparamset.cpp
+++ b/indra/newview/llwaterparamset.cpp
@@ -29,7 +29,6 @@
#include "llwaterparamset.h"
#include "llsd.h"
-#include "llfloaterwater.h"
#include "llwaterparammanager.h"
#include "lluictrlfactory.h"
#include "llsliderctrl.h"
@@ -224,3 +223,46 @@ F32 LLWaterParamSet::getFloat(const std::string& paramName, bool& error)
return 0;
}
+// Added for interpolation effect in DEV-33645
+// Based on LLWLParamSet::mix, but written by Jacob without an intimate knowledge of how WindLight works.
+// The function definition existed in the header but was never implemented. If you think there is something
+// wrong with this, you're probably right. Ask Jacob, Q, or a member of the original WindLight team.
+void LLWaterParamSet::mix(LLWaterParamSet& src, LLWaterParamSet& dest, F32 weight)
+{
+ // Setup
+ LLSD srcVal, destVal; // LLSD holders for get/set calls, reusable
+
+ // Iterate through values
+ for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
+ {
+ // If param exists in both src and dest, set the holder variables, otherwise skip
+ if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))
+ {
+ srcVal = src.mParamValues[iter->first];
+ destVal = dest.mParamValues[iter->first];
+ }
+ else
+ {
+ continue;
+ }
+
+ if(iter->second.isReal()) // If it's a real, interpolate directly
+ {
+ iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight);
+ }
+ else if(iter->second.isArray() && iter->second[0].isReal() // If it's an array of reals, loop through the reals and interpolate on those
+ && iter->second.size() == srcVal.size() && iter->second.size() == destVal.size())
+ {
+ // Actually do interpolation: old value + (difference in values * factor)
+ for(int i=0; i < iter->second.size(); ++i)
+ {
+ // iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal(); // old way of doing it -- equivalent but one more operation
+ iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight);
+ }
+ }
+ else // Else, skip
+ {
+ continue;
+ }
+ }
+}
diff --git a/indra/newview/llwaterparamset.h b/indra/newview/llwaterparamset.h
index 9957d5371b..b28585af59 100644
--- a/indra/newview/llwaterparamset.h
+++ b/indra/newview/llwaterparamset.h
@@ -34,7 +34,6 @@
#include "v4color.h"
#include "llviewershadermgr.h"
-class LLFloaterWater;
class LLWaterParamSet;
/// A class representing a set of parameter values for the Water shaders.
diff --git a/indra/newview/llwlanimator.cpp b/indra/newview/llwlanimator.cpp
index a94a2e41aa..e568638cf6 100644
--- a/indra/newview/llwlanimator.cpp
+++ b/indra/newview/llwlanimator.cpp
@@ -30,20 +30,31 @@
#include "llsky.h"
#include "pipeline.h"
#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
-LLWLAnimator::LLWLAnimator() : mStartTime(0), mDayRate(1), mDayTime(0),
- mIsRunning(FALSE), mUseLindenTime(false)
+extern LLControlGroup gSavedSettings;
+
+F64 LLWLAnimator::INTERP_TOTAL_SECONDS = 3.f;
+
+LLWLAnimator::LLWLAnimator() : mStartTime(0.f), mDayRate(1.f), mDayTime(0.f),
+ mIsRunning(FALSE), mIsInterpolating(FALSE), mTimeType(TIME_LINDEN),
+ mInterpStartTime(), mInterpEndTime()
{
- mDayTime = 0;
+ mInterpBeginWL = new LLWLParamSet();
+ mInterpBeginWater = new LLWaterParamSet();
+ mInterpEndWater = new LLWaterParamSet();
}
void LLWLAnimator::update(LLWLParamSet& curParams)
{
+ //llassert(mUseLindenTime != mUseLocalTime);
+
F64 curTime;
curTime = getDayTime();
// don't do anything if empty
- if(mTimeTrack.size() == 0) {
+ if(mTimeTrack.size() == 0)
+ {
return;
}
@@ -53,13 +64,15 @@ void LLWLAnimator::update(LLWLParamSet& curParams)
mSecondIt++;
// grab the two tween iterators
- while(mSecondIt != mTimeTrack.end() && curTime > mSecondIt->first) {
+ while(mSecondIt != mTimeTrack.end() && curTime > mSecondIt->first)
+ {
mFirstIt++;
mSecondIt++;
}
// scroll it around when you get to the end
- if(mSecondIt == mTimeTrack.end() || mFirstIt->first > curTime) {
+ if(mSecondIt == mTimeTrack.end() || mFirstIt->first > curTime)
+ {
mSecondIt = mTimeTrack.begin();
mFirstIt = mTimeTrack.end();
mFirstIt--;
@@ -67,70 +80,111 @@ void LLWLAnimator::update(LLWLParamSet& curParams)
F32 weight = 0;
- if(mFirstIt->first < mSecondIt->first) {
+ if(mFirstIt->first < mSecondIt->first)
+ {
// get the delta time and the proper weight
weight = F32 (curTime - mFirstIt->first) /
(mSecondIt->first - mFirstIt->first);
// handle the ends
- } else if(mFirstIt->first > mSecondIt->first) {
+ }
+ else if(mFirstIt->first > mSecondIt->first)
+ {
// right edge of time line
- if(curTime >= mFirstIt->first) {
+ if(curTime >= mFirstIt->first)
+ {
weight = F32 (curTime - mFirstIt->first) /
((1 + mSecondIt->first) - mFirstIt->first);
-
// left edge of time line
- } else {
+ }
+ else
+ {
weight = F32 ((1 + curTime) - mFirstIt->first) /
((1 + mSecondIt->first) - mFirstIt->first);
}
-
// handle same as whatever the last one is
- } else {
+ }
+ else
+ {
weight = 1;
}
+ if(mIsInterpolating)
+ {
+ // *TODO_JACOB: this is kind of laggy. Not sure why. The part that lags is the curParams.mix call, and none of the other mixes. It works, though.
+ clock_t current = clock();
+ if(current >= mInterpEndTime)
+ {
+ mIsInterpolating = false;
+ return;
+ }
+
+ // determine moving target for final interpolation value
+ // *TODO: this will not work with lazy loading of sky presets.
+ LLWLParamSet buf = LLWLParamSet();
+ buf.setAll(LLWLParamManager::getInstance()->mParamList[mFirstIt->second].getAll()); // just give it some values, otherwise it has no params to begin with (see comment in constructor)
+ buf.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight); // mix to determine moving target for interpolation finish (as below)
+
+ // mix from previous value to moving target
+ weight = (current - mInterpStartTime) / (INTERP_TOTAL_SECONDS * CLOCKS_PER_SEC);
+ curParams.mix(*mInterpBeginWL, buf, weight);
+
+ // mix water
+ LLWaterParamManager::getInstance()->mCurParams.mix(*mInterpBeginWater, *mInterpEndWater, weight);
+ }
+ else
+ {
// do the interpolation and set the parameters
- curParams.mix(LLWLParamManager::instance()->mParamList[mFirstIt->second],
- LLWLParamManager::instance()->mParamList[mSecondIt->second], weight);
+ // *TODO: this will not work with lazy loading of sky presets.
+ curParams.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight);
+ }
}
F64 LLWLAnimator::getDayTime()
{
- if(!mIsRunning) {
+ if(!mIsRunning)
+ {
return mDayTime;
}
-
- if(mUseLindenTime) {
-
+ else if(mTimeType == TIME_LINDEN)
+ {
F32 phase = gSky.getSunPhase() / F_PI;
// we're not solving the non-linear equation that determines sun phase
// we're just linearly interpolating between the major points
if (phase <= 5.0 / 4.0) {
mDayTime = (1.0 / 3.0) * phase + (1.0 / 3.0);
- } else {
+ }
+ else
+ {
mDayTime = phase - (1.0 / 2.0);
}
- if(mDayTime > 1) {
+ if(mDayTime > 1)
+ {
mDayTime--;
}
return mDayTime;
}
+ else if(mTimeType == TIME_LOCAL)
+ {
+ return getLocalTime();
+ }
// get the time;
mDayTime = (LLTimer::getElapsedSeconds() - mStartTime) / mDayRate;
// clamp it
- if(mDayTime < 0) {
+ if(mDayTime < 0)
+ {
mDayTime = 0;
}
- while(mDayTime > 1) {
+ while(mDayTime > 1)
+ {
mDayTime--;
}
@@ -144,15 +198,18 @@ void LLWLAnimator::setDayTime(F64 dayTime)
mDayTime = dayTime;
// clamp it
- if(mDayTime < 0) {
+ if(mDayTime < 0)
+ {
mDayTime = 0;
- } else if(mDayTime > 1) {
+ }
+ else if(mDayTime > 1)
+ {
mDayTime = 1;
}
}
-void LLWLAnimator::setTrack(std::map<F32, std::string>& curTrack,
+void LLWLAnimator::setTrack(std::map<F32, LLWLParamKey>& curTrack,
F32 dayRate, F64 dayTime, bool run)
{
mTimeTrack = curTrack;
@@ -161,3 +218,96 @@ void LLWLAnimator::setTrack(std::map<F32, std::string>& curTrack,
mIsRunning = run;
}
+
+void LLWLAnimator::startInterpolation(const LLSD& targetWater)
+{
+ mInterpBeginWL->setAll(LLWLParamManager::getInstance()->mCurParams.getAll());
+ mInterpBeginWater->setAll(LLWaterParamManager::getInstance()->mCurParams.getAll());
+
+ mInterpStartTime = clock();
+ mInterpEndTime = mInterpStartTime + clock_t(INTERP_TOTAL_SECONDS) * CLOCKS_PER_SEC;
+
+ // Don't set any ending WL -- this is continuously calculated as the animator updates since it's a moving target
+ mInterpEndWater->setAll(targetWater);
+
+ mIsInterpolating = true;
+}
+
+std::string LLWLAnimator::timeToString(F32 curTime)
+{
+ S32 hours;
+ S32 min;
+ bool isPM = false;
+
+ // get hours and minutes
+ hours = (S32) (24.0 * curTime);
+ curTime -= ((F32) hours / 24.0f);
+ min = llround(24.0f * 60.0f * curTime);
+
+ // handle case where it's 60
+ if(min == 60)
+ {
+ hours++;
+ min = 0;
+ }
+
+ // set for PM
+ if(hours >= 12 && hours < 24)
+ {
+ isPM = true;
+ }
+
+ // convert to non-military notation
+ if(hours >= 24)
+ {
+ hours = 12;
+ }
+ else if(hours > 12)
+ {
+ hours -= 12;
+ }
+ else if(hours == 0)
+ {
+ hours = 12;
+ }
+
+ // make the string
+ std::stringstream newTime;
+ newTime << hours << ":";
+
+ // double 0
+ if(min < 10)
+ {
+ newTime << 0;
+ }
+
+ // finish it
+ newTime << min << " ";
+ if(isPM)
+ {
+ newTime << "PM";
+ }
+ else
+ {
+ newTime << "AM";
+ }
+
+ return newTime.str();
+}
+
+F64 LLWLAnimator::getLocalTime()
+{
+ char buffer[9];
+ time_t rawtime;
+ struct tm* timeinfo;
+
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime(buffer, 9, "%H:%M:%S", timeinfo);
+ std::string timeStr(buffer);
+
+ F64 tod = ((F64)atoi(timeStr.substr(0,2).c_str())) / 24.f +
+ ((F64)atoi(timeStr.substr(3,2).c_str())) / 1440.f +
+ ((F64)atoi(timeStr.substr(6,2).c_str())) / 86400.f;
+ return tod;
+}
diff --git a/indra/newview/llwlanimator.h b/indra/newview/llwlanimator.h
index 5677290213..5223b45343 100644
--- a/indra/newview/llwlanimator.h
+++ b/indra/newview/llwlanimator.h
@@ -28,28 +28,39 @@
#define LL_WL_ANIMATOR_H
#include "llwlparamset.h"
+#include "llwaterparamset.h"
#include <string>
#include <map>
+struct LLWLParamKey;
+
class LLWLAnimator {
public:
+ typedef enum e_time
+ {
+ TIME_LINDEN,
+ TIME_LOCAL,
+ TIME_CUSTOM
+ } ETime;
+
F64 mStartTime;
F32 mDayRate;
F64 mDayTime;
// track to play
- std::map<F32, std::string> mTimeTrack;
- std::map<F32, std::string>::iterator mFirstIt, mSecondIt;
-
- // params to use
- //std::map<std::string, LLWLParamSet> mParamList;
-
- bool mIsRunning;
- bool mUseLindenTime;
+ std::map<F32, LLWLParamKey> mTimeTrack;
+ std::map<F32, LLWLParamKey>::iterator mFirstIt, mSecondIt;
// simple constructor
LLWLAnimator();
+ ~LLWLAnimator()
+ {
+ delete mInterpBeginWL;
+ delete mInterpBeginWater;
+ delete mInterpEndWater;
+ }
+
// update the parameters
void update(LLWLParamSet& curParams);
@@ -63,9 +74,66 @@ public:
void setDayTime(F64 dayTime);
// set an animation track
- void setTrack(std::map<F32, std::string>& track,
+ void setTrack(std::map<F32, LLWLParamKey>& track,
F32 dayRate, F64 dayTime = 0, bool run = true);
+ void deactivate()
+ {
+ mIsRunning = false;
+ }
+
+ void activate(ETime time)
+ {
+ mIsRunning = true;
+ mTimeType = time;
+ }
+
+ void startInterpolation(const LLSD& targetWater);
+
+ bool getIsRunning()
+ {
+ return mIsRunning;
+ }
+
+ bool getUseCustomTime()
+ {
+ return mTimeType == TIME_CUSTOM;
+ }
+
+ bool getUseLocalTime()
+ {
+ return mTimeType == TIME_LOCAL;
+ }
+
+ bool getUseLindenTime()
+ {
+ return mTimeType == TIME_LINDEN;
+ }
+
+ void setTimeType(ETime time)
+ {
+ mTimeType = time;
+ }
+
+ ETime getTimeType()
+ {
+ return mTimeType;
+ }
+
+ /// convert the present time to a digital clock time
+ static std::string timeToString(F32 curTime);
+
+ /// get local time between 0 and 1
+ static F64 getLocalTime();
+
+private:
+ ETime mTimeType;
+ bool mIsRunning, mIsInterpolating;
+ LLWLParamSet *mInterpBeginWL;
+ LLWaterParamSet *mInterpBeginWater, *mInterpEndWater;
+ clock_t mInterpStartTime, mInterpEndTime;
+
+ static F64 INTERP_TOTAL_SECONDS;
};
#endif // LL_WL_ANIMATOR_H
diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp
index 85b3d62a49..4c0cb7c0f4 100644
--- a/indra/newview/llwldaycycle.cpp
+++ b/indra/newview/llwldaycycle.cpp
@@ -27,12 +27,11 @@
#include "llviewerprecompiledheaders.h"
#include "llwldaycycle.h"
-
-#include "llnotificationsutil.h"
#include "llsdserialize.h"
-#include "llxmlnode.h"
-
#include "llwlparammanager.h"
+#include "llnotifications.h"
+
+#include "llviewerwindow.h"
#include <map>
@@ -45,85 +44,160 @@ LLWLDayCycle::~LLWLDayCycle()
{
}
-void LLWLDayCycle::loadDayCycle(const std::string & fileName)
+void LLWLDayCycle::loadDayCycle(const LLSD& day_data, LLWLParamKey::EScope scope)
{
- // clear the first few things
+ lldebugs << "Loading day cycle (day_data.size() = " << day_data.size() << ", scope = " << scope << ")" << llendl;
mTimeMap.clear();
- // now load the file
- std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
- "windlight/days", fileName));
- llinfos << "Loading DayCycle settings from " << pathName << llendl;
-
- llifstream day_cycle_xml(pathName);
- if (day_cycle_xml.is_open())
+ // add each key frame
+ for(S32 i = 0; i < day_data.size(); ++i)
{
- // load and parse it
- LLSD day_data(LLSD::emptyArray());
- LLPointer<LLSDParser> parser = new LLSDXMLParser();
- parser->parse(day_cycle_xml, day_data, LLSDSerialize::SIZE_UNLIMITED);
-
- // add each key
- for(S32 i = 0; i < day_data.size(); ++i)
+ // make sure it's a two array
+ if(day_data[i].size() != 2)
+ {
+ continue;
+ }
+
+ // check each param key exists in param manager
+ bool success;
+ LLWLParamSet pset;
+ LLWLParamKey frame = LLWLParamKey(day_data[i][1].asString(), scope);
+ success =
+ LLWLParamManager::getInstance()->getParamSet(frame, pset);
+ if(!success)
{
- // make sure it's a two array
- if(day_data[i].size() != 2)
+ // *HACK: If loading region day cycle, try local sky presets as well.
+ // Local presets may be referenced by a region day cycle after
+ // it has been edited but the changes have not been uploaded.
+ if (scope == LLEnvKey::SCOPE_REGION)
{
- continue;
+ frame.scope = LLEnvKey::SCOPE_LOCAL;
+ success = LLWLParamManager::getInstance()->getParamSet(frame, pset);
}
-
- // check each param name exists in param manager
- bool success;
- LLWLParamSet pset;
- success = LLWLParamManager::instance()->getParamSet(day_data[i][1].asString(), pset);
- if(!success)
+
+ if (!success)
{
// alert the user
LLSD args;
args["SKY"] = day_data[i][1].asString();
- LLNotificationsUtil::add("WLMissingSky", args);
+ LLNotifications::instance().add("WLMissingSky", args, LLSD());
continue;
}
-
- // then add the key
- addKey((F32)day_data[i][0].asReal(), day_data[i][1].asString());
}
+
+ // then add the keyframe
+ addKeyframe((F32)day_data[i][0].asReal(), frame);
+ }
+}
+
+void LLWLDayCycle::loadDayCycleFromFile(const std::string & fileName)
+{
+ loadDayCycle(loadCycleDataFromFile(fileName), LLWLParamKey::SCOPE_LOCAL);
+}
+/*static*/ LLSD LLWLDayCycle::loadCycleDataFromFile(const std::string & fileName)
+{
+ // *FIX: Cannot load user day cycles.
+ std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
+ "windlight/days", fileName));
+
+ return loadDayCycleFromPath(pathName);
+}
+
+// static
+LLSD LLWLDayCycle::loadDayCycleFromPath(const std::string& file_path)
+{
+ LL_INFOS("Windlight") << "Loading DayCycle settings from " << file_path << LL_ENDL;
+
+ llifstream day_cycle_xml(file_path);
+ if (day_cycle_xml.is_open())
+ {
+ // load and parse it
+ LLSD day_data(LLSD::emptyArray());
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+ parser->parse(day_cycle_xml, day_data, LLSDSerialize::SIZE_UNLIMITED);
day_cycle_xml.close();
+ return day_data;
+ }
+ else
+ {
+ return LLSD();
}
}
void LLWLDayCycle::saveDayCycle(const std::string & fileName)
{
- LLSD day_data(LLSD::emptyArray());
-
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/days", fileName));
//llinfos << "Saving WindLight settings to " << pathName << llendl;
- for(std::map<F32, std::string>::const_iterator mIt = mTimeMap.begin();
- mIt != mTimeMap.end();
- ++mIt)
+ save(pathName);
+}
+
+void LLWLDayCycle::save(const std::string& file_path)
+{
+ LLSD day_data = asLLSD();
+
+ llofstream day_cycle_xml(file_path);
+ LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
+ formatter->format(day_data, day_cycle_xml, LLSDFormatter::OPTIONS_PRETTY);
+ day_cycle_xml.close();
+}
+
+LLSD LLWLDayCycle::asLLSD()
+{
+ LLSD day_data(LLSD::emptyArray());
+ for(std::map<F32, LLWLParamKey>::const_iterator mIt = mTimeMap.begin(); mIt != mTimeMap.end(); ++mIt)
{
LLSD key(LLSD::emptyArray());
key.append(mIt->first);
- key.append(mIt->second);
+ key.append(mIt->second.name);
day_data.append(key);
}
- llofstream day_cycle_xml(pathName);
- LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
- formatter->format(day_data, day_cycle_xml, LLSDFormatter::OPTIONS_PRETTY);
- day_cycle_xml.close();
+ lldebugs << "Dumping day cycle (" << mTimeMap.size() << ") to LLSD: " << day_data << llendl;
+ return day_data;
}
+bool LLWLDayCycle::getSkyRefs(std::map<LLWLParamKey, LLWLParamSet>& refs) const
+{
+ bool result = true;
+ LLWLParamManager& wl_mgr = LLWLParamManager::instance();
+
+ refs.clear();
+ for (std::map<F32, LLWLParamKey>::const_iterator iter = mTimeMap.begin(); iter != mTimeMap.end(); ++iter)
+ {
+ const LLWLParamKey& key = iter->second;
+ if (!wl_mgr.getParamSet(key, refs[key]))
+ {
+ llwarns << "Cannot find sky [" << key.name << "] referenced by a day cycle" << llendl;
+ result = false;
+ }
+ }
+
+ return result;
+}
-void LLWLDayCycle::clearKeys()
+bool LLWLDayCycle::getSkyMap(LLSD& sky_map) const
{
+ std::map<LLWLParamKey, LLWLParamSet> refs;
+
+ if (!getSkyRefs(refs))
+ {
+ return false;
+ }
+
+ sky_map = LLWLParamManager::createSkyMap(refs);
+ return true;
+}
+
+void LLWLDayCycle::clearKeyframes()
+{
+ lldebugs << "Clearing key frames" << llendl;
mTimeMap.clear();
}
-bool LLWLDayCycle::addKey(F32 newTime, const std::string & paramName)
+bool LLWLDayCycle::addKeyframe(F32 newTime, LLWLParamKey frame)
{
// no adding negative time
if(newTime < 0)
@@ -134,48 +208,58 @@ bool LLWLDayCycle::addKey(F32 newTime, const std::string & paramName)
// if time not being used, add it and return true
if(mTimeMap.find(newTime) == mTimeMap.end())
{
- mTimeMap.insert(std::pair<F32, std::string>(newTime, paramName));
+ mTimeMap.insert(std::pair<F32, LLWLParamKey>(newTime, frame));
+ lldebugs << "Adding key frame (" << newTime << ", " << frame.toLLSD() << ")" << llendl;
return true;
}
// otherwise, don't add, and return error
+ llwarns << "Error adding key frame (" << newTime << ", " << frame.toLLSD() << ")" << llendl;
return false;
}
-bool LLWLDayCycle::changeKeyTime(F32 oldTime, F32 newTime)
+bool LLWLDayCycle::changeKeyframeTime(F32 oldTime, F32 newTime)
{
+ lldebugs << "Changing key frame time (" << oldTime << " => " << newTime << ")" << llendl;
+
// just remove and add back
- std::string name = mTimeMap[oldTime];
+ LLWLParamKey frame = mTimeMap[oldTime];
- bool stat = removeKey(oldTime);
+ bool stat = removeKeyframe(oldTime);
if(stat == false)
{
+ lldebugs << "Failed to change key frame time (" << oldTime << " => " << newTime << ")" << llendl;
return stat;
}
- return addKey(newTime, name);
+ return addKeyframe(newTime, frame);
}
-bool LLWLDayCycle::changeKeyParam(F32 time, const std::string & name)
+bool LLWLDayCycle::changeKeyframeParam(F32 time, LLWLParamKey key)
{
+ lldebugs << "Changing key frame param (" << time << ", " << key.toLLSD() << ")" << llendl;
+
// just remove and add back
// make sure param exists
LLWLParamSet tmp;
- bool stat = LLWLParamManager::instance()->getParamSet(name, tmp);
+ bool stat = LLWLParamManager::getInstance()->getParamSet(key, tmp);
if(stat == false)
{
+ lldebugs << "Failed to change key frame param (" << time << ", " << key.toLLSD() << ")" << llendl;
return stat;
}
- mTimeMap[time] = name;
+ mTimeMap[time] = key;
return true;
}
-bool LLWLDayCycle::removeKey(F32 time)
+bool LLWLDayCycle::removeKeyframe(F32 time)
{
+ lldebugs << "Removing key frame (" << time << ")" << llendl;
+
// look for the time. If there, erase it
- std::map<F32, std::string>::iterator mIt = mTimeMap.find(time);
+ std::map<F32, LLWLParamKey>::iterator mIt = mTimeMap.find(time);
if(mIt != mTimeMap.end())
{
mTimeMap.erase(mIt);
@@ -185,15 +269,15 @@ bool LLWLDayCycle::removeKey(F32 time)
return false;
}
-bool LLWLDayCycle::getKey(const std::string & name, F32& key)
+bool LLWLDayCycle::getKeytime(LLWLParamKey frame, F32& key_time) const
{
- // scroll through till we find the
- std::map<F32, std::string>::iterator mIt = mTimeMap.begin();
+ // scroll through till we find the correct value in the map
+ std::map<F32, LLWLParamKey>::const_iterator mIt = mTimeMap.begin();
for(; mIt != mTimeMap.end(); ++mIt)
{
- if(name == mIt->second)
+ if(frame == mIt->second)
{
- key = mIt->first;
+ key_time = mIt->first;
return true;
}
}
@@ -204,26 +288,52 @@ bool LLWLDayCycle::getKey(const std::string & name, F32& key)
bool LLWLDayCycle::getKeyedParam(F32 time, LLWLParamSet& param)
{
// just scroll on through till you find it
- std::map<F32, std::string>::iterator mIt = mTimeMap.find(time);
- if(mIt != mTimeMap.end())
+ std::map<F32, LLWLParamKey>::iterator mIt = mTimeMap.find(time);
+ if(mIt != mTimeMap.end())
{
- return LLWLParamManager::instance()->getParamSet(mIt->second, param);
+ return LLWLParamManager::getInstance()->getParamSet(mIt->second, param);
}
// return error if not found
+ lldebugs << "Key " << time << " not found" << llendl;
return false;
}
bool LLWLDayCycle::getKeyedParamName(F32 time, std::string & name)
{
// just scroll on through till you find it
- std::map<F32, std::string>::iterator mIt = mTimeMap.find(time);
+ std::map<F32, LLWLParamKey>::iterator mIt = mTimeMap.find(time);
if(mIt != mTimeMap.end())
{
- name = mTimeMap[time];
+ name = mTimeMap[time].name;
return true;
}
// return error if not found
+ lldebugs << "Key " << time << " not found" << llendl;
return false;
}
+
+bool LLWLDayCycle::hasReferencesTo(const LLWLParamKey& keyframe) const
+{
+ F32 dummy;
+ return getKeytime(keyframe, dummy);
+}
+
+void LLWLDayCycle::removeReferencesTo(const LLWLParamKey& keyframe)
+{
+ lldebugs << "Removing references to key frame " << keyframe.toLLSD() << llendl;
+ F32 keytime;
+ bool might_exist;
+ do
+ {
+ // look for it
+ might_exist = getKeytime(keyframe, keytime);
+ if(!might_exist)
+ {
+ return;
+ }
+ might_exist = removeKeyframe(keytime);
+
+ } while(might_exist); // might be another one
+}
diff --git a/indra/newview/llwldaycycle.h b/indra/newview/llwldaycycle.h
index 5cbf72191d..c8585564ed 100644
--- a/indra/newview/llwldaycycle.h
+++ b/indra/newview/llwldaycycle.h
@@ -34,13 +34,16 @@ class LLWLDayCycle;
#include <string>
#include "llwlparamset.h"
#include "llwlanimator.h"
+struct LLWLParamKey;
+#include "llenvmanager.h" // for LLEnvKey::EScope
class LLWLDayCycle
{
+ LOG_CLASS(LLWLDayCycle);
public:
// lists what param sets are used when during the day
- std::map<F32, std::string> mTimeMap;
+ std::map<F32, LLWLParamKey> mTimeMap;
// how long is my day
F32 mDayRate;
@@ -54,35 +57,56 @@ public:
~LLWLDayCycle();
/// load a day cycle
- void loadDayCycle(const std::string & fileName);
+ void loadDayCycle(const LLSD& llsd, LLEnvKey::EScope scope);
/// load a day cycle
+ void loadDayCycleFromFile(const std::string & fileName);
+
+ /// save a day cycle
void saveDayCycle(const std::string & fileName);
- /// clear keys
- void clearKeys();
+ /// save a day cycle
+ void save(const std::string& file_path);
+
+ /// load the LLSD data from a file (returns the undefined LLSD if not found)
+ static LLSD loadCycleDataFromFile(const std::string & fileName);
+
+ /// load the LLSD data from a file specified by full path
+ static LLSD loadDayCycleFromPath(const std::string& file_path);
+
+ /// get the LLSD data for this day cycle
+ LLSD asLLSD();
+
+ // get skies referenced by this day cycle
+ bool getSkyRefs(std::map<LLWLParamKey, LLWLParamSet>& refs) const;
+
+ // get referenced skies as LLSD
+ bool getSkyMap(LLSD& sky_map) const;
+
+ /// clear keyframes
+ void clearKeyframes();
/// Getters and Setters
/// add a new key frame to the day cycle
/// returns true if successful
/// no negative time
- bool addKey(F32 newTime, const std::string & paramName);
+ bool addKeyframe(F32 newTime, LLWLParamKey key);
- /// adjust a key's placement in the day cycle
+ /// adjust a keyframe's placement in the day cycle
/// returns true if successful
- bool changeKeyTime(F32 oldTime, F32 newTime);
+ bool changeKeyframeTime(F32 oldTime, F32 newTime);
- /// adjust a key's parameter used
+ /// adjust a keyframe's parameter used
/// returns true if successful
- bool changeKeyParam(F32 time, const std::string & paramName);
+ bool changeKeyframeParam(F32 time, LLWLParamKey key);
- /// remove a key from the day cycle
+ /// remove a key frame from the day cycle
/// returns true if successful
- bool removeKey(F32 time);
+ bool removeKeyframe(F32 time);
/// get the first key time for a parameter
/// returns false if not there
- bool getKey(const std::string & name, F32& key);
+ bool getKeytime(LLWLParamKey keyFrame, F32& keyTime) const;
/// get the param set at a given time
/// returns true if found one
@@ -92,6 +116,12 @@ public:
/// returns true if it found one
bool getKeyedParamName(F32 time, std::string & name);
+ /// @return true if there are references to the given sky
+ bool hasReferencesTo(const LLWLParamKey& keyframe) const;
+
+ /// removes all references to the sky (paramkey)
+ /// does nothing if the sky doesn't exist in the day
+ void removeReferencesTo(const LLWLParamKey& keyframe);
};
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
new file mode 100644
index 0000000000..b5f53232cc
--- /dev/null
+++ b/indra/newview/llwlhandlers.cpp
@@ -0,0 +1,203 @@
+/**
+ * @file llwlhandlers.cpp
+ * @brief Various classes which handle Windlight-related messaging
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llwlhandlers.h"
+
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "llenvmanager.h"
+#include "llnotificationsutil.h"
+
+/****
+ * LLEnvironmentRequest
+ ****/
+// static
+bool LLEnvironmentRequest::initiate()
+{
+ LLViewerRegion* cur_region = gAgent.getRegion();
+
+ if (!cur_region)
+ {
+ LL_WARNS("WindlightCaps") << "Viewer region not set yet, skipping env. settings request" << LL_ENDL;
+ return false;
+ }
+
+ if (!cur_region->capabilitiesReceived())
+ {
+ LL_INFOS("WindlightCaps") << "Deferring windlight settings request until we've got region caps" << LL_ENDL;
+ cur_region->setCapabilitiesReceivedCallback(boost::bind(&LLEnvironmentRequest::onRegionCapsReceived, _1));
+ return false;
+ }
+
+ return doRequest();
+}
+
+// static
+void LLEnvironmentRequest::onRegionCapsReceived(const LLUUID& region_id)
+{
+ if (region_id != gAgent.getRegion()->getRegionID())
+ {
+ LL_INFOS("WindlightCaps") << "Got caps for a non-current region" << LL_ENDL;
+ return;
+ }
+
+ LL_DEBUGS("WindlightCaps") << "Received region capabilities" << LL_ENDL;
+ doRequest();
+}
+
+// static
+bool LLEnvironmentRequest::doRequest()
+{
+ std::string url = gAgent.getRegion()->getCapability("EnvironmentSettings");
+ if (url.empty())
+ {
+ LL_INFOS("WindlightCaps") << "Skipping windlight setting request - we don't have this capability" << LL_ENDL;
+ // region is apparently not capable of this; don't respond at all
+ return false;
+ }
+
+ LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL;
+ LLHTTPClient::get(url, new LLEnvironmentRequestResponder());
+ return true;
+}
+
+/****
+ * LLEnvironmentRequestResponder
+ ****/
+int LLEnvironmentRequestResponder::sCount = 0; // init to 0
+
+LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
+{
+ mID = ++sCount;
+}
+/*virtual*/ void LLEnvironmentRequestResponder::result(const LLSD& unvalidated_content)
+{
+ LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
+
+ if (mID != sCount)
+ {
+ LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL;
+ return;
+ }
+
+ if (unvalidated_content[0]["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
+ {
+ LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
+ << gAgent.getRegion()->getRegionID() << " but got " << unvalidated_content[0]["regionID"].asUUID()
+ << ") - ignoring..." << LL_ENDL;
+ return;
+ }
+
+ LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content);
+}
+/*virtual*/ void LLEnvironmentRequestResponder::error(U32 status, const std::string& reason)
+{
+ LL_INFOS("WindlightCaps") << "Got an error, not using region windlight..." << LL_ENDL;
+ LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
+}
+
+/****
+ * LLEnvironmentApply
+ ****/
+
+clock_t LLEnvironmentApply::UPDATE_WAIT_SECONDS = clock_t(3.f);
+clock_t LLEnvironmentApply::sLastUpdate = clock_t(0.f);
+
+// static
+bool LLEnvironmentApply::initiateRequest(const LLSD& content)
+{
+ clock_t current = clock();
+
+ // Make sure we don't update too frequently.
+ if (current < sLastUpdate + (UPDATE_WAIT_SECONDS * CLOCKS_PER_SEC))
+ {
+ LLSD args(LLSD::emptyMap());
+ args["WAIT"] = (F64)UPDATE_WAIT_SECONDS;
+ LLNotificationsUtil::add("EnvUpdateRate", args);
+ return false;
+ }
+
+ sLastUpdate = current;
+
+ // Send update request.
+ std::string url = gAgent.getRegion()->getCapability("EnvironmentSettings");
+ if (url.empty())
+ {
+ LL_WARNS("WindlightCaps") << "Applying windlight settings not supported" << LL_ENDL;
+ return false;
+ }
+
+ LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL;
+ LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL;
+ LLHTTPClient::post(url, content, new LLEnvironmentApplyResponder());
+ return true;
+}
+
+/****
+ * LLEnvironmentApplyResponder
+ ****/
+/*virtual*/ void LLEnvironmentApplyResponder::result(const LLSD& content)
+{
+ if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
+ {
+ LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
+ << gAgent.getRegion()->getRegionID() << ", reply is from " << content["regionID"].asUUID()
+ << "); ignoring..." << LL_ENDL;
+ return;
+ }
+ else if (content["success"].asBoolean())
+ {
+ LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << content["regionID"].asUUID() << LL_ENDL;
+ LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true);
+ }
+ else
+ {
+ LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! Reason from sim: " << content["fail_reason"].asString() << LL_ENDL;
+ LLSD args(LLSD::emptyMap());
+ args["FAIL_REASON"] = content["fail_reason"].asString();
+ LLNotificationsUtil::add("WLRegionApplyFail", args);
+ LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
+ }
+}
+/*virtual*/ void LLEnvironmentApplyResponder::error(U32 status, const std::string& reason)
+{
+ std::stringstream msg;
+ msg << reason << " (Code " << status << ")";
+
+ LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! Reason: " << msg << LL_ENDL;
+
+ LLSD args(LLSD::emptyMap());
+ args["FAIL_REASON"] = msg.str();
+ LLNotificationsUtil::add("WLRegionApplyFail", args);
+}
diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h
new file mode 100644
index 0000000000..213bc7c7ce
--- /dev/null
+++ b/indra/newview/llwlhandlers.h
@@ -0,0 +1,106 @@
+/**
+ * @file llwlhandlers.h
+ * @brief Headers for classes in llwlhandlers.cpp
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLWLHANDLERS_H
+#define LL_LLWLHANDLERS_H
+
+#include "llviewerprecompiledheaders.h"
+#include "llhttpclient.h"
+
+class LLEnvironmentRequest
+{
+ LOG_CLASS(LLEnvironmentRequest);
+public:
+ /// @return true if request was successfully sent
+ static bool initiate();
+
+private:
+ static void onRegionCapsReceived(const LLUUID& region_id);
+ static bool doRequest();
+};
+
+class LLEnvironmentRequestResponder: public LLHTTPClient::Responder
+{
+ LOG_CLASS(LLEnvironmentRequestResponder);
+public:
+ virtual void result(const LLSD& content);
+ virtual void error(U32 status, const std::string& reason);
+
+private:
+ friend class LLEnvironmentRequest;
+
+ LLEnvironmentRequestResponder();
+ static int sCount;
+ int mID;
+};
+
+class LLEnvironmentApply
+{
+ LOG_CLASS(LLEnvironmentApply);
+public:
+ /// @return true if request was successfully sent
+ static bool initiateRequest(const LLSD& content);
+
+private:
+ static clock_t sLastUpdate;
+ static clock_t UPDATE_WAIT_SECONDS;
+};
+
+class LLEnvironmentApplyResponder: public LLHTTPClient::Responder
+{
+ LOG_CLASS(LLEnvironmentApplyResponder);
+public:
+ /*
+ * Expecting reply from sim in form of:
+ * {
+ * regionID : uuid,
+ * messageID: uuid,
+ * success : true
+ * }
+ * or
+ * {
+ * regionID : uuid,
+ * success : false,
+ * fail_reason : string
+ * }
+ */
+ virtual void result(const LLSD& content);
+
+ virtual void error(U32 status, const std::string& reason); // non-200 errors only
+
+private:
+ friend class LLEnvironmentApply;
+
+ LLEnvironmentApplyResponder() {}
+};
+
+#endif // LL_LLWLHANDLERS_H
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index 848efcbb49..55608a059f 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -37,23 +37,29 @@
#include "llspinctrl.h"
#include "llcheckboxctrl.h"
#include "lluictrlfactory.h"
+#include "llviewercamera.h"
#include "llcombobox.h"
#include "lllineeditor.h"
#include "llsdserialize.h"
#include "v4math.h"
+#include "llviewerdisplay.h"
#include "llviewercontrol.h"
+#include "llviewerwindow.h"
+#include "lldrawpoolwater.h"
+#include "llagent.h"
+#include "llviewerregion.h"
+#include "lldaycyclemanager.h"
+#include "llenvmanager.h"
#include "llwlparamset.h"
#include "llpostprocess.h"
-#include "llfloaterwindlight.h"
-#include "llfloaterdaycycle.h"
-#include "llfloaterenvsettings.h"
-#include "curl/curl.h"
+#include "llviewershadermgr.h"
+#include "llglslshader.h"
-LLWLParamManager * LLWLParamManager::sInstance = NULL;
-static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params");
+#include "curl/curl.h"
+#include "llstreamtools.h"
LLWLParamManager::LLWLParamManager() :
@@ -96,161 +102,237 @@ LLWLParamManager::~LLWLParamManager()
{
}
-void LLWLParamManager::loadPresets(const std::string& file_name)
+void LLWLParamManager::clearParamSetsOfScope(LLWLParamKey::EScope scope)
{
- std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));
- LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
-
- bool found = true;
- LLDirIterator app_settings_iter(path_name, "*.xml");
- while(found)
+ if (LLWLParamKey::SCOPE_LOCAL == scope)
{
- std::string name;
- found = app_settings_iter.next(name);
- if(found)
- {
-
- name=name.erase(name.length()-4);
-
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_unescape(name.c_str(), name.size());
- std::string unescaped_name(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
+ LL_WARNS("Windlight") << "Tried to clear windlight sky presets from local system! This shouldn't be called..." << LL_ENDL;
+ return;
+ }
- LL_DEBUGS2("AppInit", "Shaders") << "name: " << name << LL_ENDL;
- loadPreset(unescaped_name,FALSE);
+ std::set<LLWLParamKey> to_remove;
+ for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = mParamList.begin(); iter != mParamList.end(); ++iter)
+ {
+ if(iter->first.scope == scope)
+ {
+ to_remove.insert(iter->first);
}
}
- // And repeat for user presets, note the user presets will modify any system presets already loaded
+ for(std::set<LLWLParamKey>::iterator iter = to_remove.begin(); iter != to_remove.end(); ++iter)
+ {
+ mParamList.erase(*iter);
+ }
+}
- std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
- LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
-
- found = true;
- LLDirIterator user_settings_iter(path_name2, "*.xml");
- while(found)
+// returns all skies referenced by the day cycle, with their final names
+// side effect: applies changes to all internal structures!
+std::map<LLWLParamKey, LLWLParamSet> LLWLParamManager::finalizeFromDayCycle(LLWLParamKey::EScope scope)
+{
+ lldebugs << "mDay before finalizing:" << llendl;
{
- std::string name;
- found = user_settings_iter.next(name);
- if(found)
+ for (std::map<F32, LLWLParamKey>::iterator iter = mDay.mTimeMap.begin(); iter != mDay.mTimeMap.end(); ++iter)
{
- name=name.erase(name.length()-4);
+ LLWLParamKey& key = iter->second;
+ lldebugs << iter->first << "->" << key.name << llendl;
+ }
+ }
+
+ std::map<LLWLParamKey, LLWLParamSet> final_references;
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_unescape(name.c_str(), name.size());
- std::string unescaped_name(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
+ // Move all referenced to desired scope, renaming if necessary
+ // First, save skies referenced
+ std::map<LLWLParamKey, LLWLParamSet> current_references; // all skies referenced by the day cycle, with their current names
+ // guard against skies with same name and different scopes
+ std::set<std::string> inserted_names;
+ std::map<std::string, unsigned int> conflicted_names; // integer later used as a count, for uniquely renaming conflicts
- LL_DEBUGS2("AppInit", "Shaders") << "name: " << name << LL_ENDL;
- loadPreset(unescaped_name,FALSE);
+ LLWLDayCycle& cycle = mDay;
+ for(std::map<F32, LLWLParamKey>::iterator iter = cycle.mTimeMap.begin();
+ iter != cycle.mTimeMap.end();
+ ++iter)
+ {
+ LLWLParamKey& key = iter->second;
+ std::string desired_name = key.name;
+ replace_newlines_with_whitespace(desired_name); // already shouldn't have newlines, but just in case
+ if(inserted_names.find(desired_name) == inserted_names.end())
+ {
+ inserted_names.insert(desired_name);
}
+ else
+ {
+ // make exist in map
+ conflicted_names[desired_name] = 0;
+ }
+ current_references[key] = mParamList[key];
}
-}
+ // forget all old skies in target scope, and rebuild, renaming as needed
+ clearParamSetsOfScope(scope);
+ for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = current_references.begin(); iter != current_references.end(); ++iter)
+ {
+ const LLWLParamKey& old_key = iter->first;
-void LLWLParamManager::savePresets(const std::string & fileName)
-{
- //Nobody currently calls me, but if they did, then its reasonable to write the data out to the user's folder
- //and not over the RO system wide version.
+ std::string desired_name(old_key.name);
+ replace_newlines_with_whitespace(desired_name);
- LLSD paramsData(LLSD::emptyMap());
-
- std::string pathName(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", fileName));
+ LLWLParamKey new_key(desired_name, scope); // name will be replaced later if necessary
- for(std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.begin();
- mIt != mParamList.end();
- ++mIt)
- {
- paramsData[mIt->first] = mIt->second.getAll();
- }
+ // if this sky is one with a non-unique name, rename via appending a number
+ // an existing preset of the target scope gets to keep its name
+ if (scope != old_key.scope && conflicted_names.find(desired_name) != conflicted_names.end())
+ {
+ std::string& new_name = new_key.name;
- llofstream presetsXML(pathName);
+ do
+ {
+ // if this executes more than once, this is an absurdly pathological case
+ // (e.g. "x" repeated twice, but "x 1" already exists, so need to use "x 2")
+ std::stringstream temp;
+ temp << desired_name << " " << (++conflicted_names[desired_name]);
+ new_name = temp.str();
+ } while (inserted_names.find(new_name) != inserted_names.end());
- LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
+ // yay, found one that works
+ inserted_names.insert(new_name); // track names we consume here; shouldn't be necessary due to ++int? but just in case
- formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
+ // *TODO factor out below into a rename()?
- presetsXML.close();
-}
+ LL_INFOS("Windlight") << "Renamed " << old_key.name << " (scope" << old_key.scope << ") to "
+ << new_key.name << " (scope " << new_key.scope << ")" << LL_ENDL;
-void LLWLParamManager::loadPreset(const std::string & name,bool propagate)
-{
-
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_escape(name.c_str(), name.size());
- std::string escaped_filename(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
+ // update name in sky
+ iter->second.mName = new_name;
- escaped_filename += ".xml";
+ // update keys in day cycle
+ for(std::map<F32, LLWLParamKey>::iterator frame = cycle.mTimeMap.begin(); frame != cycle.mTimeMap.end(); ++frame)
+ {
+ if (frame->second == old_key)
+ {
+ frame->second = new_key;
+ }
+ }
- std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename));
- LL_DEBUGS2("AppInit", "Shaders") << "Loading WindLight sky setting from " << pathName << LL_ENDL;
+ // add to master sky map
+ mParamList[new_key] = iter->second;
+ }
- llifstream presetsXML;
- presetsXML.open(pathName.c_str());
+ final_references[new_key] = iter->second;
+ }
- // That failed, try loading from the users area instead.
- if(!presetsXML)
+ lldebugs << "mDay after finalizing:" << llendl;
{
- pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", escaped_filename);
- LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight sky setting from " << pathName << LL_ENDL;
- presetsXML.clear();
- presetsXML.open(pathName.c_str());
+ for (std::map<F32, LLWLParamKey>::iterator iter = mDay.mTimeMap.begin(); iter != mDay.mTimeMap.end(); ++iter)
+ {
+ LLWLParamKey& key = iter->second;
+ lldebugs << iter->first << "->" << key.name << llendl;
+ }
}
- if (presetsXML)
+ return final_references;
+}
+
+// static
+LLSD LLWLParamManager::createSkyMap(std::map<LLWLParamKey, LLWLParamSet> refs)
+{
+ LLSD skies = LLSD::emptyMap();
+ for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = refs.begin(); iter != refs.end(); ++iter)
{
- LLSD paramsData(LLSD::emptyMap());
+ skies.insert(iter->first.name, iter->second.getAll());
+ }
+ return skies;
+}
- LLPointer<LLSDParser> parser = new LLSDXMLParser();
+void LLWLParamManager::addAllSkies(const LLWLParamKey::EScope scope, const LLSD& sky_presets)
+{
+ for(LLSD::map_const_iterator iter = sky_presets.beginMap(); iter != sky_presets.endMap(); ++iter)
+ {
+ LLWLParamSet set;
+ set.setAll(iter->second);
+ mParamList[LLWLParamKey(iter->first, scope)] = set;
+ }
+}
- parser->parse(presetsXML, paramsData, LLSDSerialize::SIZE_UNLIMITED);
+void LLWLParamManager::refreshRegionPresets()
+{
+ // Remove all region sky presets because they may belong to a previously visited region.
+ clearParamSetsOfScope(LLEnvKey::SCOPE_REGION);
+
+ // Add all sky presets belonging to the current region.
+ addAllSkies(LLEnvKey::SCOPE_REGION, LLEnvManagerNew::instance().getRegionSettings().getSkyMap());
+}
+
+void LLWLParamManager::loadAllPresets()
+{
+ // First, load system (coming out of the box) sky presets.
+ loadPresetsFromDir(getSysDir());
- std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
- if(mIt == mParamList.end())
+ // Then load user presets. Note that user day presets will modify any system ones already loaded.
+ loadPresetsFromDir(getUserDir());
+}
+
+void LLWLParamManager::loadPresetsFromDir(const std::string& dir)
+{
+ LL_INFOS2("AppInit", "Shaders") << "Loading sky presets from " << dir << LL_ENDL;
+
+ LLDirIterator dir_iter(dir, "*.xml");
+ while (1)
+ {
+ std::string file;
+ if (!dir_iter.next(file))
{
- addParamSet(name, paramsData);
+ break; // no more files
}
- else
+
+ std::string path = dir + file;
+ if (!loadPreset(path))
{
- setParamSet(name, paramsData);
+ llwarns << "Error loading sky preset from " << path << llendl;
}
- presetsXML.close();
- }
- else
+ }
+}
+
+bool LLWLParamManager::loadPreset(const std::string& path)
+{
+ llifstream xml_file;
+ std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
+
+ xml_file.open(path.c_str());
+ if (!xml_file)
{
- llwarns << "Can't find " << name << llendl;
- return;
+ return false;
}
-
- if(propagate)
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading sky " << name << LL_ENDL;
+
+ LLSD params_data;
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+ parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
+ xml_file.close();
+
+ LLWLParamKey key(name, LLEnvKey::SCOPE_LOCAL);
+ if (hasParamSet(key))
{
- getParamSet(name, mCurParams);
- propagateParameters();
+ setParamSet(key, params_data);
+ }
+ else
+ {
+ addParamSet(key, params_data);
}
-}
-void LLWLParamManager::savePreset(const std::string & name)
-{
- // bugfix for SL-46920: preventing filenames that break stuff.
- char * curl_str = curl_escape(name.c_str(), name.size());
- std::string escaped_filename(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
+ return true;
+}
- escaped_filename += ".xml";
+void LLWLParamManager::savePreset(LLWLParamKey key)
+{
+ llassert(key.scope == LLEnvKey::SCOPE_LOCAL && !key.name.empty());
// make an empty llsd
LLSD paramsData(LLSD::emptyMap());
- std::string pathName(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", escaped_filename));
+ std::string pathName(getUserDir() + escapeString(key.name) + ".xml");
// fill it with LLSD windlight params
- paramsData = mParamList[name].getAll();
+ paramsData = mParamList[key].getAll();
// write to file
llofstream presetsXML(pathName);
@@ -283,6 +365,8 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)
}
+static LLFastTimer::DeclareTimer FTM_UPDATE_WLPARAM("Update Windlight Params");
+
void LLWLParamManager::propagateParameters(void)
{
LLFastTimer ftm(FTM_UPDATE_WLPARAM);
@@ -362,7 +446,7 @@ void LLWLParamManager::update(LLViewerCamera * cam)
mCurParams.updateCloudScrolling();
// update only if running
- if(mAnimator.mIsRunning)
+ if(mAnimator.getIsRunning())
{
mAnimator.update(mCurParams);
}
@@ -370,31 +454,16 @@ void LLWLParamManager::update(LLViewerCamera * cam)
// update the shaders and the menu
propagateParameters();
- // sync menus if they exist
- LLFloaterWindLight* wlfloater = LLFloaterReg::findTypedInstance<LLFloaterWindLight>("env_windlight");
- if (wlfloater)
- {
- wlfloater->syncMenu();
- }
- LLFloaterDayCycle* dlfloater = LLFloaterReg::findTypedInstance<LLFloaterDayCycle>("env_day_cycle");
- if (dlfloater)
- {
- dlfloater->syncMenu();
- }
- LLFloaterEnvSettings* envfloater = LLFloaterReg::findTypedInstance<LLFloaterEnvSettings>("env_settings");
- if (envfloater)
- {
- envfloater->syncMenu();
- }
-
F32 camYaw = cam->getYaw();
+ stop_glerror();
+
// *TODO: potential optimization - this block may only need to be
// executed some of the time. For example for water shaders only.
{
F32 camYawDelta = mSunDeltaYaw * DEG_TO_RAD;
- LLVector3 lightNorm3(mLightDir);
+ LLVector3 lightNorm3(mLightDir);
lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f));
mRotatedLightDir = LLVector4(lightNorm3, 0.f);
@@ -412,17 +481,18 @@ void LLWLParamManager::update(LLViewerCamera * cam)
}
}
-// static
-void LLWLParamManager::initClass(void)
+bool LLWLParamManager::applyDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time)
{
- instance();
+ mDay.loadDayCycle(params, scope);
+ resetAnimator(time, true); // set to specified time and start animator
+ return true;
}
-// static
-void LLWLParamManager::cleanupClass()
+bool LLWLParamManager::applySkyParams(const LLSD& params)
{
- delete sInstance;
- sInstance = NULL;
+ mAnimator.deactivate();
+ mCurParams.setAll(params);
+ return true;
}
void LLWLParamManager::resetAnimator(F32 curTime, bool run)
@@ -432,133 +502,227 @@ void LLWLParamManager::resetAnimator(F32 curTime, bool run)
return;
}
-bool LLWLParamManager::addParamSet(const std::string& name, LLWLParamSet& param)
+
+bool LLWLParamManager::addParamSet(const LLWLParamKey& key, LLWLParamSet& param)
{
// add a new one if not one there already
- std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
+ std::map<LLWLParamKey, LLWLParamSet>::iterator mIt = mParamList.find(key);
if(mIt == mParamList.end())
{
- mParamList[name] = param;
+ llassert(!key.name.empty());
+ // *TODO: validate params
+ mParamList[key] = param;
+ mPresetListChangeSignal();
return true;
}
return false;
}
-BOOL LLWLParamManager::addParamSet(const std::string& name, LLSD const & param)
+BOOL LLWLParamManager::addParamSet(const LLWLParamKey& key, LLSD const & param)
{
- // add a new one if not one there already
- std::map<std::string, LLWLParamSet>::const_iterator finder = mParamList.find(name);
- if(finder == mParamList.end())
- {
- mParamList[name].setAll(param);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ LLWLParamSet param_set;
+ param_set.setAll(param);
+ return addParamSet(key, param_set);
}
-bool LLWLParamManager::getParamSet(const std::string& name, LLWLParamSet& param)
+bool LLWLParamManager::getParamSet(const LLWLParamKey& key, LLWLParamSet& param)
{
// find it and set it
- std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
+ std::map<LLWLParamKey, LLWLParamSet>::iterator mIt = mParamList.find(key);
if(mIt != mParamList.end())
{
- param = mParamList[name];
- param.mName = name;
+ param = mParamList[key];
+ param.mName = key.name;
return true;
}
return false;
}
-bool LLWLParamManager::setParamSet(const std::string& name, LLWLParamSet& param)
+bool LLWLParamManager::hasParamSet(const LLWLParamKey& key)
{
- mParamList[name] = param;
+ LLWLParamSet dummy;
+ return getParamSet(key, dummy);
+}
+
+bool LLWLParamManager::setParamSet(const LLWLParamKey& key, LLWLParamSet& param)
+{
+ llassert(!key.name.empty());
+ // *TODO: validate params
+ mParamList[key] = param;
return true;
}
-bool LLWLParamManager::setParamSet(const std::string& name, const LLSD & param)
+bool LLWLParamManager::setParamSet(const LLWLParamKey& key, const LLSD & param)
{
+ llassert(!key.name.empty());
+ // *TODO: validate params
+
// quick, non robust (we won't be working with files, but assets) check
+ // this might not actually be true anymore....
if(!param.isMap())
{
return false;
}
- mParamList[name].setAll(param);
-
- return true;
+ LLWLParamSet param_set;
+ param_set.setAll(param);
+ return setParamSet(key, param_set);
}
-bool LLWLParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
+void LLWLParamManager::removeParamSet(const LLWLParamKey& key, bool delete_from_disk)
{
+ // *NOTE: Removing a sky preset invalidates day cycles that refer to it.
+
+ if (key.scope == LLEnvKey::SCOPE_REGION)
+ {
+ llwarns << "Removing region skies not supported" << llendl;
+ llassert(key.scope == LLEnvKey::SCOPE_LOCAL);
+ return;
+ }
+
// remove from param list
- std::map<std::string, LLWLParamSet>::iterator mIt = mParamList.find(name);
- if(mIt != mParamList.end())
+ std::map<LLWLParamKey, LLWLParamSet>::iterator it = mParamList.find(key);
+ if (it == mParamList.end())
{
- mParamList.erase(mIt);
+ LL_WARNS("WindLight") << "No sky preset named " << key.name << LL_ENDL;
+ return;
}
- F32 key;
+ mParamList.erase(it);
+ mDay.removeReferencesTo(key);
- // remove all references
- bool stat = true;
- do
+ // remove from file system if requested
+ if (delete_from_disk)
{
- // get it
- stat = mDay.getKey(name, key);
- if(stat == false)
+ std::string path_name(getUserDir());
+ std::string escaped_name = escapeString(key.name);
+
+ if(gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml") < 1)
{
- break;
+ LL_WARNS("WindLight") << "Error removing sky preset " << key.name << " from disk" << LL_ENDL;
}
+ }
- // and remove
- stat = mDay.removeKey(key);
+ // signal interested parties
+ mPresetListChangeSignal();
+}
- } while(stat == true);
-
- if(delete_from_disk)
+bool LLWLParamManager::isSystemPreset(const std::string& preset_name) const
+{
+ // *TODO: file system access is excessive here.
+ return gDirUtilp->fileExists(getSysDir() + escapeString(preset_name) + ".xml");
+}
+
+void LLWLParamManager::getPresetNames(preset_name_list_t& region, preset_name_list_t& user, preset_name_list_t& sys) const
+{
+ region.clear();
+ user.clear();
+ sys.clear();
+
+ for (std::map<LLWLParamKey, LLWLParamSet>::const_iterator it = mParamList.begin(); it != mParamList.end(); it++)
{
- std::string path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
-
- // use full curl escaped name
- char * curl_str = curl_escape(name.c_str(), name.size());
- std::string escaped_name(curl_str);
- curl_free(curl_str);
- curl_str = NULL;
-
- gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml");
- }
+ const LLWLParamKey& key = it->first;
+ const std::string& name = key.name;
- return true;
+ if (key.scope == LLEnvKey::SCOPE_REGION)
+ {
+ region.push_back(name);
+ }
+ else
+ {
+ if (isSystemPreset(name))
+ {
+ sys.push_back(name);
+ }
+ else
+ {
+ user.push_back(name);
+ }
+ }
+ }
}
+void LLWLParamManager::getUserPresetNames(preset_name_list_t& user) const
+{
+ preset_name_list_t region, sys; // unused
+ getPresetNames(region, user, sys);
+}
-// static
-LLWLParamManager * LLWLParamManager::instance()
+void LLWLParamManager::getPresetKeys(preset_key_list_t& keys) const
{
- if(NULL == sInstance)
+ keys.clear();
+
+ for (std::map<LLWLParamKey, LLWLParamSet>::const_iterator it = mParamList.begin(); it != mParamList.end(); it++)
{
- sInstance = new LLWLParamManager();
+ keys.push_back(it->first);
+ }
+}
+
+boost::signals2::connection LLWLParamManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb)
+{
+ return mPresetListChangeSignal.connect(cb);
+}
- sInstance->loadPresets(LLStringUtil::null);
+// virtual static
+void LLWLParamManager::initSingleton()
+{
+ LL_DEBUGS("Windlight") << "Initializing sky" << LL_ENDL;
+
+ loadAllPresets();
- // load the day
- sInstance->mDay.loadDayCycle(std::string("Default.xml"));
+ // load the day
+ std::string preferred_day = LLEnvManagerNew::instance().getDayCycleName();
+ if (!LLDayCycleManager::instance().getPreset(preferred_day, mDay))
+ {
+ // Fall back to default.
+ llwarns << "No day cycle named " << preferred_day << ", falling back to defaults" << llendl;
+ mDay.loadDayCycleFromFile("Default.xml");
- // *HACK - sets cloud scrolling to what we want... fix this better in the future
- sInstance->getParamSet("Default", sInstance->mCurParams);
+ // *TODO: Fix user preferences accordingly.
+ }
- // set it to noon
- sInstance->resetAnimator(0.5, true);
+ // *HACK - sets cloud scrolling to what we want... fix this better in the future
+ std::string sky = LLEnvManagerNew::instance().getSkyPresetName();
+ if (!getParamSet(LLWLParamKey(sky, LLWLParamKey::SCOPE_LOCAL), mCurParams))
+ {
+ llwarns << "No sky preset named " << sky << ", falling back to defaults" << llendl;
+ getParamSet(LLWLParamKey("Default", LLWLParamKey::SCOPE_LOCAL), mCurParams);
- // but use linden time sets it to what the estate is
- sInstance->mAnimator.mUseLindenTime = true;
+ // *TODO: Fix user preferences accordingly.
}
- return sInstance;
+ // set it to noon
+ resetAnimator(0.5, LLEnvManagerNew::instance().getUseDayCycle());
+
+ // but use linden time sets it to what the estate is
+ mAnimator.setTimeType(LLWLAnimator::TIME_LINDEN);
+
+ LLEnvManagerNew::instance().usePrefs();
+}
+
+// static
+std::string LLWLParamManager::getSysDir()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", "");
+}
+
+// static
+std::string LLWLParamManager::getUserDir()
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/skies", "");
+}
+
+// static
+std::string LLWLParamManager::escapeString(const std::string& str)
+{
+ // Don't use LLURI::escape() because it doesn't encode '-' characters
+ // which may break handling of some system presets like "A-12AM".
+ char* curl_str = curl_escape(str.c_str(), str.size());
+ std::string escaped_str(curl_str);
+ curl_free(curl_str);
+
+ return escaped_str;
}
diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h
index 8c6329e769..bc984b9126 100644
--- a/indra/newview/llwlparammanager.h
+++ b/indra/newview/llwlparammanager.h
@@ -27,12 +27,14 @@
#ifndef LL_WLPARAMMANAGER_H
#define LL_WLPARAMMANAGER_H
-#include <vector>
+#include <list>
#include <map>
+#include "llenvmanager.h"
#include "llwlparamset.h"
#include "llwlanimator.h"
#include "llwldaycycle.h"
#include "llviewercamera.h"
+#include "lltrans.h"
class LLGLSLShader;
@@ -72,7 +74,7 @@ struct WLColorControl {
r = val.mV[0];
g = val.mV[1];
b = val.mV[2];
- i = val.mV[3];
+ i = val.mV[3];
return *this;
}
@@ -115,25 +117,112 @@ struct WLFloatControl {
}
};
-/// WindLight parameter manager class - what controls all the wind light shaders
-class LLWLParamManager
+struct LLWLParamKey : LLEnvKey
{
public:
+ // scope and source of a param set (WL sky preset)
+ std::string name;
+ EScope scope;
- LLWLParamManager();
- ~LLWLParamManager();
+ // for conversion from LLSD
+ static const int NAME_IDX = 0;
+ static const int SCOPE_IDX = 1;
+
+ inline LLWLParamKey(const std::string& n, EScope s)
+ : name(n), scope(s)
+ {
+ }
+
+ inline LLWLParamKey(LLSD llsd)
+ : name(llsd[NAME_IDX].asString()), scope(EScope(llsd[SCOPE_IDX].asInteger()))
+ {
+ }
+
+ inline LLWLParamKey() // NOT really valid, just so std::maps can return a default of some sort
+ : name(""), scope(SCOPE_LOCAL)
+ {
+ }
+
+ inline LLWLParamKey(std::string& stringVal)
+ {
+ size_t len = stringVal.length();
+ if (len > 0)
+ {
+ name = stringVal.substr(0, len - 1);
+ scope = (EScope) atoi(stringVal.substr(len - 1, len).c_str());
+ }
+ }
+
+ inline std::string toStringVal() const
+ {
+ std::stringstream str;
+ str << name << scope;
+ return str.str();
+ }
+
+ inline LLSD toLLSD() const
+ {
+ LLSD llsd = LLSD::emptyArray();
+ llsd.append(LLSD(name));
+ llsd.append(LLSD(scope));
+ return llsd;
+ }
+
+ inline void fromLLSD(const LLSD& llsd)
+ {
+ name = llsd[NAME_IDX].asString();
+ scope = EScope(llsd[SCOPE_IDX].asInteger());
+ }
+
+ inline bool operator <(const LLWLParamKey other) const
+ {
+ if (name < other.name)
+ {
+ return true;
+ }
+ else if (name > other.name)
+ {
+ return false;
+ }
+ else
+ {
+ return scope < other.scope;
+ }
+ }
+
+ inline bool operator ==(const LLWLParamKey other) const
+ {
+ return (name == other.name) && (scope == other.scope);
+ }
- /// load a preset file
- void loadPresets(const std::string & fileName);
+ inline std::string toString() const
+ {
+ switch (scope)
+ {
+ case SCOPE_LOCAL:
+ return name + std::string(" (") + LLTrans::getString("Local") + std::string(")");
+ break;
+ case SCOPE_REGION:
+ return name + std::string(" (") + LLTrans::getString("Region") + std::string(")");
+ break;
+ default:
+ return name + " (?)";
+ }
+ }
+};
- /// save the preset file
- void savePresets(const std::string & fileName);
+/// WindLight parameter manager class - what controls all the wind light shaders
+class LLWLParamManager : public LLSingleton<LLWLParamManager>
+{
+ LOG_CLASS(LLWLParamManager);
- /// load an individual preset into the sky
- void loadPreset(const std::string & name,bool propogate=true);
+public:
+ typedef std::list<std::string> preset_name_list_t;
+ typedef std::list<LLWLParamKey> preset_key_list_t;
+ typedef boost::signals2::signal<void()> preset_list_signal_t;
/// save the parameter presets to file
- void savePreset(const std::string & name);
+ void savePreset(const LLWLParamKey key);
/// Set shader uniforms dirty, so they'll update automatically.
void propagateParameters(void);
@@ -147,6 +236,12 @@ public:
/// update information camera dependent parameters
void update(LLViewerCamera * cam);
+ /// apply specified day cycle, setting time to noon by default
+ bool applyDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time = 0.5);
+
+ /// apply specified fixed sky params
+ bool applySkyParams(const LLSD& params);
+
// get where the light is pointing
inline LLVector4 getLightDir(void) const;
@@ -161,36 +256,62 @@ public:
/// get the radius of the dome
inline F32 getDomeRadius(void) const;
-
- /// Perform global initialization for this class.
- static void initClass(void);
-
- // Cleanup of global data that's only inited once per class.
- static void cleanupClass();
- /// add a param to the list
- bool addParamSet(const std::string& name, LLWLParamSet& param);
+ /// add a param set (preset) to the list
+ bool addParamSet(const LLWLParamKey& key, LLWLParamSet& param);
- /// add a param to the list
- BOOL addParamSet(const std::string& name, LLSD const & param);
+ /// add a param set (preset) to the list
+ BOOL addParamSet(const LLWLParamKey& key, LLSD const & param);
- /// get a param from the list
- bool getParamSet(const std::string& name, LLWLParamSet& param);
+ /// get a param set (preset) from the list
+ bool getParamSet(const LLWLParamKey& key, LLWLParamSet& param);
+
+ /// check whether the preset is in the list
+ bool hasParamSet(const LLWLParamKey& key);
/// set the param in the list with a new param
- bool setParamSet(const std::string& name, LLWLParamSet& param);
+ bool setParamSet(const LLWLParamKey& key, LLWLParamSet& param);
/// set the param in the list with a new param
- bool setParamSet(const std::string& name, LLSD const & param);
+ bool setParamSet(const LLWLParamKey& key, LLSD const & param);
/// gets rid of a parameter and any references to it
- /// returns true if successful
- bool removeParamSet(const std::string& name, bool delete_from_disk);
+ /// ignores "delete_from_disk" if the scope is not local
+ void removeParamSet(const LLWLParamKey& key, bool delete_from_disk);
- // singleton pattern implementation
- static LLWLParamManager * instance();
+ /// clear parameter mapping of a given scope
+ void clearParamSetsOfScope(LLEnvKey::EScope scope);
-public:
+ /// @return true if the preset comes out of the box
+ bool isSystemPreset(const std::string& preset_name) const;
+
+ /// @return user and system preset names as a single list
+ void getPresetNames(preset_name_list_t& region, preset_name_list_t& user, preset_name_list_t& sys) const;
+
+ /// @return user preset names
+ void getUserPresetNames(preset_name_list_t& user) const;
+
+ /// @return keys of all known presets
+ void getPresetKeys(preset_key_list_t& keys) const;
+
+ /// Emitted when a preset gets added or deleted.
+ boost::signals2::connection setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb);
+
+ /// add all skies in LLSD using the given scope
+ void addAllSkies(LLEnvKey::EScope scope, const LLSD& preset_map);
+
+ /// refresh region-scope presets
+ void refreshRegionPresets();
+
+ // returns all skies referenced by the current day cycle (in mDay), with their final names
+ // side effect: applies changes to all internal structures! (trashes all unreferenced skies in scope, keys in day cycle rescoped to scope, etc.)
+ std::map<LLWLParamKey, LLWLParamSet> finalizeFromDayCycle(LLWLParamKey::EScope scope);
+
+ // returns all skies in map (intended to be called with output from a finalize)
+ static LLSD createSkyMap(std::map<LLWLParamKey, LLWLParamSet> map);
+
+ /// escape string in a way different from LLURI::escape()
+ static std::string escapeString(const std::string& str);
// helper variables
LLWLAnimator mAnimator;
@@ -243,14 +364,27 @@ public:
F32 mDomeOffset;
F32 mDomeRadius;
- // list of all the parameters, listed by name
- std::map<std::string, LLWLParamSet> mParamList;
-
-
+
private:
- // our parameter manager singleton instance
- static LLWLParamManager * sInstance;
+ friend class LLWLAnimator;
+
+ void loadAllPresets();
+ void loadPresetsFromDir(const std::string& dir);
+ bool loadPreset(const std::string& path);
+
+ static std::string getSysDir();
+ static std::string getUserDir();
+
+ friend class LLSingleton<LLWLParamManager>;
+ /*virtual*/ void initSingleton();
+ LLWLParamManager();
+ ~LLWLParamManager();
+
+ // list of all the parameters, listed by name
+ std::map<LLWLParamKey, LLWLParamSet> mParamList;
+
+ preset_list_signal_t mPresetListChangeSignal;
};
inline F32 LLWLParamManager::getDomeOffset(void) const
diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp
index cf06766d73..02d914a812 100644
--- a/indra/newview/llwlparamset.cpp
+++ b/indra/newview/llwlparamset.cpp
@@ -29,8 +29,8 @@
#include "llwlparamset.h"
#include "llwlanimator.h"
-#include "llfloaterwindlight.h"
#include "llwlparammanager.h"
+#include "llglslshader.h"
#include "lluictrlfactory.h"
#include "llsliderctrl.h"
@@ -94,7 +94,7 @@ void LLWLParamSet::update(LLGLSLShader * shader) const
shader->uniform4fv(param, 1, val.mV);
}
- else
+ else // param is the uniform name
{
LLVector4 val;
@@ -119,7 +119,6 @@ void LLWLParamSet::update(LLGLSLShader * shader) const
val.mV[0] = i->second.asBoolean();
}
-
shader->uniform4fv(param, 1, val.mV);
}
}
@@ -260,7 +259,6 @@ void LLWLParamSet::setEastAngle(float val)
void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)
{
// set up the iterators
- LLSD::map_iterator cIt = mParamValues.beginMap();
// keep cloud positions and coverage the same
/// TODO masking will do this later
@@ -273,55 +271,39 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)
LLSD srcVal;
LLSD destVal;
- // do the interpolation for all the ones saved as vectors
- // skip the weird ones
- for(; cIt != mParamValues.endMap(); cIt++) {
+ // Iterate through values
+ for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
+ {
- // check params to make sure they're actually there
- if(src.mParamValues.has(cIt->first))
+ // If param exists in both src and dest, set the holder variables, otherwise skip
+ if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))
{
- srcVal = src.mParamValues[cIt->first];
+ srcVal = src.mParamValues[iter->first];
+ destVal = dest.mParamValues[iter->first];
}
else
{
continue;
}
- if(dest.mParamValues.has(cIt->first))
+ if(iter->second.isReal()) // If it's a real, interpolate directly
{
- destVal = dest.mParamValues[cIt->first];
+ iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight);
}
- else
- {
- continue;
- }
-
- // skip if not a vector
- if(!cIt->second.isArray())
- {
- continue;
- }
-
- // only Real vectors allowed
- if(!cIt->second[0].isReal())
+ else if(iter->second.isArray() && iter->second[0].isReal() // If it's an array of reals, loop through the reals and interpolate on those
+ && iter->second.size() == srcVal.size() && iter->second.size() == destVal.size())
{
- continue;
+ // Actually do interpolation: old value + (difference in values * factor)
+ for(int i=0; i < iter->second.size(); ++i)
+ {
+ // iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal(); // old way of doing it -- equivalent but one more operation
+ iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight);
+ }
}
-
- // make sure all the same size
- if( cIt->second.size() != srcVal.size() ||
- cIt->second.size() != destVal.size())
+ else // Else, skip
{
continue;
- }
-
- // more error checking might be necessary;
-
- for(int i=0; i < cIt->second.size(); ++i)
- {
- cIt->second[i] = (1.0f - weight) * (F32) srcVal[i].asReal() +
- weight * (F32) destVal[i].asReal();
- }
+ }
}
// now mix the extra parameters
diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h
index 487e2bf922..3c44ed3bb8 100644
--- a/indra/newview/llwlparamset.h
+++ b/indra/newview/llwlparamset.h
@@ -32,10 +32,9 @@
#include "v4math.h"
#include "v4color.h"
-#include "llviewershadermgr.h"
-class LLFloaterWindLight;
class LLWLParamSet;
+class LLGLSLShader;
/// A class representing a set of parameter values for the WindLight shaders.
class LLWLParamSet {
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index ec24b02934..4a6ec7fdbb 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -61,6 +61,7 @@
#include <map>
#include <cstring>
+
//
// Globals
//
@@ -91,8 +92,7 @@ LLWorld::LLWorld() :
mLastPacketsIn(0),
mLastPacketsOut(0),
mLastPacketsLost(0),
- mSpaceTimeUSec(0),
- mClassicCloudsEnabled(TRUE)
+ mSpaceTimeUSec(0)
{
for (S32 i = 0; i < 8; i++)
{
@@ -183,10 +183,6 @@ LLViewerRegion* LLWorld::addRegion(const U64 &region_handle, const LLHost &host)
llerrs << "Unable to create new region!" << llendl;
}
- regionp->mCloudLayer.create(regionp);
- regionp->mCloudLayer.setWidth((F32)mWidth);
- regionp->mCloudLayer.setWindPointer(&regionp->mWind);
-
mRegionList.push_back(regionp);
mActiveRegionList.push_back(regionp);
mCulledRegionList.push_back(regionp);
@@ -661,92 +657,6 @@ void LLWorld::updateParticles()
LLViewerPartSim::getInstance()->updateSimulation();
}
-void LLWorld::updateClouds(const F32 dt)
-{
- static LLFastTimer::DeclareTimer ftm("World Clouds");
- LLFastTimer t(ftm);
-
- if ( gSavedSettings.getBOOL("FreezeTime") )
- {
- // don't move clouds in snapshot mode
- return;
- }
-
- if (
- mClassicCloudsEnabled !=
- gSavedSettings.getBOOL("SkyUseClassicClouds") )
- {
- // The classic cloud toggle has been flipped
- // gotta update all of the cloud layers
- mClassicCloudsEnabled =
- gSavedSettings.getBOOL("SkyUseClassicClouds");
-
- if ( !mClassicCloudsEnabled && mActiveRegionList.size() )
- {
- // We've transitioned to having classic clouds disabled
- // reset all cloud layers.
- for (
- region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end();
- ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->mCloudLayer.reset();
- }
-
- return;
- }
- }
- else if ( !mClassicCloudsEnabled ) return;
-
- if (mActiveRegionList.size())
- {
- for (region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->mCloudLayer.updatePuffs(dt);
- }
-
- // Reshuffle who owns which puffs
- for (region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->mCloudLayer.updatePuffOwnership();
- }
-
- // Add new puffs
- for (region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->mCloudLayer.updatePuffCount();
- }
- }
-}
-
-LLCloudGroup* LLWorld::findCloudGroup(const LLCloudPuff &puff)
-{
- if (mActiveRegionList.size())
- {
- // Update all the cloud puff positions, and timer based stuff
- // such as death decay
- for (region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- LLCloudGroup *groupp = regionp->mCloudLayer.findCloudGroup(puff);
- if (groupp)
- {
- return groupp;
- }
- }
- }
- return NULL;
-}
-
-
void LLWorld::renderPropertyLines()
{
S32 region_count = 0;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index f64eb89866..e74bf2a620 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -392,6 +392,7 @@ void LLPipeline::init()
{
LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
+ gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
@@ -580,11 +581,6 @@ void LLPipeline::allocatePhysicsBuffer()
if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY)
{
mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
- if (mSampleBuffer.getWidth() == mPhysicsDisplay.getWidth() &&
- mSampleBuffer.getHeight() == mPhysicsDisplay.getHeight())
- {
- mPhysicsDisplay.setSampleBuffer(&mSampleBuffer);
- }
}
}
@@ -594,8 +590,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
mScreenWidth = resX;
mScreenHeight = resY;
- //never use more than 4 samples for render targets
- U32 samples = llmin(gSavedSettings.getU32("RenderFSAASamples"), (U32) 4);
+ //cap samples at 4 for render targets to avoid out of memory errors
+ U32 samples = gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"));
+
if (gGLManager.mIsATI)
{ //disable multisampling of render targets where ATI is involved
samples = 0;
@@ -621,16 +618,22 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
bool gi = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED);
//allocate deferred rendering color buffers
- mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
- mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
+ mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
addDeferredAttachments(mDeferredScreen);
- mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples);
+
+#if LL_DARWIN
+ // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
+ mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+#else
mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+#endif
if (shadow_detail > 0 || ssao)
{ //only need mDeferredLight[0] for shadows OR ssao
- mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
}
else
{
@@ -639,7 +642,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
if (ssao)
{ //only need mDeferredLight[1] for ssao
- mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false);
}
else
{
@@ -648,10 +651,15 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
if (gi)
{ //only need mDeferredLight[2] and mGIMapPost for gi
- mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, false);
for (U32 i = 0; i < 2; i++)
{
+#if LL_DARWIN
+ // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
+ mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+#else
mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+#endif
}
}
else
@@ -666,8 +674,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
+#if LL_DARWIN
+ U32 shadow_fmt = 0;
+#else
//HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug)
U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0;
+#endif
if (shadow_detail > 0)
{ //allocate 4 sun shadow maps
@@ -729,35 +741,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
}
- if (LLRenderTarget::sUseFBO && samples > 1)
- {
- mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
- if (LLPipeline::sRenderDeferred)
- {
- addDeferredAttachments(mSampleBuffer);
- mDeferredScreen.setSampleBuffer(&mSampleBuffer);
- mEdgeMap.setSampleBuffer(&mSampleBuffer);
- }
-
- mScreen.setSampleBuffer(&mSampleBuffer);
-
- stop_glerror();
- }
- else
- {
- mSampleBuffer.release();
- }
-
if (LLPipeline::sRenderDeferred)
{ //share depth buffer between deferred targets
mDeferredScreen.shareDepthBuffer(mScreen);
- for (U32 i = 0; i < 3; i++)
- { //share stencil buffer with screen space lightmap to stencil out sky
- if (mDeferredLight[i].getTexture(0))
- {
- mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
- }
- }
}
gGL.getTexUnit(0)->disable();
@@ -787,16 +773,7 @@ void LLPipeline::updateRenderDeferred()
//static
void LLPipeline::refreshRenderDeferred()
{
- if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
- {
- //turn the deferred rendering and glow off when draw physics shapes.
- sRenderDeferred = FALSE ;
- sRenderGlow = FALSE ;
- }
- else
- {
- updateRenderDeferred() ;
- }
+ updateRenderDeferred();
}
void LLPipeline::releaseGLBuffers()
@@ -826,7 +803,6 @@ void LLPipeline::releaseGLBuffers()
mScreen.release();
mPhysicsDisplay.release();
mUIScreen.release();
- mSampleBuffer.release();
mDeferredScreen.release();
mDeferredDepth.release();
for (U32 i = 0; i < 3; i++)
@@ -2535,6 +2511,32 @@ void LLPipeline::markGLRebuild(LLGLUpdate* glu)
}
}
+void LLPipeline::markPartitionMove(LLDrawable* drawable)
+{
+ if (!drawable->isState(LLDrawable::PARTITION_MOVE) &&
+ !drawable->getPositionGroup().equals3(LLVector4a::getZero()))
+ {
+ drawable->setState(LLDrawable::PARTITION_MOVE);
+ mPartitionQ.push_back(drawable);
+ }
+}
+
+void LLPipeline::processPartitionQ()
+{
+ for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter)
+ {
+ LLDrawable* drawable = *iter;
+ if (!drawable->isDead())
+ {
+ drawable->updateBinRadius();
+ drawable->movePartition();
+ }
+ drawable->clearState(LLDrawable::PARTITION_MOVE);
+ }
+
+ mPartitionQ.clear();
+}
+
void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
@@ -3595,7 +3597,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
if (gDebugGL)
{
check_stack_depth(stack_depth);
- std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i);
+ std::string msg = llformat("pass %d", i);
LLGLState::checkStates(msg);
LLGLState::checkTextureChannels(msg);
LLGLState::checkClientArrays(msg);
@@ -4070,6 +4072,37 @@ void LLPipeline::renderDebug()
bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD);
+ if (!hud_only && !mDebugBlips.empty())
+ { //render debug blips
+ glPointSize(8.f);
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+
+ gGL.begin(LLRender::POINTS);
+ for (std::list<DebugBlip>::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); )
+ {
+ DebugBlip& blip = *iter;
+
+ blip.mAge += gFrameIntervalSeconds;
+ if (blip.mAge > 2.f)
+ {
+ mDebugBlips.erase(iter++);
+ }
+ else
+ {
+ iter++;
+ }
+
+ blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f;
+
+ gGL.color4fv(blip.mColor.mV);
+ gGL.vertex3fv(blip.mPosition.mV);
+ }
+ gGL.end();
+ gGL.flush();
+ glPointSize(1.f);
+ }
+
+
// Debug stuff.
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -5904,7 +5937,6 @@ LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
return NULL;
}
-
void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
{
if (!drawable || drawable->isDead())
@@ -6050,7 +6082,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
{
LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
if (!(gPipeline.canUseVertexShaders() &&
- sRenderGlow))
+ sRenderGlow) ||
+ (!sRenderDeferred && hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)))
{
return;
}
@@ -6096,67 +6129,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.setColorMask(true, true);
glClearColor(0,0,0,0);
-
- /*if (for_snapshot)
- {
- gGL.getTexUnit(0)->bind(&mGlow[1]);
- {
- //LLGLEnable stencil(GL_STENCIL_TEST);
- //glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
- //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- //LLGLDisable blend(GL_BLEND);
-
- // If the snapshot is constructed from tiles, calculate which
- // tile we're in.
-
- //from LLViewerCamera::setPerpsective
- if (zoom_factor > 1.f)
- {
- int pos_y = subfield / llceil(zoom_factor);
- int pos_x = subfield - (pos_y*llceil(zoom_factor));
- F32 size = 1.f/zoom_factor;
-
- tc1.set(pos_x*size, pos_y*size);
- tc2 = tc1 + LLVector2(size,size);
- }
- else
- {
- tc2.set(1,1);
- }
-
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_ADD);
-
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.color4f(1,1,1,1);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,1);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(1,-1);
-
- gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
- gGL.vertex2f(1,1);
-
- gGL.end();
-
- gGL.flush();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-
- gGL.flush();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- return;
- }*/
-
+
{
{
LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
@@ -6180,11 +6153,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->disable();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
- gGL.getTexUnit(0)->bind(&mScreen);
-
+ mScreen.bindTexture(0, 0);
+
gGL.color4f(1,1,1,1);
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
gGL.begin(LLRender::TRIANGLE_STRIP);
@@ -6199,7 +6169,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.end();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->unbind(mScreen.getUsage());
mGlow[2].flush();
}
@@ -6227,7 +6197,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
for (S32 i = 0; i < kernel; i++)
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
{
LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
mGlow[i%2].bindTarget();
@@ -6288,9 +6257,9 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
LLVertexBuffer::unbind();
- if (LLPipeline::sRenderDeferred && !LLViewerCamera::getInstance()->cameraUnderWater())
+ if (LLPipeline::sRenderDeferred)
{
- bool dof_enabled = true;
+ bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater();
LLGLSLShader* shader = &gDeferredPostProgram;
if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
@@ -6298,7 +6267,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
shader = &gDeferredGIFinalProgram;
dof_enabled = false;
}
- else if (LLToolMgr::getInstance()->inBuildMode() || !gSavedSettings.getBOOL("RenderDepthOfField"))
+ else if (!dof_enabled || LLToolMgr::getInstance()->inBuildMode() || !gSavedSettings.getBOOL("RenderDepthOfField"))
{ //squish focal length when in build mode (or if DoF is disabled) so DoF doesn't make editing objects difficult
shader = &gDeferredPostNoDoFProgram;
dof_enabled = false;
@@ -6420,11 +6389,10 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
shader->uniform1f("magnification", magnification);
}
- S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
if (channel > -1)
{
mScreen.bindTexture(0, channel);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
}
//channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
//if (channel > -1)
@@ -6517,6 +6485,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
{
+ gGL.setColorMask(true, false);
+
LLVector2 tc1(0,0);
LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
(F32) gViewerWindow->getWorldViewHeightRaw()*2);
@@ -6563,25 +6533,23 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
noise_map = mNoiseMap;
}
- LLGLState::checkTextureChannels();
-
shader.bind();
S32 channel = 0;
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
if (channel > -1)
{
mDeferredScreen.bindTexture(0,channel);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
if (channel > -1)
{
mDeferredScreen.bindTexture(1, channel);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
if (channel > -1)
{
mDeferredScreen.bindTexture(2, channel);
@@ -6704,22 +6672,16 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m);
}
}
-
- /*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
- if (channel > -1)
- {
- mDeferredScreen.bindTexture(3, channel);
- }*/
+ stop_glerror();
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
if (channel > -1)
{
gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
- glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
- glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
+ //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
stop_glerror();
@@ -6748,7 +6710,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
stop_glerror();
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, mDeferredLight[light_index].getUsage());
if (channel > -1)
{
mDeferredLight[light_index].bindTexture(0, channel);
@@ -6968,9 +6930,9 @@ void LLPipeline::renderDeferredLighting()
}
//ati doesn't seem to love actually using the stencil buffer on FBO's
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+ //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gGL.setColorMask(true, true);
@@ -7772,33 +7734,41 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
LLViewerTexture* img = volume->getLightTexture();
+ if (img == NULL)
+ {
+ img = LLViewerFetchedTexture::sWhiteImagep;
+ }
+
S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
- if (channel > -1 && img)
+ if (channel > -1)
{
- gGL.getTexUnit(channel)->bind(img);
+ if (img)
+ {
+ gGL.getTexUnit(channel)->bind(img);
- F32 lod_range = logf(img->getWidth())/logf(2.f);
+ F32 lod_range = logf(img->getWidth())/logf(2.f);
- shader.uniform1f("proj_focus", focus);
- shader.uniform1f("proj_lod", lod_range);
- shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+ shader.uniform1f("proj_focus", focus);
+ shader.uniform1f("proj_lod", lod_range);
+ shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+ }
}
+
}
void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
stop_glerror();
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, mDeferredLight[0].getUsage());
shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
- shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, mEdgeMap.getUsage());
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, mDeferredLight[1].getUsage());
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, mDeferredLight[2].getUsage());
shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP);
@@ -7845,8 +7815,6 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->activate();
shader.unbind();
-
- LLGLState::checkTextureChannels();
}
inline float sgn(float a)
@@ -9394,6 +9362,11 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadow[i+4].flush();
}
}
+ else
+ { //no spotlight shadows
+ mShadowSpotLight[0] = mShadowSpotLight[1] = NULL;
+ }
+
if (!gSavedSettings.getBOOL("CameraOffset"))
{
@@ -9816,4 +9789,9 @@ void LLPipeline::clearRenderTypeMask(U32 type, ...)
}
}
+void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color)
+{
+ DebugBlip blip(position, color);
+ mDebugBlips.push_back(blip);
+}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index e9a250cd6d..e9da25e544 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -157,7 +157,8 @@ public:
void markGLRebuild(LLGLUpdate* glu);
void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE);
void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);
-
+ void markPartitionMove(LLDrawable* drawablep);
+
//get the object between start and end that's closest to start.
LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
BOOL pick_transparent,
@@ -211,6 +212,7 @@ public:
void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane
void createObjects(F32 max_dtime);
void createObject(LLViewerObject* vobj);
+ void processPartitionQ();
void updateGeom(F32 max_dtime);
void updateGL();
void rebuildPriorityGroups();
@@ -358,6 +360,8 @@ public:
static void updateRenderDeferred();
static void refreshRenderDeferred();
+ void addDebugBlip(const LLVector3& position, const LLColor4& color);
+
private:
void unloadShaders();
void addToQuickLookup( LLDrawPool* new_poolp );
@@ -524,7 +528,6 @@ public:
LLRenderTarget mEdgeMap;
LLRenderTarget mDeferredDepth;
LLRenderTarget mDeferredLight[3];
- LLMultisampleBuffer mSampleBuffer;
LLRenderTarget mGIMap;
LLRenderTarget mGIMapPost[2];
LLRenderTarget mLuminanceMap;
@@ -637,6 +640,9 @@ protected:
LLDrawable::drawable_list_t mBuildQ2; // non-priority
LLSpatialGroup::sg_vector_t mGroupQ1; //priority
LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority
+
+ LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius
+
bool mGroupQ2Locked;
bool mGroupQ1Locked;
@@ -726,6 +732,20 @@ public:
protected:
std::vector<LLFace*> mSelectedFaces;
+ class DebugBlip
+ {
+ public:
+ LLColor4 mColor;
+ LLVector3 mPosition;
+ F32 mAge;
+
+ DebugBlip(const LLVector3& position, const LLColor4& color)
+ : mColor(color), mPosition(position), mAge(0.f)
+ { }
+ };
+
+ std::list<DebugBlip> mDebugBlips;
+
LLPointer<LLViewerFetchedTexture> mFaceSelectImagep;
U32 mLightMask;
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index d02662681b..76965ad14b 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -133,6 +133,15 @@
name="AvatarListItemIconVoiceLeftColor"
reference="AvatarListItemIconOfflineColor" />
<color
+ name="BadgeImageColor"
+ value="0.44 0.69 0.56 1.0" />
+ <color
+ name="BadgeBorderColor"
+ value="0.9 0.9 0.9 1.0" />
+ <color
+ name="BadgeLabelColor"
+ reference="White" />
+ <color
name="ButtonBorderColor"
reference="Unused?" />
<color
@@ -500,22 +509,22 @@
reference="DkGray2" />
<color
name="MultiSliderDisabledThumbColor"
- reference="Unused?" />
+ reference="Black" />
<color
name="MultiSliderThumbCenterColor"
- reference="Unused?" />
+ reference="White" />
<color
name="MultiSliderThumbCenterSelectedColor"
- reference="Unused?" />
+ reference="Green" />
<color
name="MultiSliderThumbOutlineColor"
reference="Unused?" />
<color
name="MultiSliderTrackColor"
- reference="Unused?" />
+ reference="LtGray" />
<color
name="MultiSliderTriangleColor"
- reference="Unused?" />
+ reference="Yellow" />
<!--
<color
name="NameTagBackground"
@@ -760,7 +769,7 @@
<color
name="MenuBarProjectBgColor"
reference="MdBlue" />
-
+
<color
name="MeshImportTableNormalColor"
value="1 1 1 1"/>
@@ -768,6 +777,9 @@
name="MeshImportTableHighlightColor"
value="0.2 0.8 1 1"/>
+ <color
+ name="DirectChatColor"
+ reference="LtOrange" />
<!-- Generic color names (legacy) -->
<color
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gift.png b/indra/newview/skins/default/textures/icons/Inv_Gift.png
new file mode 100644
index 0000000000..5afe85d72d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Gift.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png
new file mode 100644
index 0000000000..be58114aa1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Off.png b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png
new file mode 100644
index 0000000000..e6b9480ab1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On.png b/indra/newview/skins/default/textures/icons/OutboxPush_On.png
new file mode 100644
index 0000000000..ffda2e92d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png
new file mode 100644
index 0000000000..6b5911014f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png
new file mode 100644
index 0000000000..0e60b417b0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png
new file mode 100644
index 0000000000..9c26b92e73
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png
new file mode 100644
index 0000000000..3b5d462975
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png
new file mode 100644
index 0000000000..f85be047b0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png
new file mode 100644
index 0000000000..cd4e482216
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png
new file mode 100644
index 0000000000..d212a871ce
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png
new file mode 100644
index 0000000000..e5b6023e36
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png
new file mode 100644
index 0000000000..e1911a092f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png
new file mode 100644
index 0000000000..9e59f7843a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png
new file mode 100644
index 0000000000..51e8bff646
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png
new file mode 100644
index 0000000000..300e2e69e1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png
new file mode 100644
index 0000000000..32fb236381
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png
new file mode 100644
index 0000000000..827f343b1e
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Dark.png
new file mode 100644
index 0000000000..956e02b14d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Light.png b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Light.png
new file mode 100644
index 0000000000..434caeda8b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOff_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Dark.png b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Dark.png
new file mode 100644
index 0000000000..064687ed0f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Dark.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Light.png b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Light.png
new file mode 100644
index 0000000000..5465650d0c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Parcel_SeeAVsOn_Light.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Disabled.png b/indra/newview/skins/default/textures/icons/Sync_Disabled.png
new file mode 100644
index 0000000000..ca2e8def97
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Enabled.png b/indra/newview/skins/default/textures/icons/Sync_Enabled.png
new file mode 100644
index 0000000000..bc236c8b98
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Enabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_1.png b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png
new file mode 100644
index 0000000000..624e556376
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_2.png b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png
new file mode 100644
index 0000000000..5769803b3f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_3.png b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png
new file mode 100644
index 0000000000..92d4bfb020
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_4.png b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png
new file mode 100644
index 0000000000..6d43eb3a9f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_5.png b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png
new file mode 100644
index 0000000000..766d063c99
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_6.png b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png
new file mode 100644
index 0000000000..dfe7f68b72
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index cc7cce99c9..799cd907dc 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -1,4 +1,4 @@
-<!--
+<!--
This file contains metadata about how to load, display, and scale textures for rendering in the UI.
Images do *NOT* have to appear in this file in order to use them as textures in the UI...simply refer
to them by filename (relative to textures directory).
@@ -72,8 +72,11 @@ with the same filename but different name
<texture name="BackButton_Over" file_name="icons/back_arrow_over.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
<texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
+ <texture name="Badge_Background" file_name="widgets/Badge_Background.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="Badge_Border" file_name="widgets/Badge_Border.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
<texture name="Blank" file_name="Blank.png" preload="false" />
-
+
<texture name="BreadCrumbBtn_Left_Disabled" file_name="widgets/BreadCrumbBtn_Left_Disabled.png" preload="false"/>
<texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/>
<texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/>
@@ -88,7 +91,6 @@ with the same filename but different name
<texture name="BreadCrumbBtn_Right_Off" file_name="widgets/BreadCrumbBtn_Right_Off.png" preload="false"/>
<texture name="BreadCrumbBtn_Right_Over" file_name="widgets/BreadCrumbBtn_Right_Over.png" preload="false"/>
<texture name="BreadCrumbBtn_Right_Press" file_name="widgets/BreadCrumbBtn_Right_Press.png" preload="false"/>
-
<texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="0" scale.top="1" scale.right="0" scale.bottom="0" />
<texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
@@ -266,6 +268,8 @@ with the same filename but different name
<texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" />
+ <texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
+ <texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
<texture name="Microphone_On" file_name="icons/Microphone_On.png" preload="false" />
@@ -349,6 +353,23 @@ with the same filename but different name
<texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
<texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
+ <texture name="OutboxPush_Disabled" file_name="icons/OutboxPush_Disabled.png" preload="true" />
+ <texture name="OutboxPush_Off" file_name="icons/OutboxPush_Off.png" preload="true" />
+ <texture name="OutboxPush_On" file_name="icons/OutboxPush_On.png" preload="true" />
+ <texture name="OutboxPush_On_Over" file_name="icons/OutboxPush_On_Over.png" preload="true" />
+ <texture name="OutboxPush_Over" file_name="icons/OutboxPush_Over.png" preload="true" />
+ <texture name="OutboxPush_Press" file_name="icons/OutboxPush_Press.png" preload="true" />
+ <texture name="OutboxPush_Progress_1" file_name="icons/OutboxPush_Progress_1.png" preload="true" />
+ <texture name="OutboxPush_Progress_2" file_name="icons/OutboxPush_Progress_2.png" preload="true" />
+ <texture name="OutboxPush_Progress_3" file_name="icons/OutboxPush_Progress_3.png" preload="true" />
+ <texture name="OutboxPush_Progress_4" file_name="icons/OutboxPush_Progress_4.png" preload="true" />
+ <texture name="OutboxPush_Progress_5" file_name="icons/OutboxPush_Progress_5.png" preload="true" />
+ <texture name="OutboxPush_Progress_6" file_name="icons/OutboxPush_Progress_6.png" preload="true" />
+ <texture name="OutboxPush_Selected" file_name="icons/OutboxPush_Selected.png" preload="true" />
+ <texture name="OutboxPush_Selected_Disabled" file_name="icons/OutboxPush_Selected_Disabled.png" preload="true" />
+ <texture name="OutboxPush_Selected_Over" file_name="icons/OutboxPush_Selected_Over.png" preload="true" />
+ <texture name="OutboxPush_Selected_Press" file_name="icons/OutboxPush_Selected_Press.png" preload="true" />
+
<texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" />
<texture name="Parcel_Exp_Color" file_name="icons/Parcel_Exp_Color.png" preload="false" />
@@ -369,6 +390,10 @@ with the same filename but different name
<texture name="Parcel_ScriptsNo_Dark" file_name="icons/Parcel_ScriptsNo_Dark.png" preload="false" />
<texture name="Parcel_Voice_Dark" file_name="icons/Parcel_Voice_Dark.png" preload="false" />
<texture name="Parcel_VoiceNo_Dark" file_name="icons/Parcel_VoiceNo_Dark.png" preload="false" />
+ <texture name="Parcel_SeeAVsOff_Dark" file_name="icons/Parcel_SeeAVsOff_Dark.png" preload="false" />
+ <texture name="Parcel_SeeAVsOn_Dark" file_name="icons/Parcel_SeeAVsOn_Dark.png" preload="false" />
+ <texture name="Parcel_SeeAVsOff_Light" file_name="icons/Parcel_SeeAVsOff_Light.png" preload="false" />
+ <texture name="Parcel_SeeAVsOn_Light" file_name="icons/Parcel_SeeAVsOn_Light.png" preload="false" />
<texture name="Parcel_BuildNo_Light" file_name="icons/Parcel_BuildNo_Light.png" preload="false" />
<texture name="Parcel_FlyNo_Light" file_name="icons/Parcel_FlyNo_Light.png" preload="false" />
@@ -496,6 +521,15 @@ with the same filename but different name
<texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
<texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
+ <texture name="Sync_Disabled" file_name="icons/Sync_Disabled.png" preload="true" />
+ <texture name="Sync_Enabled" file_name="icons/Sync_Enabled.png" preload="true" />
+ <texture name="Sync_Progress_1" file_name="icons/Sync_Progress_1.png" preload="true" />
+ <texture name="Sync_Progress_2" file_name="icons/Sync_Progress_2.png" preload="true" />
+ <texture name="Sync_Progress_3" file_name="icons/Sync_Progress_3.png" preload="true" />
+ <texture name="Sync_Progress_4" file_name="icons/Sync_Progress_4.png" preload="true" />
+ <texture name="Sync_Progress_5" file_name="icons/Sync_Progress_5.png" preload="true" />
+ <texture name="Sync_Progress_6" file_name="icons/Sync_Progress_6.png" preload="true" />
+
<texture name="TabIcon_Appearance_Off" file_name="taskpanel/TabIcon_Appearance_Off.png" preload="false" />
<texture name="TabIcon_Appearance_Selected" file_name="taskpanel/TabIcon_Appearance_Selected.png" preload="false" />
<texture name="TabIcon_Close_Off" file_name="taskpanel/TabIcon_Close_Off.png" preload="false" />
@@ -649,6 +683,7 @@ with the same filename but different name
<texture name="inv_folder_mesh.tga"/>
<texture name="inv_item_mesh.tga"/>
+
<texture name="lag_status_critical.tga" />
<texture name="lag_status_good.tga" />
<texture name="lag_status_warning.tga" />
diff --git a/indra/newview/skins/default/textures/widgets/Badge_Background.png b/indra/newview/skins/default/textures/widgets/Badge_Background.png
new file mode 100644
index 0000000000..5089c30312
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Badge_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Badge_Border.png b/indra/newview/skins/default/textures/widgets/Badge_Border.png
new file mode 100644
index 0000000000..4b086a63fb
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Badge_Border.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
new file mode 100644
index 0000000000..e603c44384
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
new file mode 100644
index 0000000000..fbc164123f
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 317c6fe9ac..e00586811b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2931,6 +2931,18 @@
function="Floater.Toggle"
parameter="region_debug_console" />
</menu_item_check>
+ <menu_item_check
+ label="Region Debug Console"
+ name="Region Debug Console"
+ shortcut="control|shift|`"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="region_debug_console" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="region_debug_console" />
+ </menu_item_check>
<menu_item_separator />
<menu_item_check
diff --git a/indra/newview/tests/lldir_stub.cpp b/indra/newview/tests/lldir_stub.cpp
new file mode 100644
index 0000000000..6646860b5e
--- /dev/null
+++ b/indra/newview/tests/lldir_stub.cpp
@@ -0,0 +1,45 @@
+/**
+ * @file lldir_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Use me only if you need to stub out some helper functions, not if you e.g. need sane numbers from countFilesInDir
+
+LLDir::LLDir() {}
+LLDir::~LLDir() {}
+BOOL LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) { return true; }
+void LLDir::setChatLogsDir(const std::string &path) {}
+void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last) {}
+void LLDir::setLindenUserDir(const std::string &first, const std::string &last) {}
+void LLDir::setSkinFolder(const std::string &skin_folder) {}
+bool LLDir::setCacheDir(const std::string &path) { return true; }
+void LLDir::dumpCurrentDirectories() {}
+
+class LLDir_stub : public LLDir
+{
+public:
+ LLDir_stub() {}
+ ~LLDir_stub() {}
+
+ /*virtual*/ void initAppDirs(const std::string &app_name) {}
+
+ /*virtual*/ std::string getCurPath() { return "CUR_PATH_FROM_LLDIR"; }
+ /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask) { return 42; }
+ /*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) { fname = fname + "_NEXT"; return false; }
+ /*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) { fname = "RANDOM_FILE"; }
+ /*virtual*/ BOOL fileExists(const std::string &filename) const { return false; }
+};
+
+LLDir_stub gDirUtil;
+
+LLDir* gDirUtilp = &gDirUtil;
+
+std::string LLDir::getExpandedFilename(ELLPath loc, const std::string& subdir, const std::string& filename) const
+{
+ return subdir + " --- " + filename + " --- expanded!";
+}
+
diff --git a/indra/newview/tests/llglslshader_stub.cpp b/indra/newview/tests/llglslshader_stub.cpp
new file mode 100644
index 0000000000..5333c8a361
--- /dev/null
+++ b/indra/newview/tests/llglslshader_stub.cpp
@@ -0,0 +1,22 @@
+/**
+ * @file llglslshader_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "llglslshader.h"
+
+void LLGLSLShader::uniform1f(const std::string& uniform, F32 num)
+{
+}
+
+void LLGLSLShader::uniform3fv(const std::string& uniform, U32 count, const GLfloat *v)
+{
+}
+
+void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
+{
+}
diff --git a/indra/newview/tests/llpipeline_stub.cpp b/indra/newview/tests/llpipeline_stub.cpp
new file mode 100644
index 0000000000..85bf0ae3fb
--- /dev/null
+++ b/indra/newview/tests/llpipeline_stub.cpp
@@ -0,0 +1,15 @@
+/**
+ * @file llpipeline_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+class LLPipeline
+{
+public: BOOL canUseWindLightShaders() const;
+};
+BOOL LLPipeline::canUseWindLightShaders() const {return TRUE;}
+LLPipeline gPipeline;
diff --git a/indra/newview/tests/llsky_stub.cpp b/indra/newview/tests/llsky_stub.cpp
new file mode 100644
index 0000000000..35f4944a95
--- /dev/null
+++ b/indra/newview/tests/llsky_stub.cpp
@@ -0,0 +1,20 @@
+/**
+ * @file llsky_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+class LLSky
+{
+public:
+ void setOverrideSun(BOOL override);
+ void setSunDirection(const LLVector3 &sun_direction, const LLVector3 &sun_ang_velocity);
+};
+
+void LLSky::setOverrideSun(BOOL override) {}
+void LLSky::setSunDirection(const LLVector3 &sun_direction, const LLVector3 &sun_ang_velocity) {}
+
+LLSky gSky;
diff --git a/indra/newview/tests/llviewershadermgr_stub.cpp b/indra/newview/tests/llviewershadermgr_stub.cpp
new file mode 100644
index 0000000000..0dae527035
--- /dev/null
+++ b/indra/newview/tests/llviewershadermgr_stub.cpp
@@ -0,0 +1,33 @@
+/**
+ * @file llglslshader_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "../llviewershadermgr.h"
+
+LLShaderMgr::LLShaderMgr() {}
+LLShaderMgr::~LLShaderMgr() {}
+
+LLViewerShaderMgr::LLViewerShaderMgr() {}
+LLViewerShaderMgr::~LLViewerShaderMgr() {}
+
+LLViewerShaderMgr* stub_instance = NULL;
+
+LLViewerShaderMgr* LLViewerShaderMgr::instance() {
+ if(NULL == stub_instance)
+ {
+ stub_instance = new LLViewerShaderMgr();
+ }
+
+ return stub_instance;
+}
+LLViewerShaderMgr::shader_iter fake_iter;
+LLViewerShaderMgr::shader_iter LLViewerShaderMgr::beginShaders() const {return fake_iter;}
+LLViewerShaderMgr::shader_iter LLViewerShaderMgr::endShaders() const {return fake_iter;}
+
+void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader* shader) {return;}
+std::string LLViewerShaderMgr::getShaderDirPrefix() {return "SHADER_DIR_PREFIX-";}
diff --git a/indra/newview/tests/llwlanimator_stub.cpp b/indra/newview/tests/llwlanimator_stub.cpp
new file mode 100644
index 0000000000..4d1bb85544
--- /dev/null
+++ b/indra/newview/tests/llwlanimator_stub.cpp
@@ -0,0 +1,12 @@
+/**
+ * @file llwlanimator_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+LLWLAnimator::LLWLAnimator(void) {}
+void LLWLAnimator::update(LLWLParamSet& set) {}
+void LLWLAnimator::setTrack(std::map<F32, LLWLParamKey>& track, F32 dayRate, F64 dayTime, bool run) {}
diff --git a/indra/newview/tests/llwldaycycle_stub.cpp b/indra/newview/tests/llwldaycycle_stub.cpp
new file mode 100644
index 0000000000..d98c9614b4
--- /dev/null
+++ b/indra/newview/tests/llwldaycycle_stub.cpp
@@ -0,0 +1,35 @@
+/**
+ * @file llwldaycycle_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+LLWLDayCycle::LLWLDayCycle(void)
+{
+}
+
+LLWLDayCycle::~LLWLDayCycle(void)
+{
+}
+
+bool LLWLDayCycle::getKeytime(LLWLParamKey keyFrame, F32& keyTime)
+{
+ keyTime = 0.5;
+ return true;
+}
+
+bool LLWLDayCycle::removeKeyframe(F32 time)
+{
+ return true;
+}
+
+void LLWLDayCycle::loadDayCycleFromFile(const std::string& fileName)
+{
+}
+
+void LLWLDayCycle::removeReferencesTo(const LLWLParamKey &keyframe)
+{
+}
diff --git a/indra/newview/tests/llwlparammanager_test.cpp b/indra/newview/tests/llwlparammanager_test.cpp
new file mode 100644
index 0000000000..a6c6a2abf4
--- /dev/null
+++ b/indra/newview/tests/llwlparammanager_test.cpp
@@ -0,0 +1,254 @@
+/**
+ * @file llwlparammanager_test.cpp
+ * @brief LLWLParamManager tests
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled headers
+#include "../llviewerprecompiledheaders.h"
+
+// Class to test
+#include "../llwlparammanager.h"
+
+// Dependencies
+#include "linden_common.h"
+
+// TUT header
+#include "lltut.h"
+
+// Stubs
+#include "llwldaycycle_stub.cpp"
+#include "llwlparamset_stub.cpp"
+#include "llwlanimator_stub.cpp"
+#include "llglslshader_stub.cpp"
+#include "lldir_stub.cpp"
+#include "llsky_stub.cpp"
+#include "llpipeline_stub.cpp"
+#include "llviewershadermgr_stub.cpp"
+
+void assert_glerror(void) {}
+LLViewerCamera::LLViewerCamera() {}
+void LLViewerCamera::setView(F32 vertical_fov_rads) {}
+std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) { return std::string(""); }
+
+char* curl_unescape(const char* c_str, int length)
+{
+ char* copy = new char[length+4];
+ memcpy(copy, c_str, length);
+ copy[length+0] = 'E';
+ copy[length+1] = 'S';
+ copy[length+2] = 'C';
+ copy[length+3] = '\0';
+ return copy;
+}
+void curl_free(void* p) {delete[] ((char*)p);}
+char* curl_escape(const char* c_str, int length) {
+ char* copy = new char[length+6];
+ memcpy(copy, c_str, length);
+ copy[length+0] = 'U';
+ copy[length+1] = 'N';
+ copy[length+2] = 'E';
+ copy[length+3] = 'S';
+ copy[length+4] = 'C';
+ copy[length+5] = '\0';
+ return copy;
+}
+
+namespace tut
+{
+ // Main Setup
+ struct LLWLParamManagerFixture
+ {
+ class LLWLParamManagerTest
+ {
+ };
+
+ LLWLParamManager* mTestManager;
+
+ LLWLParamManagerFixture()
+ : mTestManager(LLWLParamManager::getInstance())
+ {
+ }
+
+ ~LLWLParamManagerFixture()
+ {
+ }
+ };
+ typedef test_group<LLWLParamManagerFixture> factory;
+ typedef factory::object object;
+ factory tf("LLWLParamManager test");
+
+ // Tests
+ template<> template<>
+ void object::test<1>()
+ {
+ try
+ {
+ std::string preset =
+ "<llsd>\
+ <map>\
+ <key>ambient</key>\
+ <array>\
+ <real>1.0499999523162842</real>\
+ <real>1.0499999523162842</real>\
+ <real>1.0499999523162842</real>\
+ <real>0.34999999403953552</real>\
+ </array>\
+ <key>blue_density</key>\
+ <array>\
+ <real>0.2447581488182351</real>\
+ <real>0.44872328639030457</real>\
+ <real>0.75999999046325684</real>\
+ <real>0.38000004053115788</real>\
+ </array>\
+ <key>blue_horizon</key>\
+ <array>\
+ <real>0.49548382097675159</real>\
+ <real>0.49548381382419748</real>\
+ <real>0.63999999284744291</real>\
+ <real>0.31999999642372146</real>\
+ </array>\
+ <key>cloud_color</key>\
+ <array>\
+ <real>0.40999999165535073</real>\
+ <real>0.40999999165535073</real>\
+ <real>0.40999999165535073</real>\
+ <real>0.40999999165535073</real>\
+ </array>\
+ <key>cloud_pos_density1</key>\
+ <array>\
+ <real>1.6884100437164307</real>\
+ <real>0.52609699964523315</real>\
+ <real>0.99999999999999289</real>\
+ <real>1</real>\
+ </array>\
+ <key>cloud_pos_density2</key>\
+ <array>\
+ <real>1.6884100437164307</real>\
+ <real>0.52609699964523315</real>\
+ <real>0.125</real>\
+ <real>1</real>\
+ </array>\
+ <key>cloud_scale</key>\
+ <array>\
+ <real>0.4199999868869746</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>cloud_scroll_rate</key>\
+ <array>\
+ <real>10.199999809265137</real>\
+ <real>10.01099967956543</real>\
+ </array>\
+ <key>cloud_shadow</key>\
+ <array>\
+ <real>0.26999998092651367</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>density_multiplier</key>\
+ <array>\
+ <real>0.00017999998817685818</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>distance_multiplier</key>\
+ <array>\
+ <real>0.80000001192093606</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>east_angle</key>\
+ <real>0</real>\
+ <key>enable_cloud_scroll</key>\
+ <array>\
+ <boolean>1</boolean>\
+ <boolean>1</boolean>\
+ </array>\
+ <key>gamma</key>\
+ <array>\
+ <real>1</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>glow</key>\
+ <array>\
+ <real>5</real>\
+ <real>0.0010000000474974513</real>\
+ <real>-0.47999998927116394</real>\
+ <real>1</real>\
+ </array>\
+ <key>haze_density</key>\
+ <array>\
+ <real>0.69999998807907104</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>haze_horizon</key>\
+ <array>\
+ <real>0.18999999761581243</real>\
+ <real>0.19915600121021271</real>\
+ <real>0.19915600121021271</real>\
+ <real>1</real>\
+ </array>\
+ <key>lightnorm</key>\
+ <array>\
+ <real>0</real>\
+ <real>0.70710659027099609</real>\
+ <real>-0.70710694789886475</real>\
+ <real>0</real>\
+ </array>\
+ <key>max_y</key>\
+ <array>\
+ <real>1605</real>\
+ <real>0</real>\
+ <real>0</real>\
+ <real>1</real>\
+ </array>\
+ <key>preset_num</key>\
+ <integer>22</integer>\
+ <key>star_brightness</key>\
+ <real>0</real>\
+ <key>sun_angle</key>\
+ <real>2.3561947345733643</real>\
+ <key>sunlight_color</key>\
+ <array>\
+ <real>0.73421055078505759</real>\
+ <real>0.78157895803450828</real>\
+ <real>0.89999997615813498</real>\
+ <real>0.29999998211860301</real>\
+ </array>\
+ </map>\
+ </llsd>";
+
+ std::stringstream preset_stream(preset);
+ mTestManager->loadPresetFromXML(LLWLParamKey("test1", LLWLParamKey::SCOPE_LOCAL), preset_stream);
+ LLWLParamSet dummy;
+ ensure("Couldn't get ParamSet after loading it", mTestManager->getParamSet(LLWLParamKey("test1", LLWLParamKey::SCOPE_LOCAL), dummy));
+ }
+ catch (...)
+ {
+ fail("loadPresetFromXML test crashed!");
+ }
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ mTestManager->propagateParameters();
+ ensure_equals("Wrong value from getDomeOffset()", mTestManager->getDomeOffset(), 0.96f);
+ ensure_equals("Wrong value from getDomeRadius()", mTestManager->getDomeRadius(), 15000.f);
+ ensure_equals("Wrong value from getLightDir()", mTestManager->getLightDir(), LLVector4(-0,0,1,0));
+ ensure_equals("Wrong value from getClampedLightDir()", mTestManager->getClampedLightDir(), LLVector4(-0,0,1,0));
+ ensure_equals("Wrong value from getRotatedLightDir()", mTestManager->getRotatedLightDir(), LLVector4(0,0,0,1));
+ }
+}
diff --git a/indra/newview/tests/llwlparamset_stub.cpp b/indra/newview/tests/llwlparamset_stub.cpp
new file mode 100644
index 0000000000..6ce4b5827d
--- /dev/null
+++ b/indra/newview/tests/llwlparamset_stub.cpp
@@ -0,0 +1,24 @@
+/**
+ * @file llwlparamset_stub.cpp
+ * @brief stub class to allow unit testing
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+LLWLParamSet::LLWLParamSet(void)
+{
+}
+
+void LLWLParamSet::updateCloudScrolling()
+{
+}
+
+void LLWLParamSet::set(const std::string& name, const LLVector4& val)
+{
+}
+
+void LLWLParamSet::update(LLGLSLShader *shader) const
+{
+}
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 651d803e0d..d480b63094 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -178,6 +178,8 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_para
request["uri"] = uri;
request["reply"] = replyPump.getName();
rewrittenURIs = postAndWait(self, request, srv_pump_name, filter);
+ // EXP-772: If rewrittenURIs fail, try original URI as a fallback.
+ rewrittenURIs.append(uri);
} // we no longer need the filter
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));