summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgtags5
-rw-r--r--BuildParams7
-rwxr-xr-xbuild.sh2
-rw-r--r--doc/contributions.txt37
-rw-r--r--etc/message.xml8
-rw-r--r--indra/CMakeLists.txt5
-rw-r--r--indra/cmake/00-Common.cmake4
-rw-r--r--indra/cmake/FMOD.cmake6
-rw-r--r--indra/cmake/LLAddBuildTest.cmake538
-rw-r--r--indra/cmake/Python.cmake2
-rw-r--r--indra/cmake/TemplateCheck.cmake7
-rw-r--r--indra/cmake/ViewerMiscLibs.cmake2
-rw-r--r--indra/integration_tests/llui_libtest/llui_libtest.cpp2
-rw-r--r--indra/linux_updater/linux_updater.cpp180
-rw-r--r--indra/llaudio/CMakeLists.txt5
-rw-r--r--indra/llaudio/llvorbisencode.cpp7
-rw-r--r--indra/llaudio/llvorbisencode.h1
-rw-r--r--indra/llcommon/CMakeLists.txt4
-rw-r--r--indra/llcommon/indra_constants.h11
-rw-r--r--indra/llcommon/llapp.cpp32
-rw-r--r--indra/llcommon/llapp.h6
-rw-r--r--indra/llcommon/lldarray.h2
-rw-r--r--indra/llcommon/llfasttimer_class.cpp1
-rw-r--r--indra/llcommon/llfasttimer_class.h1
-rw-r--r--indra/llcommon/llfile.cpp5
-rw-r--r--indra/llcommon/llmetricperformancetester.cpp254
-rw-r--r--indra/llcommon/llmetricperformancetester.h206
-rw-r--r--indra/llcommon/llprocesslauncher.cpp5
-rw-r--r--indra/llcommon/llprocesslauncher.h2
-rw-r--r--indra/llcommon/llsys.cpp20
-rw-r--r--indra/llcommon/llsys.h3
-rw-r--r--indra/llcommon/llthread.cpp30
-rw-r--r--indra/llcommon/llthreadsafequeue.cpp109
-rw-r--r--indra/llcommon/llthreadsafequeue.h205
-rw-r--r--indra/llcommon/llversionviewer.h6
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp16
-rw-r--r--indra/llimage/llimagej2c.cpp178
-rw-r--r--indra/llimage/llimagej2c.h45
-rw-r--r--indra/llmessage/llavatarnamecache.cpp14
-rw-r--r--indra/llrender/llgl.cpp53
-rw-r--r--indra/llrender/llgl.h8
-rw-r--r--indra/llrender/llglheaders.h10
-rw-r--r--indra/llrender/llimagegl.cpp2
-rw-r--r--indra/llrender/llrender.cpp3
-rw-r--r--indra/llrender/llvertexbuffer.cpp12
-rw-r--r--indra/llui/llaccordionctrltab.cpp58
-rw-r--r--indra/llui/llbutton.cpp8
-rw-r--r--indra/llui/llbutton.h4
-rw-r--r--indra/llui/llcombobox.cpp2
-rw-r--r--indra/llui/llfloater.cpp59
-rw-r--r--indra/llui/llfloater.h6
-rw-r--r--indra/llui/lliconctrl.cpp5
-rw-r--r--indra/llui/lliconctrl.h5
-rw-r--r--indra/llui/lllineeditor.cpp9
-rw-r--r--indra/llui/llmenubutton.cpp144
-rw-r--r--indra/llui/llmenubutton.h33
-rw-r--r--indra/llui/llmenugl.cpp205
-rw-r--r--indra/llui/llmenugl.h12
-rw-r--r--indra/llui/llnotifications.cpp16
-rw-r--r--indra/llui/llpanel.cpp4
-rw-r--r--indra/llui/llscrollcontainer.cpp5
-rw-r--r--indra/llui/llscrolllistctrl.cpp3
-rw-r--r--indra/llui/lltextbase.cpp44
-rw-r--r--indra/llui/lltoggleablemenu.cpp18
-rw-r--r--indra/llui/lltoggleablemenu.h5
-rw-r--r--indra/llui/llui.cpp11
-rw-r--r--indra/llui/llui.h2
-rw-r--r--indra/llui/lluictrl.cpp37
-rw-r--r--indra/llui/lluictrl.h18
-rw-r--r--indra/llui/lluistring.h10
-rw-r--r--indra/llui/llurlentry.cpp9
-rw-r--r--indra/llui/llurlentry.h2
-rw-r--r--indra/llvfs/lldir.cpp2
-rw-r--r--indra/llvfs/lldir.h28
-rw-r--r--indra/llvfs/lldir_linux.cpp48
-rw-r--r--indra/llvfs/lldir_linux.h3
-rw-r--r--indra/llvfs/lldir_mac.cpp42
-rw-r--r--indra/llvfs/lldir_mac.h3
-rw-r--r--indra/llvfs/lldir_solaris.cpp48
-rw-r--r--indra/llvfs/lldir_solaris.h3
-rw-r--r--indra/llvfs/lldir_win32.cpp127
-rw-r--r--indra/llvfs/lldir_win32.h5
-rw-r--r--indra/llvfs/tests/lldir_test.cpp155
-rw-r--r--indra/llxml/llcontrol.cpp26
-rw-r--r--indra/mac_updater/mac_updater.cpp103
-rw-r--r--indra/newview/CMakeLists.txt30
-rw-r--r--indra/newview/app_settings/cmd_line.xml13
-rw-r--r--indra/newview/app_settings/settings.xml211
-rw-r--r--indra/newview/app_settings/settings_per_account.xml12
-rw-r--r--indra/newview/featuretable.txt5
-rw-r--r--indra/newview/featuretable_linux.txt5
-rw-r--r--indra/newview/featuretable_mac.txt5
-rw-r--r--indra/newview/featuretable_xp.txt5
-rw-r--r--indra/newview/generate_breakpad_symbols.py11
-rw-r--r--indra/newview/installers/windows/installer_template.nsi55
-rw-r--r--indra/newview/llagent.cpp10
-rw-r--r--indra/newview/llagent.h1
-rw-r--r--indra/newview/llagentcamera.cpp7
-rw-r--r--indra/newview/llappearancemgr.cpp20
-rw-r--r--indra/newview/llappviewer.cpp248
-rw-r--r--indra/newview/llappviewer.h16
-rw-r--r--indra/newview/llappviewerlinux.cpp3
-rw-r--r--indra/newview/llavatarlistitem.cpp11
-rw-r--r--indra/newview/llavatarlistitem.h4
-rw-r--r--indra/newview/llbottomtray.cpp21
-rw-r--r--indra/newview/llcallfloater.cpp18
-rw-r--r--indra/newview/llcallfloater.h1
-rw-r--r--indra/newview/llchathistory.cpp14
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp62
-rw-r--r--indra/newview/llchiclet.cpp8
-rw-r--r--indra/newview/llcolorswatch.cpp46
-rw-r--r--indra/newview/llcolorswatch.h2
-rw-r--r--indra/newview/llcommandlineparser.cpp6
-rw-r--r--indra/newview/llcurrencyuimanager.cpp4
-rw-r--r--indra/newview/lldrawable.cpp1
-rw-r--r--indra/newview/lldrawpool.cpp1
-rw-r--r--indra/newview/lldrawpool.h2
-rw-r--r--indra/newview/lldrawpoolavatar.cpp73
-rw-r--r--indra/newview/lldrawpoolavatar.h1
-rw-r--r--indra/newview/lldrawpoolclouds.cpp3
-rw-r--r--indra/newview/lldrawpoolclouds.h1
-rw-r--r--indra/newview/lldrawpoolground.cpp6
-rw-r--r--indra/newview/lldrawpoolground.h1
-rw-r--r--indra/newview/lldrawpoolsky.cpp6
-rw-r--r--indra/newview/lldrawpoolsky.h1
-rw-r--r--indra/newview/lldrawpoolterrain.cpp21
-rw-r--r--indra/newview/lldrawpoolterrain.h1
-rw-r--r--indra/newview/lldrawpooltree.cpp62
-rw-r--r--indra/newview/lldrawpooltree.h1
-rw-r--r--indra/newview/lldrawpoolwater.cpp136
-rw-r--r--indra/newview/lldrawpoolwater.h5
-rw-r--r--indra/newview/lldrawpoolwlsky.cpp2
-rw-r--r--indra/newview/llexternaleditor.cpp192
-rw-r--r--indra/newview/llexternaleditor.h91
-rw-r--r--indra/newview/llface.cpp78
-rw-r--r--indra/newview/llface.h1
-rw-r--r--indra/newview/llfasttimerview.cpp55
-rw-r--r--indra/newview/llfasttimerview.h1
-rw-r--r--indra/newview/llfavoritesbar.cpp3
-rw-r--r--indra/newview/llfloaterabout.cpp4
-rw-r--r--indra/newview/llfloatercamera.cpp1
-rw-r--r--indra/newview/llfloatercolorpicker.cpp19
-rw-r--r--indra/newview/llfloatercolorpicker.h1
-rw-r--r--indra/newview/llfloaterevent.cpp5
-rw-r--r--indra/newview/llfloaterevent.h1
-rw-r--r--indra/newview/llfloatergodtools.cpp18
-rw-r--r--indra/newview/llfloatergroups.cpp5
-rw-r--r--indra/newview/llfloatermap.cpp33
-rw-r--r--indra/newview/llfloaterpostcard.cpp10
-rw-r--r--indra/newview/llfloaterpreference.cpp109
-rw-r--r--indra/newview/llfloaterpreference.h13
-rw-r--r--indra/newview/llfloaterregiondebugconsole.cpp227
-rw-r--r--indra/newview/llfloaterregiondebugconsole.h63
-rw-r--r--indra/newview/llfloatersnapshot.cpp15
-rw-r--r--indra/newview/llfloatertopobjects.cpp24
-rw-r--r--indra/newview/llfloatertopobjects.h5
-rw-r--r--indra/newview/llfloateruipreview.cpp222
-rw-r--r--indra/newview/llfloaterworldmap.cpp2
-rw-r--r--indra/newview/llfolderview.cpp2
-rw-r--r--indra/newview/llgiveinventory.cpp4
-rw-r--r--indra/newview/llglsandbox.cpp94
-rw-r--r--indra/newview/llhudicon.cpp5
-rw-r--r--indra/newview/llhudicon.h1
-rw-r--r--indra/newview/llhudobject.cpp21
-rw-r--r--indra/newview/llhudobject.h1
-rw-r--r--indra/newview/llhudtext.cpp25
-rw-r--r--indra/newview/llhudtext.h3
-rw-r--r--indra/newview/llimfloater.cpp2
-rw-r--r--indra/newview/llimview.cpp58
-rw-r--r--indra/newview/llimview.h2
-rw-r--r--indra/newview/llinspectavatar.cpp5
-rw-r--r--indra/newview/llinspectobject.cpp3
-rw-r--r--indra/newview/llinventorybridge.cpp104
-rw-r--r--indra/newview/llinventoryfunctions.cpp5
-rw-r--r--indra/newview/llinventoryicon.cpp4
-rw-r--r--indra/newview/llinventorylistitem.cpp3
-rw-r--r--indra/newview/llinventorypanel.cpp5
-rw-r--r--indra/newview/lllogchat.cpp86
-rw-r--r--indra/newview/lllogchat.h4
-rw-r--r--indra/newview/lllogininstance.cpp6
-rw-r--r--indra/newview/llmainlooprepeater.cpp88
-rw-r--r--indra/newview/llmainlooprepeater.h65
-rw-r--r--indra/newview/llmaniptranslate.cpp2
-rw-r--r--indra/newview/llmetricperformancetester.cpp252
-rw-r--r--indra/newview/llmetricperformancetester.h153
-rw-r--r--indra/newview/llmoveview.cpp3
-rw-r--r--indra/newview/llnearbychat.cpp13
-rw-r--r--indra/newview/llnearbychat.h1
-rw-r--r--indra/newview/llnearbychathandler.cpp97
-rw-r--r--indra/newview/llnetmap.h2
-rw-r--r--indra/newview/lloutfitslist.cpp69
-rw-r--r--indra/newview/lloutfitslist.h4
-rw-r--r--indra/newview/llpanelappearancetab.h2
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp3
-rw-r--r--indra/newview/llpanelgrouproles.cpp111
-rw-r--r--indra/newview/llpanelgrouproles.h6
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp6
-rw-r--r--indra/newview/llpanellandmarks.cpp23
-rw-r--r--indra/newview/llpanellandmarks.h7
-rw-r--r--indra/newview/llpanellogin.cpp4
-rw-r--r--indra/newview/llpanelmaininventory.cpp60
-rw-r--r--indra/newview/llpanelmaininventory.h7
-rw-r--r--indra/newview/llpanelobject.cpp4
-rw-r--r--indra/newview/llpaneloutfitedit.cpp57
-rw-r--r--indra/newview/llpaneloutfitedit.h11
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp20
-rw-r--r--indra/newview/llpaneloutfitsinventory.h1
-rw-r--r--indra/newview/llpanelpeople.cpp75
-rw-r--r--indra/newview/llpanelpeople.h10
-rw-r--r--indra/newview/llpanelpick.cpp3
-rw-r--r--indra/newview/llpanelpicks.cpp15
-rw-r--r--indra/newview/llpanelpicks.h1
-rw-r--r--indra/newview/llpanelplaceinfo.cpp4
-rw-r--r--indra/newview/llpanelprofile.cpp16
-rw-r--r--indra/newview/llpanelteleporthistory.cpp35
-rw-r--r--indra/newview/llpanelteleporthistory.h3
-rw-r--r--indra/newview/llpanelwearing.cpp31
-rw-r--r--indra/newview/llpanelwearing.h2
-rw-r--r--indra/newview/llparticipantlist.cpp99
-rw-r--r--indra/newview/llparticipantlist.h431
-rw-r--r--indra/newview/llplacesinventorypanel.cpp18
-rw-r--r--indra/newview/llplacesinventorypanel.h6
-rw-r--r--indra/newview/llpreviewscript.cpp235
-rw-r--r--indra/newview/llpreviewscript.h15
-rw-r--r--indra/newview/llremoteparcelrequest.cpp56
-rw-r--r--indra/newview/llremoteparcelrequest.h2
-rw-r--r--indra/newview/llscreenchannel.cpp8
-rw-r--r--indra/newview/llscriptfloater.cpp46
-rw-r--r--indra/newview/llscriptfloater.h3
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp23
-rw-r--r--indra/newview/llsidepaneliteminfo.h2
-rw-r--r--indra/newview/llsidetray.cpp12
-rw-r--r--indra/newview/llsidetray.h29
-rw-r--r--indra/newview/llspatialpartition.cpp25
-rw-r--r--indra/newview/llspatialpartition.h7
-rw-r--r--indra/newview/llspeakbutton.cpp7
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp5
-rw-r--r--indra/newview/llstartup.cpp13
-rw-r--r--indra/newview/llstartup.h1
-rw-r--r--indra/newview/llsurface.cpp5
-rw-r--r--indra/newview/lltexturectrl.cpp20
-rw-r--r--indra/newview/lltexturefetch.cpp12
-rw-r--r--indra/newview/lltextureview.cpp7
-rw-r--r--indra/newview/lltoast.cpp115
-rw-r--r--indra/newview/lltoast.h43
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp2
-rw-r--r--indra/newview/lltoastnotifypanel.cpp17
-rw-r--r--indra/newview/lltoastscripttextbox.cpp109
-rw-r--r--indra/newview/lltoastscripttextbox.h58
-rw-r--r--indra/newview/lltransientfloatermgr.cpp5
-rw-r--r--indra/newview/lltranslate.cpp12
-rw-r--r--indra/newview/llversioninfo.cpp37
-rw-r--r--indra/newview/llversioninfo.h7
-rw-r--r--indra/newview/llviewercontrol.cpp29
-rw-r--r--indra/newview/llviewercontrol.h2
-rw-r--r--indra/newview/llviewerdisplay.cpp36
-rw-r--r--indra/newview/llviewerdisplay.h1
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerjoint.cpp2
-rw-r--r--indra/newview/llviewerjointmesh.cpp27
-rw-r--r--indra/newview/llviewermedia.cpp4
-rw-r--r--indra/newview/llviewermenu.cpp107
-rw-r--r--indra/newview/llviewermenufile.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp50
-rw-r--r--indra/newview/llviewerobject.cpp221
-rw-r--r--indra/newview/llviewerobject.h43
-rw-r--r--indra/newview/llviewerobjectlist.cpp52
-rw-r--r--indra/newview/llviewerobjectlist.h1
-rw-r--r--indra/newview/llviewerregion.cpp3
-rw-r--r--indra/newview/llviewerregion.h1
-rw-r--r--indra/newview/llviewershadermgr.cpp4
-rw-r--r--indra/newview/llviewerstats.cpp5
-rw-r--r--indra/newview/llviewerstats.h2
-rw-r--r--indra/newview/llviewertexture.cpp246
-rw-r--r--indra/newview/llviewertexture.h9
-rw-r--r--indra/newview/llviewertexturelist.cpp26
-rw-r--r--indra/newview/llviewerthrottle.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp68
-rw-r--r--indra/newview/llviewerwindow.h3
-rw-r--r--indra/newview/llviewerwindowlistener.cpp3
-rw-r--r--indra/newview/llvoavatar.cpp5
-rw-r--r--indra/newview/llvoavatarself.cpp21
-rw-r--r--indra/newview/llvoavatarself.h2
-rw-r--r--indra/newview/llvocache.cpp30
-rw-r--r--indra/newview/llvocache.h3
-rw-r--r--indra/newview/llvosurfacepatch.cpp2
-rw-r--r--indra/newview/llvowater.cpp32
-rw-r--r--indra/newview/llvowater.h14
-rw-r--r--indra/newview/llwaterparammanager.cpp4
-rw-r--r--indra/newview/llwlparammanager.cpp4
-rw-r--r--indra/newview/llworld.cpp363
-rw-r--r--indra/newview/llworld.h3
-rw-r--r--indra/newview/llworldmapview.cpp6
-rw-r--r--indra/newview/pipeline.cpp226
-rw-r--r--indra/newview/pipeline.h3
-rw-r--r--indra/newview/skins/default/colors.xml9
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_classified_info.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_classified.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_pick.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_wearable.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_edit.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_info.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_place_profile.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_colors.xml14
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_privacy.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_view.xml3
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_item_info.xml3
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_task_info.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/avatar_icon.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/button.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/icon.xml1
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp9
-rw-r--r--indra/newview/tests/llremoteparcelrequest_test.cpp134
-rw-r--r--indra/newview/tests/llversioninfo_test.cpp114
-rw-r--r--indra/newview/tests/llviewerhelputil_test.cpp17
-rw-r--r--indra/newview/viewer_manifest.py27
-rw-r--r--indra/viewer_components/CMakeLists.txt2
-rw-r--r--indra/viewer_components/updater/CMakeLists.txt82
-rw-r--r--indra/viewer_components/updater/llupdatechecker.cpp194
-rw-r--r--indra/viewer_components/updater/llupdatechecker.h82
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.cpp428
-rw-r--r--indra/viewer_components/updater/llupdatedownloader.h87
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.cpp90
-rw-r--r--indra/viewer_components/updater/llupdateinstaller.h57
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp519
-rw-r--r--indra/viewer_components/updater/llupdaterservice.h85
-rwxr-xr-xindra/viewer_components/updater/scripts/darwin/update_install9
-rwxr-xr-xindra/viewer_components/updater/scripts/linux/update_install10
-rw-r--r--indra/viewer_components/updater/scripts/windows/update_install.bat3
-rw-r--r--indra/viewer_components/updater/tests/llupdaterservice_test.cpp199
-rw-r--r--install.xml14
-rwxr-xr-xscripts/md5check.py61
338 files changed, 9322 insertions, 3613 deletions
diff --git a/.hgtags b/.hgtags
index 0f6c5a94d8..b9d50a7fb2 100644
--- a/.hgtags
+++ b/.hgtags
@@ -29,7 +29,12 @@ c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint
9822eb3e25f7fe0c28ffd8aba45c507caa383cbc 2.2.0-beta2
b0cd7e150009809a0b5b0a9d5785cd4bb230413a 2.2.0-beta3
00a831292231faad7e44c69f76cb96f175b8dfad 2.2.0-beta4
+98e0d6df638429fd2f0476667504bd5a6b298def 2.3.0-beta1
1415e6538d54fd5d568ee88343424d57c6803c2c 2.2.0-release
98e0d6df638429fd2f0476667504bd5a6b298def 2.3.0-start
a3c12342b1af0951b8aa3b828aacef17fcea8178 2.3.0-beta1
db0fe9bb65187f365e58a717dd23d0f4754a9c1d 2.3.0-beta2
+6ad3d6fa35a4e320e9ce442fce2bf9c7fc852556 2.3.0-beta3
+6ad3d6fa35a4e320e9ce442fce2bf9c7fc852556 2.3.0-release
+dbc206fc61d89ff4cfe15aade0bf0c7bc7fee1c9 2.4.0-start
+dc6483491b4af559060bccaef8e9045a303212dd 2.4.0-beta1
diff --git a/BuildParams b/BuildParams
index 151b21fb1f..8e4164d5ca 100644
--- a/BuildParams
+++ b/BuildParams
@@ -14,6 +14,9 @@ public_build = true
# Update Public Inworld Build Status Indicators
email_status_this_is_os = true
+# Limit extent of codeticket updates to revisions after...
+codeticket_since = 2.2.0-release
+
# ========================================
# Viewer Development
# ========================================
@@ -43,6 +46,9 @@ viewer-beta.viewer_channel = "Second Life Beta Viewer"
viewer-beta.login_channel = "Second Life Beta Viewer"
viewer-beta.build_debug_release_separately = true
viewer-beta.build_viewer_update_version_manager = true
+# Settings to test new code ticket service
+viewer-beta.codeticket_server_url = "http://pdp75.lindenlab.com:8000/codeticket/linden/"
+viewer-beta.codeticket_add_context = true
# ========================================
# Viewer Release
@@ -51,6 +57,7 @@ viewer-release.viewer_channel = "Second Life Release"
viewer-release.login_channel = "Second Life Release"
viewer-release.build_debug_release_separately = true
viewer-release.build_viewer_update_version_manager = true
+viewer-release.release-viewer.jira = DRTVWR-13
# ========================================
# aimee
diff --git a/build.sh b/build.sh
index b372168f98..f9c6beefed 100755
--- a/build.sh
+++ b/build.sh
@@ -228,7 +228,7 @@ do
fi
else
begin_section "Build$variant"
- build "$variant" "$build_dir" > "$build_log" 2>&1
+ build "$variant" "$build_dir" >> "$build_log" 2>&1
begin_section Tests
grep --line-buffered "^##teamcity" "$build_log"
end_section Tests
diff --git a/doc/contributions.txt b/doc/contributions.txt
index bcf714b29a..c88d712bc8 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -62,20 +62,25 @@ Alejandro Rosenthal
VWR-1184
Aleric Inglewood
SNOW-522
+ SNOW-626
SNOW-756
SNOW-764
VWR-10001
VWR-10759
VWR-10837
VWR-12691
+ VWR-12984
VWR-13996
VWR-14426
SNOW-84
+ SNOW-477
SNOW-766
STORM-163
Ales Beaumont
VWR-9352
SNOW-240
+Alexandrea Fride
+ STORM-255
Alissa Sabre
VWR-81
VWR-83
@@ -124,6 +129,7 @@ Alissa Sabre
VWR-12617
VWR-12620
VWR-12789
+ SNOW-322
Angus Boyd
VWR-592
Ann Congrejo
@@ -140,6 +146,7 @@ Asuka Neely
Balp Allen
VWR-4157
Be Holder
+ SNOW-322
SNOW-397
Benja Kepler
VWR-746
@@ -170,9 +177,11 @@ Boroondas Gupte
SNOW-610
SNOW-624
SNOW-737
+ STORM-318
VWR-233
VWR-20583
VWR-20891
+ VWR-23455
WEB-262
Bulli Schumann
CT-218
@@ -202,6 +211,8 @@ Catherine Pfeffer
Celierra Darling
VWR-1274
VWR-6975
+Cypren Christenson
+ STORM-417
Dale Glass
VWR-120
VWR-560
@@ -344,6 +355,8 @@ Joghert LeSabre
VWR-64
Jonathan Yap
VWR-17801
+ STORM-616
+ STORM-726
Kage Pixel
VWR-11
Ken March
@@ -381,6 +394,8 @@ Malwina Dollinger
CT-138
march Korda
SVC-1020
+Marine Kelley
+ STORM-281
Matthew Dowd
VWR-1344
VWR-1651
@@ -402,6 +417,7 @@ McCabe Maxsted
VWR-8689
VWR-9007
Michelle2 Zenovka
+ STORM-477
VWR-2652
VWR-2662
VWR-2834
@@ -529,6 +545,7 @@ Pf Shan
CT-230
CT-231
CT-321
+ SNOW-422
princess niven
VWR-5733
CT-85
@@ -562,6 +579,7 @@ Robin Cornelius
SNOW-585
SNOW-599
SNOW-747
+ STORM-422
VWR-2488
VWR-9557
VWR-11128
@@ -585,6 +603,8 @@ Salahzar Stenvaag
CT-321
Sammy Frederix
VWR-6186
+Satomi Ahn
+ STORM-501
Scrippy Scofield
VWR-3748
Seg Baphomet
@@ -643,6 +663,7 @@ Strife Onizuka
VWR-183
VWR-2265
VWR-4111
+ SNOW-691
Tayra Dagostino
SNOW-517
SNOW-543
@@ -695,6 +716,8 @@ Thraxis Epsilon
VWR-383
tiamat bingyi
CT-246
+Tofu Buzzard
+ STORM-546
TraductoresAnonimos Alter
CT-324
Tue Torok
@@ -740,6 +763,20 @@ Whoops Babii
VWR-8298
Wilton Lundquist
VWR-7682
+WolfPup Lowenhar
+ SNOW-622
+ SNOW-772
+ STORM-102
+ STORM-103
+ STORM-143
+ STORM-255
+ STORM-256
+ STORM-535
+ STORM-544
+ STORM-654
+ STORM-674
+ VWR-20741
+ VWR-20933
Zai Lynch
VWR-19505
Zarkonnen Decosta
diff --git a/etc/message.xml b/etc/message.xml
index ebbb4e57a9..7c4a927cc5 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -442,6 +442,14 @@
<boolean>true</boolean>
</map>
+ <key>SimConsoleResponse</key>
+ <map>
+ <key>flavor</key>
+ <string>llsd</string>
+ <key>trusted-sender</key>
+ <boolean>true</boolean>
+ </map>
+
<key>DirLandReply</key>
<map>
<key>flavor</key>
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 8d4969a49e..d01e1869b6 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -22,7 +22,10 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(Variables)
if (DARWIN)
- cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
+ # 2.6.4 fixes a Mac bug in get_target_property(... "SLPlugin" LOCATION):
+ # before that version it returns "pathname/SLPlugin", whereas the correct
+ # answer is "pathname/SLPlugin.app/Contents/MacOS/SLPlugin".
+ cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
endif (DARWIN)
if (NOT CMAKE_BUILD_TYPE)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index a114d6e778..db2cdb5ff8 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -38,10 +38,10 @@ if (WINDOWS)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP"
CACHE STRING "C++ compiler debug options" FORCE)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
- "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP"
+ "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP /Ob2"
CACHE STRING "C++ compiler release-with-debug options" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE
- "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP"
+ "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /Ob2"
CACHE STRING "C++ compiler release options" FORCE)
set(CMAKE_CXX_STANDARD_LIBRARIES "")
diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake
index 96434e38fa..dcf44cd642 100644
--- a/indra/cmake/FMOD.cmake
+++ b/indra/cmake/FMOD.cmake
@@ -7,8 +7,10 @@ if (FMOD)
set(FMOD_FIND_REQUIRED ON)
include(FindFMOD)
else (STANDALONE)
- include(Prebuilt)
- use_prebuilt_binary(fmod)
+ if (INSTALL_PROPRIETARY)
+ include(Prebuilt)
+ use_prebuilt_binary(fmod)
+ endif (INSTALL_PROPRIETARY)
if (WINDOWS)
set(FMOD_LIBRARY fmod)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 79c3bb7da2..29e2492551 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -1,265 +1,273 @@
-# -*- cmake -*-
-include(LLTestCommand)
-include(GoogleMock)
-
-MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
- # Given a project name and a list of sourcefiles (with optional properties on each),
- # add targets to build and run the tests specified.
- # ASSUMPTIONS:
- # * this macro is being executed in the project file that is passed in
- # * current working SOURCE dir is that project dir
- # * there is a subfolder tests/ with test code corresponding to the filenames passed in
- # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
- #
- # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
- #
- # WARNING: do NOT modify this code without working with poppy -
- # there is another branch that will conflict heavily with any changes here.
-INCLUDE(GoogleMock)
-
-
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
- ENDIF(LL_TEST_VERBOSE)
-
- # Start with the header and project-wide setup before making targets
- #project(UNITTEST_PROJECT_${project})
- # Setup includes, paths, etc
- SET(alltest_SOURCE_FILES
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- ${CMAKE_SOURCE_DIR}/test/lltut.cpp
- )
- SET(alltest_DEP_TARGETS
- # needed by the test harness itself
- ${APRUTIL_LIBRARIES}
- ${APR_LIBRARIES}
- llcommon
- )
- IF(NOT "${project}" STREQUAL "llmath")
- # add llmath as a dep unless the tested module *is* llmath!
- LIST(APPEND alltest_DEP_TARGETS
- llmath
- )
- ENDIF(NOT "${project}" STREQUAL "llmath")
- SET(alltest_INCLUDE_DIRS
- ${LLMATH_INCLUDE_DIRS}
- ${LLCOMMON_INCLUDE_DIRS}
- ${LIBS_OPEN_DIR}/test
- ${GOOGLEMOCK_INCLUDE_DIRS}
- )
- SET(alltest_LIBRARIES
- ${GOOGLEMOCK_LIBRARIES}
- ${PTHREAD_LIBRARY}
- ${WINDOWS_LIBRARIES}
- )
- # Headers, for convenience in targets.
- SET(alltest_HEADER_FILES
- ${CMAKE_SOURCE_DIR}/test/test.h
- )
-
- # Use the default flags
- if (LINUX)
- SET(CMAKE_EXE_LINKER_FLAGS "")
- endif (LINUX)
-
- # start the source test executable definitions
- SET(${project}_TEST_OUTPUT "")
- FOREACH (source ${sources})
- STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
- STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
- ENDIF(LL_TEST_VERBOSE)
-
- #
- # Per-codefile additional / external source, header, and include dir property extraction
- #
- # Source
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
- IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
- SET(${name}_test_additional_SOURCE_FILES "")
- ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
- SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
- ENDIF(LL_TEST_VERBOSE)
- # Headers
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
- IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
- SET(${name}_test_additional_HEADER_FILES "")
- ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
- SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
- set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
- LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
- ENDIF(LL_TEST_VERBOSE)
- # Include dirs
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
- IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
- SET(${name}_test_additional_INCLUDE_DIRS "")
- ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
- INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
- ENDIF(LL_TEST_VERBOSE)
-
-
- # Setup target
- ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
- SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
-
- #
- # Per-codefile additional / external project dep and lib dep property extraction
- #
- # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
- # Projects
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
- IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
- SET(${name}_test_additional_PROJECTS "")
- ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
- # Libraries
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
- IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
- SET(${name}_test_additional_LIBRARIES "")
- ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
- ENDIF(LL_TEST_VERBOSE)
- # Add to project
- TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
-
- #
- # Setup test targets
- #
- GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
- SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
- SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
-
- # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
- IF(LL_TEST_VERBOSE)
- MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}")
- ENDIF(LL_TEST_VERBOSE)
-
- SET_TEST_PATH(LD_LIBRARY_PATH)
- LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD})
- IF(LL_TEST_VERBOSE)
- MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}")
- ENDIF(LL_TEST_VERBOSE)
- # Add test
- ADD_CUSTOM_COMMAND(
- OUTPUT ${TEST_OUTPUT}
- COMMAND ${TEST_SCRIPT_CMD}
- DEPENDS PROJECT_${project}_TEST_${name}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- )
- # Why not add custom target and add POST_BUILD command?
- # Slightly less uncertain behavior
- # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
- # > I did not use a post build step as I could not make it notify of a
- # > failure after the first time you build and fail a test. - daveh 2009-04-20
- LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
- ENDFOREACH (source)
-
- # Add the test runner target per-project
- # (replaces old _test_ok targets all over the place)
- ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
- ADD_DEPENDENCIES(${project} ${project}_tests)
-ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
-
-FUNCTION(LL_ADD_INTEGRATION_TEST
- testname
- additional_source_files
- library_dependencies
-# variable args
- )
- if(TEST_DEBUG)
- message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
- endif(TEST_DEBUG)
-
- SET(source_files
- tests/${testname}_test.cpp
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- ${CMAKE_SOURCE_DIR}/test/lltut.cpp
- ${additional_source_files}
- )
-
- SET(libraries
- ${library_dependencies}
- ${GOOGLEMOCK_LIBRARIES}
- ${PTHREAD_LIBRARY}
- )
-
- # Add test executable build target
- if(TEST_DEBUG)
- message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
- endif(TEST_DEBUG)
- ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
- SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
-
- # Add link deps to the executable
- if(TEST_DEBUG)
- message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
- endif(TEST_DEBUG)
- TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
-
- # Create the test running command
- SET(test_command ${ARGN})
- GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
- LIST(FIND test_command "{}" test_exe_pos)
- IF(test_exe_pos LESS 0)
- # The {} marker means "the full pathname of the test executable."
- # test_exe_pos -1 means we didn't find it -- so append the test executable
- # name to $ARGN, the variable part of the arg list. This is convenient
- # shorthand for both straightforward execution of the test program (empty
- # $ARGN) and for running a "wrapper" program of some kind accepting the
- # pathname of the test program as the last of its args. You need specify
- # {} only if the test program's pathname isn't the last argument in the
- # desired command line.
- LIST(APPEND test_command "${TEST_EXE}")
- ELSE (test_exe_pos LESS 0)
- # Found {} marker at test_exe_pos. Remove the {}...
- LIST(REMOVE_AT test_command test_exe_pos)
- # ...and replace it with the actual name of the test executable.
- LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
- ENDIF (test_exe_pos LESS 0)
-
- SET_TEST_PATH(LD_LIBRARY_PATH)
- LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command})
-
- if(TEST_DEBUG)
- message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
- endif(TEST_DEBUG)
-
- ADD_CUSTOM_COMMAND(
- TARGET INTEGRATION_TEST_${testname}
- POST_BUILD
- COMMAND ${TEST_SCRIPT_CMD}
- )
-
- # Use CTEST? Not sure how to yet...
- # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
-
-ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
-
-MACRO(SET_TEST_PATH LISTVAR)
- IF(WINDOWS)
- # We typically build/package only Release variants of third-party
- # libraries, so append the Release staging dir in case the library being
- # sought doesn't have a debug variant.
- set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release)
- ELSEIF(DARWIN)
- # We typically build/package only Release variants of third-party
- # libraries, so append the Release staging dir in case the library being
- # sought doesn't have a debug variant.
- set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
- ELSE(WINDOWS)
- # Linux uses a single staging directory anyway.
- IF (STANDALONE)
- set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
- ELSE (STANDALONE)
- set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
- ENDIF (STANDALONE)
- ENDIF(WINDOWS)
-ENDMACRO(SET_TEST_PATH)
+# -*- cmake -*-
+include(LLTestCommand)
+include(GoogleMock)
+
+MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
+ # Given a project name and a list of sourcefiles (with optional properties on each),
+ # add targets to build and run the tests specified.
+ # ASSUMPTIONS:
+ # * this macro is being executed in the project file that is passed in
+ # * current working SOURCE dir is that project dir
+ # * there is a subfolder tests/ with test code corresponding to the filenames passed in
+ # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
+ #
+ # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
+ #
+ # WARNING: do NOT modify this code without working with poppy -
+ # there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
+
+
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
+ ENDIF(LL_TEST_VERBOSE)
+
+ # Start with the header and project-wide setup before making targets
+ #project(UNITTEST_PROJECT_${project})
+ # Setup includes, paths, etc
+ SET(alltest_SOURCE_FILES
+ ${CMAKE_SOURCE_DIR}/test/test.cpp
+ ${CMAKE_SOURCE_DIR}/test/lltut.cpp
+ )
+ SET(alltest_DEP_TARGETS
+ # needed by the test harness itself
+ ${APRUTIL_LIBRARIES}
+ ${APR_LIBRARIES}
+ llcommon
+ )
+ IF(NOT "${project}" STREQUAL "llmath")
+ # add llmath as a dep unless the tested module *is* llmath!
+ LIST(APPEND alltest_DEP_TARGETS
+ llmath
+ )
+ ENDIF(NOT "${project}" STREQUAL "llmath")
+ SET(alltest_INCLUDE_DIRS
+ ${LLMATH_INCLUDE_DIRS}
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LIBS_OPEN_DIR}/test
+ ${GOOGLEMOCK_INCLUDE_DIRS}
+ )
+ SET(alltest_LIBRARIES
+ ${GOOGLEMOCK_LIBRARIES}
+ ${PTHREAD_LIBRARY}
+ ${WINDOWS_LIBRARIES}
+ )
+ # Headers, for convenience in targets.
+ SET(alltest_HEADER_FILES
+ ${CMAKE_SOURCE_DIR}/test/test.h
+ )
+
+ # Use the default flags
+ if (LINUX)
+ SET(CMAKE_EXE_LINKER_FLAGS "")
+ endif (LINUX)
+
+ # start the source test executable definitions
+ SET(${project}_TEST_OUTPUT "")
+ FOREACH (source ${sources})
+ STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
+ STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
+ ENDIF(LL_TEST_VERBOSE)
+
+ #
+ # Per-codefile additional / external source, header, and include dir property extraction
+ #
+ # Source
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
+ IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
+ SET(${name}_test_additional_SOURCE_FILES "")
+ ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
+ SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Headers
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
+ IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
+ SET(${name}_test_additional_HEADER_FILES "")
+ ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
+ SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
+ set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
+ LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Include dirs
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
+ IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
+ SET(${name}_test_additional_INCLUDE_DIRS "")
+ ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
+ INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
+ ENDIF(LL_TEST_VERBOSE)
+
+
+ # Setup target
+ ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
+ SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
+
+ #
+ # Per-codefile additional / external project dep and lib dep property extraction
+ #
+ # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
+ # Projects
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
+ IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
+ SET(${name}_test_additional_PROJECTS "")
+ ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
+ # Libraries
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
+ IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
+ SET(${name}_test_additional_LIBRARIES "")
+ ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Add to project
+ TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
+ # Compile-time Definitions
+ GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS)
+ IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
+ SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} )
+ IF(LL_TEST_VERBOSE)
+ MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
+ ENDIF(LL_TEST_VERBOSE)
+ ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
+
+ #
+ # Setup test targets
+ #
+ GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
+ SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
+ SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+
+ # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
+ IF(LL_TEST_VERBOSE)
+ MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}")
+ ENDIF(LL_TEST_VERBOSE)
+
+ SET_TEST_PATH(LD_LIBRARY_PATH)
+ LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD})
+ IF(LL_TEST_VERBOSE)
+ MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}")
+ ENDIF(LL_TEST_VERBOSE)
+ # Add test
+ ADD_CUSTOM_COMMAND(
+ OUTPUT ${TEST_OUTPUT}
+ COMMAND ${TEST_SCRIPT_CMD}
+ DEPENDS PROJECT_${project}_TEST_${name}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ )
+ # Why not add custom target and add POST_BUILD command?
+ # Slightly less uncertain behavior
+ # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
+ # > I did not use a post build step as I could not make it notify of a
+ # > failure after the first time you build and fail a test. - daveh 2009-04-20
+ LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
+ ENDFOREACH (source)
+
+ # Add the test runner target per-project
+ # (replaces old _test_ok targets all over the place)
+ ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
+ ADD_DEPENDENCIES(${project} ${project}_tests)
+ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
+
+FUNCTION(LL_ADD_INTEGRATION_TEST
+ testname
+ additional_source_files
+ library_dependencies
+# variable args
+ )
+ if(TEST_DEBUG)
+ message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
+ endif(TEST_DEBUG)
+
+ SET(source_files
+ tests/${testname}_test.cpp
+ ${CMAKE_SOURCE_DIR}/test/test.cpp
+ ${CMAKE_SOURCE_DIR}/test/lltut.cpp
+ ${additional_source_files}
+ )
+
+ SET(libraries
+ ${library_dependencies}
+ ${GOOGLEMOCK_LIBRARIES}
+ ${PTHREAD_LIBRARY}
+ )
+
+ # Add test executable build target
+ if(TEST_DEBUG)
+ message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
+ endif(TEST_DEBUG)
+ ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
+ SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
+
+ # Add link deps to the executable
+ if(TEST_DEBUG)
+ message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
+ endif(TEST_DEBUG)
+ TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
+
+ # Create the test running command
+ SET(test_command ${ARGN})
+ GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
+ LIST(FIND test_command "{}" test_exe_pos)
+ IF(test_exe_pos LESS 0)
+ # The {} marker means "the full pathname of the test executable."
+ # test_exe_pos -1 means we didn't find it -- so append the test executable
+ # name to $ARGN, the variable part of the arg list. This is convenient
+ # shorthand for both straightforward execution of the test program (empty
+ # $ARGN) and for running a "wrapper" program of some kind accepting the
+ # pathname of the test program as the last of its args. You need specify
+ # {} only if the test program's pathname isn't the last argument in the
+ # desired command line.
+ LIST(APPEND test_command "${TEST_EXE}")
+ ELSE (test_exe_pos LESS 0)
+ # Found {} marker at test_exe_pos. Remove the {}...
+ LIST(REMOVE_AT test_command test_exe_pos)
+ # ...and replace it with the actual name of the test executable.
+ LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
+ ENDIF (test_exe_pos LESS 0)
+
+ SET_TEST_PATH(LD_LIBRARY_PATH)
+ LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command})
+
+ if(TEST_DEBUG)
+ message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
+ endif(TEST_DEBUG)
+
+ ADD_CUSTOM_COMMAND(
+ TARGET INTEGRATION_TEST_${testname}
+ POST_BUILD
+ COMMAND ${TEST_SCRIPT_CMD}
+ )
+
+ # Use CTEST? Not sure how to yet...
+ # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
+
+ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
+
+MACRO(SET_TEST_PATH LISTVAR)
+ IF(WINDOWS)
+ # We typically build/package only Release variants of third-party
+ # libraries, so append the Release staging dir in case the library being
+ # sought doesn't have a debug variant.
+ set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release)
+ ELSEIF(DARWIN)
+ # We typically build/package only Release variants of third-party
+ # libraries, so append the Release staging dir in case the library being
+ # sought doesn't have a debug variant.
+ set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
+ ELSE(WINDOWS)
+ # Linux uses a single staging directory anyway.
+ IF (STANDALONE)
+ set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
+ ELSE (STANDALONE)
+ set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
+ ENDIF (STANDALONE)
+ ENDIF(WINDOWS)
+ENDMACRO(SET_TEST_PATH)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 0901c1b7a2..748c8c2bec 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -9,10 +9,12 @@ if (WINDOWS)
NAMES python25.exe python23.exe python.exe
NO_DEFAULT_PATH # added so that cmake does not find cygwin python
PATHS
+ [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
[HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
diff --git a/indra/cmake/TemplateCheck.cmake b/indra/cmake/TemplateCheck.cmake
index fa4e387dd5..90d58d93ad 100644
--- a/indra/cmake/TemplateCheck.cmake
+++ b/indra/cmake/TemplateCheck.cmake
@@ -7,8 +7,9 @@ macro (check_message_template _target)
TARGET ${_target}
POST_BUILD
COMMAND ${PYTHON_EXECUTABLE}
- ARGS ${SCRIPTS_DIR}/template_verifier.py
- --mode=development --cache_master
- COMMENT "Verifying message template"
+ ARGS ${SCRIPTS_DIR}/md5check.py
+ 3f19d130400c547de36278a6b6f9b028
+ ${SCRIPTS_DIR}/messages/message_template.msg
+ COMMENT "Verifying message template - See http://wiki.secondlife.com/wiki/Template_verifier.py"
)
endmacro (check_message_template)
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index 32c4bc81df..df013b1665 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -3,7 +3,7 @@ include(Prebuilt)
if (NOT STANDALONE)
use_prebuilt_binary(libuuid)
- use_prebuilt_binary(vivox)
+ use_prebuilt_binary(slvoice)
use_prebuilt_binary(fontconfig)
endif(NOT STANDALONE)
diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp
index 1f15b73182..c34115ee80 100644
--- a/indra/integration_tests/llui_libtest/llui_libtest.cpp
+++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp
@@ -174,7 +174,7 @@ void export_test_floaters()
std::string delim = gDirUtilp->getDirDelimiter();
std::string xui_dir = get_xui_dir() + "en" + delim;
std::string filename;
- while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename, false))
+ while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename))
{
if (filename.find("_new.xml") != std::string::npos)
{
diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp
index be4d810860..d909516bf8 100644
--- a/indra/linux_updater/linux_updater.cpp
+++ b/indra/linux_updater/linux_updater.cpp
@@ -49,6 +49,7 @@ const guint ROTATE_IMAGE_TIMEOUT = 8000;
typedef struct _updater_app_state {
std::string app_name;
std::string url;
+ std::string file;
std::string image_dir;
std::string dest_dir;
std::string strings_dirs;
@@ -113,7 +114,7 @@ BOOL install_package(std::string package_file, std::string destination);
BOOL spawn_viewer(UpdaterAppState *app_state);
extern "C" {
- void on_window_closed(GtkWidget *sender, gpointer state);
+ void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state);
gpointer worker_thread_cb(gpointer *data);
int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow);
gboolean rotate_image_cb(gpointer data);
@@ -216,11 +217,11 @@ gboolean rotate_image_cb(gpointer data)
std::string next_image_filename(std::string& image_path)
{
std::string image_filename;
- gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename, true);
+ gDirUtilp->getNextFileInDir(image_path, "/*.jpg", image_filename);
return image_path + "/" + image_filename;
}
-void on_window_closed(GtkWidget *sender, gpointer data)
+void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data)
{
UpdaterAppState *app_state;
@@ -266,85 +267,95 @@ gpointer worker_thread_cb(gpointer data)
CURLcode result;
FILE *package_file;
GError *error = NULL;
- char *tmp_filename = NULL;
int fd;
//g_return_val_if_fail (data != NULL, NULL);
app_state = (UpdaterAppState *) data;
try {
- // create temporary file to store the package.
- fd = g_file_open_tmp
- ("secondlife-update-XXXXXX", &tmp_filename, &error);
- if (error != NULL)
- {
- llerrs << "Unable to create temporary file: "
- << error->message
- << llendl;
-
- g_error_free(error);
- throw 0;
- }
- package_file = fdopen(fd, "wb");
- if (package_file == NULL)
+ if(!app_state->url.empty())
{
- llerrs << "Failed to create temporary file: "
- << tmp_filename
- << llendl;
+ char* tmp_local_filename = NULL;
+ // create temporary file to store the package.
+ fd = g_file_open_tmp
+ ("secondlife-update-XXXXXX", &tmp_local_filename, &error);
+ if (error != NULL)
+ {
+ llerrs << "Unable to create temporary file: "
+ << error->message
+ << llendl;
- gdk_threads_enter();
- display_error(app_state->window,
- LLTrans::getString("UpdaterFailDownloadTitle"),
- LLTrans::getString("UpdaterFailUpdateDescriptive"));
- gdk_threads_leave();
- throw 0;
- }
+ g_error_free(error);
+ throw 0;
+ }
+
+ if(tmp_local_filename != NULL)
+ {
+ app_state->file = tmp_local_filename;
+ g_free(tmp_local_filename);
+ }
- // initialize curl and start downloading the package
- llinfos << "Downloading package: " << app_state->url << llendl;
+ package_file = fdopen(fd, "wb");
+ if (package_file == NULL)
+ {
+ llerrs << "Failed to create temporary file: "
+ << app_state->file.c_str()
+ << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
- curl = curl_easy_init();
- if (curl == NULL)
- {
- llerrs << "Failed to initialize libcurl" << llendl;
+ // initialize curl and start downloading the package
+ llinfos << "Downloading package: " << app_state->url << llendl;
- gdk_threads_enter();
- display_error(app_state->window,
- LLTrans::getString("UpdaterFailDownloadTitle"),
- LLTrans::getString("UpdaterFailUpdateDescriptive"));
- gdk_threads_leave();
- throw 0;
- }
+ curl = curl_easy_init();
+ if (curl == NULL)
+ {
+ llerrs << "Failed to initialize libcurl" << llendl;
+
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
+ throw 0;
+ }
- curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
- curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
- curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
- &download_progress_cb);
- curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
+ curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
+ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
+ &download_progress_cb);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
- result = curl_easy_perform(curl);
- fclose(package_file);
- curl_easy_cleanup(curl);
+ result = curl_easy_perform(curl);
+ fclose(package_file);
+ curl_easy_cleanup(curl);
- if (result)
- {
- llerrs << "Failed to download update: "
- << app_state->url
- << llendl;
+ if (result)
+ {
+ llerrs << "Failed to download update: "
+ << app_state->url
+ << llendl;
- gdk_threads_enter();
- display_error(app_state->window,
- LLTrans::getString("UpdaterFailDownloadTitle"),
- LLTrans::getString("UpdaterFailUpdateDescriptive"));
- gdk_threads_leave();
+ gdk_threads_enter();
+ display_error(app_state->window,
+ LLTrans::getString("UpdaterFailDownloadTitle"),
+ LLTrans::getString("UpdaterFailUpdateDescriptive"));
+ gdk_threads_leave();
- throw 0;
+ throw 0;
+ }
}
-
+
// now pulse the progres bar back and forth while the package is
// being unpacked
gdk_threads_enter();
@@ -357,7 +368,7 @@ gpointer worker_thread_cb(gpointer data)
// *TODO: if the destination is not writable, terminate this
// thread and show file chooser?
- if (!install_package(tmp_filename, app_state->dest_dir))
+ if (!install_package(app_state->file.c_str(), app_state->dest_dir))
{
llwarns << "Failed to install package to destination: "
<< app_state->dest_dir
@@ -392,15 +403,6 @@ gpointer worker_thread_cb(gpointer data)
app_state->failure = TRUE;
}
- // FIXME: delete package file also if delete-event is raised on window
- if (tmp_filename != NULL)
- {
- if (gDirUtilp->fileExists(tmp_filename))
- {
- LLFile::remove(tmp_filename);
- }
- }
-
gdk_threads_enter();
updater_app_quit(app_state);
gdk_threads_leave();
@@ -712,7 +714,7 @@ BOOL spawn_viewer(UpdaterAppState *app_state)
void show_usage_and_exit()
{
- std::cout << "Usage: linux-updater --url URL --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
+ std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
<< "[--image-dir PATH]"
<< std::endl;
exit(1);
@@ -728,6 +730,10 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
{
app_state->url = argv[i];
}
+ else if ((!strcmp(argv[i], "--file")) && (++i < argc))
+ {
+ app_state->file = argv[i];
+ }
else if ((!strcmp(argv[i], "--name")) && (++i < argc))
{
app_state->app_name = argv[i];
@@ -756,7 +762,7 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
}
if (app_state->app_name.empty()
- || app_state->url.empty()
+ || (app_state->url.empty() && app_state->file.empty())
|| app_state->dest_dir.empty())
{
show_usage_and_exit();
@@ -771,10 +777,10 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
int main(int argc, char **argv)
{
- UpdaterAppState app_state;
+ UpdaterAppState* app_state = new UpdaterAppState;
GThread *worker_thread;
- parse_args_and_init(argc, argv, &app_state);
+ parse_args_and_init(argc, argv, app_state);
// Initialize logger, and rename old log file
gDirUtilp->initAppDirs("SecondLife");
@@ -797,17 +803,29 @@ int main(int argc, char **argv)
gtk_init(&argc, &argv);
// create UI
- updater_app_ui_init(&app_state);
+ updater_app_ui_init(app_state);
//llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl;
// create download thread
worker_thread = g_thread_create
- (GThreadFunc(worker_thread_cb), &app_state, FALSE, NULL);
+ (GThreadFunc(worker_thread_cb), app_state, FALSE, NULL);
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
- return (app_state.failure == FALSE) ? 0 : 1;
+ // Delete the file only if created from url download.
+ if(!app_state->url.empty() && !app_state->file.empty())
+ {
+ if (gDirUtilp->fileExists(app_state->file))
+ {
+ LLFile::remove(app_state->file);
+ }
+ }
+
+ bool success = !app_state->failure;
+ delete app_state;
+ return success ? 0 : 1;
}
+
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index e869b9717c..21ec622819 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -14,7 +14,6 @@ include(LLVFS)
include_directories(
${LLAUDIO_INCLUDE_DIRS}
- ${FMOD_INCLUDE_DIR}
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
@@ -45,6 +44,10 @@ set(llaudio_HEADER_FILES
)
if (FMOD)
+ include_directories(
+ ${FMOD_INCLUDE_DIR}
+ )
+
list(APPEND llaudio_SOURCE_FILES
llaudioengine_fmod.cpp
lllistener_fmod.cpp
diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp
index 9f479189d7..0e0c80a456 100644
--- a/indra/llaudio/llvorbisencode.cpp
+++ b/indra/llaudio/llvorbisencode.cpp
@@ -120,6 +120,13 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
+ ((U32) wav_header[5] << 8)
+ wav_header[4];
+ if (chunk_length > physical_file_size - file_pos - 4)
+ {
+ infile.close();
+ error_msg = "SoundFileInvalidChunkSize";
+ return(LLVORBISENC_CHUNK_SIZE_ERR);
+ }
+
// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
diff --git a/indra/llaudio/llvorbisencode.h b/indra/llaudio/llvorbisencode.h
index d33aacf1ea..6b22a2cb59 100644
--- a/indra/llaudio/llvorbisencode.h
+++ b/indra/llaudio/llvorbisencode.h
@@ -38,6 +38,7 @@ const S32 LLVORBISENC_MULTICHANNEL_ERR = 7; // can't do stereo
const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample rate
const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size
const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long
+const S32 LLVORBISENC_CHUNK_SIZE_ERR = 11; // chunk size is wrong
const F32 LLVORBIS_CLIP_MAX_TIME = 10.0f;
const U8 LLVORBIS_CLIP_MAX_CHANNELS = 2;
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 7bad780dd8..9342a22d46 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -70,6 +70,7 @@ set(llcommon_SOURCE_FILES
llmemorystream.cpp
llmemtype.cpp
llmetrics.cpp
+ llmetricperformancetester.cpp
llmortician.cpp
lloptioninterface.cpp
llptrto.cpp
@@ -92,6 +93,7 @@ set(llcommon_SOURCE_FILES
llstringtable.cpp
llsys.cpp
llthread.cpp
+ llthreadsafequeue.cpp
lltimer.cpp
lluri.cpp
lluuid.cpp
@@ -186,6 +188,7 @@ set(llcommon_HEADER_FILES
llmemorystream.h
llmemtype.h
llmetrics.h
+ llmetricperformancetester.h
llmortician.h
llnametable.h
lloptioninterface.h
@@ -223,6 +226,7 @@ set(llcommon_HEADER_FILES
llstringtable.h
llsys.h
llthread.h
+ llthreadsafequeue.h
lltimer.h
lltreeiterators.h
lluri.h
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index b0618bfe59..95cb606240 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -245,9 +245,6 @@ const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
const U8 SIM_ACCESS_DOWN = 254;
const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
-// group constants
-const S32 MAX_AGENT_GROUPS = 25;
-
// attachment constants
const S32 MAX_AGENT_ATTACHMENTS = 38;
const U8 ATTACHMENT_ADD = 0x80;
@@ -300,6 +297,14 @@ const U32 START_LOCATION_ID_COUNT = 6;
// group constants
const U32 GROUP_MIN_SIZE = 2;
+// gMaxAgentGroups is now sent by login.cgi, which
+// looks it up from globals.xml.
+//
+// For now we need an old default value however,
+// so the viewer can be deployed ahead of login.cgi.
+//
+const S32 DEFAULT_MAX_AGENT_GROUPS = 25;
+
// radius within which a chat message is fully audible
const F32 CHAT_WHISPER_RADIUS = 10.f;
const F32 CHAT_NORMAL_RADIUS = 20.f;
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index eebd5ed0a6..39daefd1ad 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -90,6 +90,10 @@ S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2;
// the static application instance
LLApp* LLApp::sApplication = NULL;
+// Allows the generation of core files for post mortem under gdb
+// and disables crashlogger
+BOOL LLApp::sDisableCrashlogger = FALSE;
+
// Local flag for whether or not to do logging in signal handlers.
//static
BOOL LLApp::sLogInSignal = FALSE;
@@ -461,11 +465,30 @@ bool LLApp::isQuitting()
return (APP_STATUS_QUITTING == sStatus);
}
+// static
bool LLApp::isExiting()
{
return isQuitting() || isError();
}
+void LLApp::disableCrashlogger()
+{
+ // Disable Breakpad exception handler.
+ if (mExceptionHandler != 0)
+ {
+ delete mExceptionHandler;
+ mExceptionHandler = 0;
+ }
+
+ sDisableCrashlogger = TRUE;
+}
+
+// static
+bool LLApp::isCrashloggerDisabled()
+{
+ return (sDisableCrashlogger == TRUE);
+}
+
#if !LL_WINDOWS
// static
U32 LLApp::getSigChildCount()
@@ -799,6 +822,15 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
{
llwarns << "Signal handler - Flagging error status and waiting for shutdown" << llendl;
}
+
+ if (LLApp::isCrashloggerDisabled()) // Don't gracefully handle any signal, crash and core for a gdb post mortem
+ {
+ clear_signals();
+ llwarns << "Fatal signal received, not handling the crash here, passing back to operating system" << llendl;
+ raise(signum);
+ return;
+ }
+
// Flag status to ERROR, so thread_error does its work.
LLApp::setError();
// Block in the signal handler until somebody says that we're done.
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index ee1d696829..a536a06ea5 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -189,6 +189,11 @@ public:
//
virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
+ //
+ // Crash logging
+ //
+ void disableCrashlogger(); // Let the OS handle the crashes
+ static bool isCrashloggerDisabled(); // Get the here above set value
//
// Application status
@@ -280,6 +285,7 @@ protected:
static void setStatus(EAppStatus status); // Use this to change the application status.
static EAppStatus sStatus; // Reflects current application status
static BOOL sErrorThreadRunning; // Set while the error thread is running
+ static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
#if !LL_WINDOWS
static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received.
diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h
index a8cd03b42a..131b819c99 100644
--- a/indra/llcommon/lldarray.h
+++ b/indra/llcommon/lldarray.h
@@ -51,7 +51,7 @@ public:
LLDynamicArray(S32 size=0) : std::vector<Type>(size) { if (size < BlockSize) std::vector<Type>::reserve(BlockSize); }
- void reset() { std::vector<Type>::resize(0); }
+ void reset() { std::vector<Type>::clear(); }
// ACCESSORS
const Type& get(S32 index) const { return std::vector<Type>::operator[](index); }
diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp
index c45921cdec..bce87ada96 100644
--- a/indra/llcommon/llfasttimer_class.cpp
+++ b/indra/llcommon/llfasttimer_class.cpp
@@ -56,6 +56,7 @@ bool LLFastTimer::sPauseHistory = 0;
bool LLFastTimer::sResetHistory = 0;
LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
BOOL LLFastTimer::sLog = FALSE;
+std::string LLFastTimer::sLogName = "";
BOOL LLFastTimer::sMetricLog = FALSE;
LLMutex* LLFastTimer::sLogLock = NULL;
std::queue<LLSD> LLFastTimer::sLogQueue;
diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h
index 1158ac5140..eb9789682b 100644
--- a/indra/llcommon/llfasttimer_class.h
+++ b/indra/llcommon/llfasttimer_class.h
@@ -211,6 +211,7 @@ public:
static std::queue<LLSD> sLogQueue;
static BOOL sLog;
static BOOL sMetricLog;
+ static std::string sLogName;
static bool sPauseHistory;
static bool sResetHistory;
static U64 sTimerCycles;
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index 289ce0bc2c..8f02391e75 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -318,7 +318,12 @@ void llofstream::close()
if(is_open())
{
if (_Filebuffer->close() == 0)
+ {
_Myios::setstate(ios_base::failbit); /*Flawfinder: ignore*/
+ }
+ delete _Filebuffer;
+ _Filebuffer = NULL;
+ _ShouldClose = false;
}
}
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
new file mode 100644
index 0000000000..5fa3a5ea07
--- /dev/null
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -0,0 +1,254 @@
+/**
+ * @file llmetricperformancetester.cpp
+ * @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes implementation
+ *
+ * $LicenseInfo:firstyear=2004&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 "indra_constants.h"
+#include "llerror.h"
+#include "llsdserialize.h"
+#include "llstat.h"
+#include "lltreeiterators.h"
+#include "llmetricperformancetester.h"
+
+//----------------------------------------------------------------------------------------------
+// LLMetricPerformanceTesterBasic : static methods and testers management
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;
+
+/*static*/
+void LLMetricPerformanceTesterBasic::cleanClass()
+{
+ for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
+ {
+ delete iter->second ;
+ }
+ sTesterMap.clear() ;
+}
+
+/*static*/
+BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester)
+{
+ llassert_always(tester != NULL);
+ std::string name = tester->getTesterName() ;
+ if (getTester(name))
+ {
+ llerrs << "Tester name is already used by some other tester : " << name << llendl ;
+ return FALSE;
+ }
+
+ sTesterMap.insert(std::make_pair(name, tester));
+ return TRUE;
+}
+
+/*static*/
+LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name)
+{
+ // Check for the requested metric name
+ name_tester_map_t::iterator found_it = sTesterMap.find(name) ;
+ if (found_it != sTesterMap.end())
+ {
+ return found_it->second ;
+ }
+ return NULL ;
+}
+
+/*static*/
+// Return TRUE if this metric is requested or if the general default "catch all" metric is requested
+BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
+{
+ return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME)));
+}
+
+
+//----------------------------------------------------------------------------------------------
+// LLMetricPerformanceTesterBasic : Tester instance methods
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name) :
+ mName(name),
+ mCount(0)
+{
+ if (mName == std::string())
+ {
+ llerrs << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << llendl ;
+ }
+
+ mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
+}
+
+LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
+{
+}
+
+void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
+{
+ incrementCurrentCount() ;
+ (*sd)[getCurrentLabelName()]["Name"] = mName ;
+}
+
+void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
+{
+ LLMutexLock lock(LLFastTimer::sLogLock);
+ LLFastTimer::sLogQueue.push((*sd));
+}
+
+void LLMetricPerformanceTesterBasic::outputTestResults()
+{
+ LLSD sd;
+
+ preOutputTestResults(&sd) ;
+ outputTestRecord(&sd) ;
+ postOutputTestResults(&sd) ;
+}
+
+void LLMetricPerformanceTesterBasic::addMetric(std::string str)
+{
+ mMetricStrings.push_back(str) ;
+}
+
+/*virtual*/
+void LLMetricPerformanceTesterBasic::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
+{
+ resetCurrentCount() ;
+
+ std::string current_label = getCurrentLabelName();
+ BOOL in_base = (*base).has(current_label) ;
+ BOOL in_current = (*current).has(current_label) ;
+
+ while(in_base || in_current)
+ {
+ LLSD::String label = current_label ;
+
+ if(in_base && in_current)
+ {
+ *os << llformat("%s\n", label.c_str()) ;
+
+ for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
+ {
+ switch((*current)[label][ mMetricStrings[index] ].type())
+ {
+ case LLSD::TypeInteger:
+ compareTestResults(os, mMetricStrings[index],
+ (S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
+ break ;
+ case LLSD::TypeReal:
+ compareTestResults(os, mMetricStrings[index],
+ (F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
+ break;
+ default:
+ llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
+ }
+ }
+ }
+
+ incrementCurrentCount();
+ current_label = getCurrentLabelName();
+ in_base = (*base).has(current_label) ;
+ in_current = (*current).has(current_label) ;
+ }
+}
+
+/*virtual*/
+void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current)
+{
+ *os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
+ v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
+}
+
+/*virtual*/
+void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current)
+{
+ *os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
+ v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
+}
+
+//----------------------------------------------------------------------------------------------
+// LLMetricPerformanceTesterWithSession
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterWithSession::LLMetricPerformanceTesterWithSession(std::string name) :
+ LLMetricPerformanceTesterBasic(name),
+ mBaseSessionp(NULL),
+ mCurrentSessionp(NULL)
+{
+}
+
+LLMetricPerformanceTesterWithSession::~LLMetricPerformanceTesterWithSession()
+{
+ if (mBaseSessionp)
+ {
+ delete mBaseSessionp ;
+ mBaseSessionp = NULL ;
+ }
+ if (mCurrentSessionp)
+ {
+ delete mCurrentSessionp ;
+ mCurrentSessionp = NULL ;
+ }
+}
+
+/*virtual*/
+void LLMetricPerformanceTesterWithSession::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
+{
+ // Load the base session
+ resetCurrentCount() ;
+ mBaseSessionp = loadTestSession(base) ;
+
+ // Load the current session
+ resetCurrentCount() ;
+ mCurrentSessionp = loadTestSession(current) ;
+
+ if (!mBaseSessionp || !mCurrentSessionp)
+ {
+ llerrs << "Error loading test sessions." << llendl ;
+ }
+
+ // Compare
+ compareTestSessions(os) ;
+
+ // Release memory
+ if (mBaseSessionp)
+ {
+ delete mBaseSessionp ;
+ mBaseSessionp = NULL ;
+ }
+ if (mCurrentSessionp)
+ {
+ delete mCurrentSessionp ;
+ mCurrentSessionp = NULL ;
+ }
+}
+
+
+//----------------------------------------------------------------------------------------------
+// LLTestSession
+//----------------------------------------------------------------------------------------------
+
+LLMetricPerformanceTesterWithSession::LLTestSession::~LLTestSession()
+{
+}
+
diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h
new file mode 100644
index 0000000000..925010ac96
--- /dev/null
+++ b/indra/llcommon/llmetricperformancetester.h
@@ -0,0 +1,206 @@
+/**
+ * @file llmetricperformancetester.h
+ * @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes definition
+ *
+ * $LicenseInfo:firstyear=2004&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_METRICPERFORMANCETESTER_H
+#define LL_METRICPERFORMANCETESTER_H
+
+const std::string DEFAULT_METRIC_NAME("metric");
+
+/**
+ * @class LLMetricPerformanceTesterBasic
+ * @brief Performance Metric Base Class
+ */
+class LL_COMMON_API LLMetricPerformanceTesterBasic
+{
+public:
+ /**
+ * @brief Creates a basic tester instance.
+ * @param[in] name - Unique string identifying this tester instance.
+ */
+ LLMetricPerformanceTesterBasic(std::string name);
+ virtual ~LLMetricPerformanceTesterBasic();
+
+ /**
+ * @return Returns true if the instance has been added to the tester map.
+ * Need to be tested after creation of a tester instance so to know if the tester is correctly handled.
+ * A tester might not be added to the map if another tester with the same name already exists.
+ */
+ BOOL isValid() const { return mValidInstance; }
+
+ /**
+ * @brief Write a set of test results to the log LLSD.
+ */
+ void outputTestResults() ;
+
+ /**
+ * @brief Compare the test results.
+ * By default, compares the test results against the baseline one by one, item by item,
+ * in the increasing order of the LLSD record counter, starting from the first one.
+ */
+ virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
+
+ /**
+ * @return Returns the number of the test metrics in this tester instance.
+ */
+ S32 getNumberOfMetrics() const { return mMetricStrings.size() ;}
+ /**
+ * @return Returns the metric name at index
+ * @param[in] index - Index on the list of metrics managed by this tester instance.
+ */
+ std::string getMetricName(S32 index) const { return mMetricStrings[index] ;}
+
+protected:
+ /**
+ * @return Returns the name of this tester instance.
+ */
+ std::string getTesterName() const { return mName ;}
+
+ /**
+ * @brief Insert a new metric to be managed by this tester instance.
+ * @param[in] str - Unique string identifying the new metric.
+ */
+ void addMetric(std::string str) ;
+
+ /**
+ * @brief Compare test results, provided in 2 flavors: compare integers and compare floats.
+ * @param[out] os - Formatted output string holding the compared values.
+ * @param[in] metric_string - Name of the metric.
+ * @param[in] v_base - Base value of the metric.
+ * @param[in] v_current - Current value of the metric.
+ */
+ virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
+ virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
+
+ /**
+ * @brief Reset internal record count. Count starts with 1.
+ */
+ void resetCurrentCount() { mCount = 1; }
+ /**
+ * @brief Increment internal record count.
+ */
+ void incrementCurrentCount() { mCount++; }
+ /**
+ * @return Returns the label to be used for the current count. It's "TesterName"-"Count".
+ */
+ std::string getCurrentLabelName() const { return llformat("%s-%d", mName.c_str(), mCount) ;}
+
+ /**
+ * @brief Write a test record to the LLSD. Implementers need to overload this method.
+ * @param[out] sd - The LLSD record to store metric data into.
+ */
+ virtual void outputTestRecord(LLSD* sd) = 0 ;
+
+private:
+ void preOutputTestResults(LLSD* sd) ;
+ void postOutputTestResults(LLSD* sd) ;
+
+ std::string mName ; // Name of this tester instance
+ S32 mCount ; // Current record count
+ BOOL mValidInstance; // TRUE if the instance is managed by the map
+ std::vector< std::string > mMetricStrings ; // Metrics strings
+
+// Static members managing the collection of testers
+public:
+ // Map of all the tester instances in use
+ typedef std::map< std::string, LLMetricPerformanceTesterBasic* > name_tester_map_t;
+ static name_tester_map_t sTesterMap ;
+
+ /**
+ * @return Returns a pointer to the tester
+ * @param[in] name - Name of the tester instance queried.
+ */
+ static LLMetricPerformanceTesterBasic* getTester(std::string name) ;
+
+ /**
+ * @return Returns TRUE if that metric *or* the default catch all metric has been requested to be logged
+ * @param[in] name - Name of the tester queried.
+ */
+ static BOOL isMetricLogRequested(std::string name);
+
+ /**
+ * @return Returns TRUE if there's a tester defined, FALSE otherwise.
+ */
+ static BOOL hasMetricPerformanceTesters() { return !sTesterMap.empty() ;}
+ /**
+ * @brief Delete all testers and reset the tester map
+ */
+ static void cleanClass() ;
+
+private:
+ // Add a tester to the map. Returns false if adding fails.
+ static BOOL addTester(LLMetricPerformanceTesterBasic* tester) ;
+};
+
+/**
+ * @class LLMetricPerformanceTesterWithSession
+ * @brief Performance Metric Class with custom session
+ */
+class LL_COMMON_API LLMetricPerformanceTesterWithSession : public LLMetricPerformanceTesterBasic
+{
+public:
+ /**
+ * @param[in] name - Unique string identifying this tester instance.
+ */
+ LLMetricPerformanceTesterWithSession(std::string name);
+ virtual ~LLMetricPerformanceTesterWithSession();
+
+ /**
+ * @brief Compare the test results.
+ * This will be loading the base and current sessions and compare them using the virtual
+ * abstract methods loadTestSession() and compareTestSessions()
+ */
+ virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
+
+protected:
+ /**
+ * @class LLMetricPerformanceTesterWithSession::LLTestSession
+ * @brief Defines an interface for the two abstract virtual functions loadTestSession() and compareTestSessions()
+ */
+ class LL_COMMON_API LLTestSession
+ {
+ public:
+ virtual ~LLTestSession() ;
+ };
+
+ /**
+ * @brief Convert an LLSD log into a test session.
+ * @param[in] log - The LLSD record
+ * @return Returns the record as a test session
+ */
+ virtual LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) = 0;
+
+ /**
+ * @brief Compare the base session and the target session. Assumes base and current sessions have been loaded.
+ * @param[out] os - The comparison result as a standard stream
+ */
+ virtual void compareTestSessions(std::ofstream* os) = 0;
+
+ LLTestSession* mBaseSessionp;
+ LLTestSession* mCurrentSessionp;
+};
+
+#endif
+
diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp
index 99308c94e7..81e5f8820d 100644
--- a/indra/llcommon/llprocesslauncher.cpp
+++ b/indra/llcommon/llprocesslauncher.cpp
@@ -58,6 +58,11 @@ void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
mWorkingDir = dir;
}
+const std::string& LLProcessLauncher::getExecutable() const
+{
+ return mExecutable;
+}
+
void LLProcessLauncher::clearArguments()
{
mLaunchArguments.clear();
diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h
index 479aeb664a..954c249147 100644
--- a/indra/llcommon/llprocesslauncher.h
+++ b/indra/llcommon/llprocesslauncher.h
@@ -47,6 +47,8 @@ public:
void setExecutable(const std::string &executable);
void setWorkingDirectory(const std::string &dir);
+ const std::string& getExecutable() const;
+
void clearArguments();
void addArgument(const std::string &arg);
void addArgument(const char *arg);
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 00c94404d4..10cdc7087b 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -635,6 +635,26 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const
}
}
+//static
+void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
+{
+#if LL_WINDOWS
+ MEMORYSTATUSEX state;
+ state.dwLength = sizeof(state);
+ GlobalMemoryStatusEx(&state);
+
+ avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ;
+ avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ;
+
+#else
+ //do not know how to collect available memory info for other systems.
+ //leave it blank here for now.
+
+ avail_physical_mem_kb = -1 ;
+ avail_virtual_mem_kb = -1 ;
+#endif
+}
+
void LLMemoryInfo::stream(std::ostream& s) const
{
#if LL_WINDOWS
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 39af74e5c8..41a4f25000 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -114,6 +114,9 @@ public:
** be returned.
*/
U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
+
+ //get the available memory infomation in KiloBytes.
+ static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
};
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index d7b7c3699c..49d05ef411 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -63,9 +63,6 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
{
LLThread *threadp = (LLThread *)datap;
- // Set thread state to running
- threadp->mStatus = RUNNING;
-
// Run the user supplied function
threadp->run();
@@ -147,26 +144,45 @@ void LLThread::shutdown()
{
// This thread just wouldn't stop, even though we gave it time
llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
+ // Put a stake in its heart.
+ apr_thread_exit(mAPRThreadp, -1);
return;
}
mAPRThreadp = NULL;
}
delete mRunCondition;
+ mRunCondition = 0;
- if (mIsLocalPool)
+ if (mIsLocalPool && mAPRPoolp)
{
apr_pool_destroy(mAPRPoolp);
+ mAPRPoolp = 0;
}
}
void LLThread::start()
{
- apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
+ llassert(isStopped());
+
+ // Set thread state to running
+ mStatus = RUNNING;
- // We won't bother joining
- apr_thread_detach(mAPRThreadp);
+ apr_status_t status =
+ apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
+
+ if(status == APR_SUCCESS)
+ {
+ // We won't bother joining
+ apr_thread_detach(mAPRThreadp);
+ }
+ else
+ {
+ mStatus = STOPPED;
+ llwarns << "failed to start thread " << mName << llendl;
+ ll_apr_warn_status(status);
+ }
}
//============================================================================
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
new file mode 100644
index 0000000000..8a73e632a9
--- /dev/null
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file llthread.cpp
+ *
+ * $LicenseInfo:firstyear=2004&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 <apr_pools.h>
+#include <apr_queue.h>
+#include "llthreadsafequeue.h"
+
+
+
+// LLThreadSafeQueueImplementation
+//-----------------------------------------------------------------------------
+
+
+LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity):
+ mOwnsPool(pool == 0),
+ mPool(pool),
+ mQueue(0)
+{
+ if(mOwnsPool) {
+ apr_status_t status = apr_pool_create(&mPool, 0);
+ if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool");
+ } else {
+ ; // No op.
+ }
+
+ apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
+ if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue");
+}
+
+
+LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
+{
+ if(mQueue != 0) {
+ if(apr_queue_size(mQueue) != 0) llwarns <<
+ "terminating queue which still contains " << apr_queue_size(mQueue) <<
+ " elements;" << "memory will be leaked" << LL_ENDL;
+ apr_queue_term(mQueue);
+ }
+ if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool);
+}
+
+
+void LLThreadSafeQueueImplementation::pushFront(void * element)
+{
+ apr_status_t status = apr_queue_push(mQueue, element);
+
+ if(status == APR_EINTR) {
+ throw LLThreadSafeQueueInterrupt();
+ } else if(status != APR_SUCCESS) {
+ throw LLThreadSafeQueueError("push failed");
+ } else {
+ ; // Success.
+ }
+}
+
+
+bool LLThreadSafeQueueImplementation::tryPushFront(void * element){
+ return apr_queue_trypush(mQueue, element) == APR_SUCCESS;
+}
+
+
+void * LLThreadSafeQueueImplementation::popBack(void)
+{
+ void * element;
+ apr_status_t status = apr_queue_pop(mQueue, &element);
+
+ if(status == APR_EINTR) {
+ throw LLThreadSafeQueueInterrupt();
+ } else if(status != APR_SUCCESS) {
+ throw LLThreadSafeQueueError("pop failed");
+ } else {
+ return element;
+ }
+}
+
+
+bool LLThreadSafeQueueImplementation::tryPopBack(void *& element)
+{
+ return apr_queue_trypop(mQueue, &element) == APR_SUCCESS;
+}
+
+
+size_t LLThreadSafeQueueImplementation::size()
+{
+ return apr_queue_size(mQueue);
+}
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
new file mode 100644
index 0000000000..58cac38769
--- /dev/null
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -0,0 +1,205 @@
+/**
+ * @file llthreadsafequeue.h
+ * @brief Base classes for thread, mutex and condition handling.
+ *
+ * $LicenseInfo:firstyear=2004&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_LLTHREADSAFEQUEUE_H
+#define LL_LLTHREADSAFEQUEUE_H
+
+
+#include <string>
+#include <stdexcept>
+
+
+struct apr_pool_t; // From apr_pools.h
+class LLThreadSafeQueueImplementation; // See below.
+
+
+//
+// A general queue exception.
+//
+class LL_COMMON_API LLThreadSafeQueueError:
+public std::runtime_error
+{
+public:
+ LLThreadSafeQueueError(std::string const & message):
+ std::runtime_error(message)
+ {
+ ; // No op.
+ }
+};
+
+
+//
+// An exception raised when blocking operations are interrupted.
+//
+class LL_COMMON_API LLThreadSafeQueueInterrupt:
+ public LLThreadSafeQueueError
+{
+public:
+ LLThreadSafeQueueInterrupt(void):
+ LLThreadSafeQueueError("queue operation interrupted")
+ {
+ ; // No op.
+ }
+};
+
+
+struct apr_queue_t; // From apr_queue.h
+
+
+//
+// Implementation details.
+//
+class LL_COMMON_API LLThreadSafeQueueImplementation
+{
+public:
+ LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity);
+ ~LLThreadSafeQueueImplementation();
+ void pushFront(void * element);
+ bool tryPushFront(void * element);
+ void * popBack(void);
+ bool tryPopBack(void *& element);
+ size_t size();
+
+private:
+ bool mOwnsPool;
+ apr_pool_t * mPool;
+ apr_queue_t * mQueue;
+};
+
+
+//
+// Implements a thread safe FIFO.
+//
+template<typename ElementT>
+class LLThreadSafeQueue
+{
+public:
+ typedef ElementT value_type;
+
+ // If the pool is set to NULL one will be allocated and managed by this
+ // queue.
+ LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024);
+
+ // Add an element to the front of queue (will block if the queue has
+ // reached capacity).
+ //
+ // This call will raise an interrupt error if the queue is deleted while
+ // the caller is blocked.
+ void pushFront(ElementT const & element);
+
+ // Try to add an element to the front ofqueue without blocking. Returns
+ // true only if the element was actually added.
+ bool tryPushFront(ElementT const & element);
+
+ // Pop the element at the end of the queue (will block if the queue is
+ // empty).
+ //
+ // This call will raise an interrupt error if the queue is deleted while
+ // the caller is blocked.
+ ElementT popBack(void);
+
+ // Pop an element from the end of the queue if there is one available.
+ // Returns true only if an element was popped.
+ bool tryPopBack(ElementT & element);
+
+ // Returns the size of the queue.
+ size_t size();
+
+private:
+ LLThreadSafeQueueImplementation mImplementation;
+};
+
+
+
+// LLThreadSafeQueue
+//-----------------------------------------------------------------------------
+
+
+template<typename ElementT>
+LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity):
+ mImplementation(pool, capacity)
+{
+ ; // No op.
+}
+
+
+template<typename ElementT>
+void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
+{
+ ElementT * elementCopy = new ElementT(element);
+ try {
+ mImplementation.pushFront(elementCopy);
+ } catch (LLThreadSafeQueueInterrupt) {
+ delete elementCopy;
+ throw;
+ }
+}
+
+
+template<typename ElementT>
+bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
+{
+ ElementT * elementCopy = new ElementT(element);
+ bool result = mImplementation.tryPushFront(elementCopy);
+ if(!result) delete elementCopy;
+ return result;
+}
+
+
+template<typename ElementT>
+ElementT LLThreadSafeQueue<ElementT>::popBack(void)
+{
+ ElementT * element = reinterpret_cast<ElementT *> (mImplementation.popBack());
+ ElementT result(*element);
+ delete element;
+ return result;
+}
+
+
+template<typename ElementT>
+bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element)
+{
+ void * storedElement;
+ bool result = mImplementation.tryPopBack(storedElement);
+ if(result) {
+ ElementT * elementPtr = reinterpret_cast<ElementT *>(storedElement);
+ element = *elementPtr;
+ delete elementPtr;
+ } else {
+ ; // No op.
+ }
+ return result;
+}
+
+
+template<typename ElementT>
+size_t LLThreadSafeQueue<ElementT>::size(void)
+{
+ return mImplementation.size();
+}
+
+
+#endif
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 12bddbfeed..b209e4aa38 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -28,10 +28,14 @@
#define LL_LLVERSIONVIEWER_H
const S32 LL_VERSION_MAJOR = 2;
-const S32 LL_VERSION_MINOR = 3;
+const S32 LL_VERSION_MINOR = 4;
const S32 LL_VERSION_PATCH = 0;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";
+#if LL_DARWIN
+const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.snowglobe.viewer";
+#endif
+
#endif
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index 5ea4a236b5..835664c60f 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -30,6 +30,9 @@
#include "llimagedimensionsinfo.h"
+// Value is true if one of Libjpeg's functions has encountered an error while working.
+static bool sJpegErrorEncountered = false;
+
bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec)
{
clean();
@@ -101,9 +104,17 @@ bool LLImageDimensionsInfo::getImageDimensionsPng()
return true;
}
+// Called instead of exit() if Libjpeg encounters an error.
+void on_jpeg_error(j_common_ptr cinfo)
+{
+ (void) cinfo;
+ sJpegErrorEncountered = true;
+ llwarns << "Libjpeg has encountered an error!" << llendl;
+}
bool LLImageDimensionsInfo::getImageDimensionsJpeg()
{
+ sJpegErrorEncountered = false;
clean();
FILE *fp = fopen (mSrcFilename.c_str(), "rb");
if (fp == NULL)
@@ -115,6 +126,9 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
jpeg_error_mgr jerr;
jpeg_decompress_struct cinfo;
cinfo.err = jpeg_std_error(&jerr);
+ // Call our function instead of exit() if Libjpeg encounters an error.
+ // This is done to avoid crash in this case (STORM-472).
+ cinfo.err->error_exit = on_jpeg_error;
jpeg_create_decompress (&cinfo);
jpeg_stdio_src (&cinfo, fp);
@@ -128,6 +142,6 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
jpeg_destroy_decompress(&cinfo);
fclose(fp);
- return true;
+ return !sJpegErrorEncountered;
}
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index c8c866b7f2..d005aaf29f 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -30,6 +30,8 @@
#include "lldir.h"
#include "llimagej2c.h"
#include "llmemtype.h"
+#include "lltimer.h"
+#include "llmath.h"
typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
@@ -51,6 +53,10 @@ LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
const char* fallbackEngineInfoLLImageJ2CImpl();
+// Test data gathering handle
+LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
+const std::string sTesterName("ImageCompressionTester");
+
//static
//Loads the required "create", "destroy" and "engineinfo" functions needed
void LLImageJ2C::openDSO()
@@ -71,8 +77,8 @@ void LLImageJ2C::openDSO()
#endif
dso_path = gDirUtilp->findFile(dso_name,
- gDirUtilp->getAppRODataDir(),
- gDirUtilp->getExecutableDir());
+ gDirUtilp->getAppRODataDir(),
+ gDirUtilp->getExecutableDir());
j2cimpl_dso_handle = NULL;
j2cimpl_dso_memory_pool = NULL;
@@ -102,7 +108,7 @@ void LLImageJ2C::openDSO()
//so lets check for a destruction function
rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
j2cimpl_dso_handle,
- "destroyLLImageJ2CKDU");
+ "destroyLLImageJ2CKDU");
if ( rv == APR_SUCCESS )
{
//we've loaded the destroy function ok
@@ -195,6 +201,17 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
{ // Array size is MAX_DISCARD_LEVEL+1
mDataSizes[i] = 0;
}
+
+ // If that test log has ben requested but not yet created, create it
+ if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
+ {
+ sTesterp = new LLImageCompressionTester() ;
+ if (!sTesterp->isValid())
+ {
+ delete sTesterp;
+ sTesterp = NULL;
+ }
+ }
}
// virtual
@@ -280,6 +297,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
// Returns TRUE to mean done, whether successful or not.
BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
{
+ LLTimer elapsed;
LLMemType mt1(mMemType);
BOOL res = TRUE;
@@ -318,6 +336,21 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
LLImage::setLastError(mLastError);
}
+ LLImageCompressionTester* tester = (LLImageCompressionTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
+ {
+ // Decompression stat gathering
+ // Note that we *do not* take into account the decompression failures data so we might overestimate the time spent processing
+
+ // Always add the decompression time to the stat
+ tester->updateDecompressionStats(elapsed.getElapsedTimeF32()) ;
+ if (res)
+ {
+ // The whole data stream is finally decompressed when res is returned as TRUE
+ tester->updateDecompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
+ }
+ }
+
return res;
}
@@ -330,6 +363,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
{
+ LLTimer elapsed;
LLMemType mt1(mMemType);
resetLastError();
BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
@@ -337,6 +371,22 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text,
{
LLImage::setLastError(mLastError);
}
+
+ LLImageCompressionTester* tester = (LLImageCompressionTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
+ {
+ // Compression stat gathering
+ // Note that we *do not* take into account the compression failures cases so we night overestimate the time spent processing
+
+ // Always add the compression time to the stat
+ tester->updateCompressionStats(elapsed.getElapsedTimeF32()) ;
+ if (res)
+ {
+ // The whole data stream is finally compressed when res is returned as TRUE
+ tester->updateCompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
+ }
+ }
+
return res;
}
@@ -540,3 +590,125 @@ void LLImageJ2C::updateRawDiscardLevel()
LLImageJ2CImpl::~LLImageJ2CImpl()
{
}
+
+//----------------------------------------------------------------------------------------------
+// Start of LLImageCompressionTester
+//----------------------------------------------------------------------------------------------
+LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTesterBasic(sTesterName)
+{
+ addMetric("Time Decompression (s)");
+ addMetric("Volume In Decompression (kB)");
+ addMetric("Volume Out Decompression (kB)");
+ addMetric("Decompression Ratio (x:1)");
+ addMetric("Perf Decompression (kB/s)");
+
+ addMetric("Time Compression (s)");
+ addMetric("Volume In Compression (kB)");
+ addMetric("Volume Out Compression (kB)");
+ addMetric("Compression Ratio (x:1)");
+ addMetric("Perf Compression (kB/s)");
+
+ mRunBytesInDecompression = 0;
+ mRunBytesInCompression = 0;
+
+ mTotalBytesInDecompression = 0;
+ mTotalBytesOutDecompression = 0;
+ mTotalBytesInCompression = 0;
+ mTotalBytesOutCompression = 0;
+
+ mTotalTimeDecompression = 0.0f;
+ mTotalTimeCompression = 0.0f;
+}
+
+LLImageCompressionTester::~LLImageCompressionTester()
+{
+ LLImageJ2C::sTesterp = NULL;
+}
+
+//virtual
+void LLImageCompressionTester::outputTestRecord(LLSD *sd)
+{
+ std::string currentLabel = getCurrentLabelName();
+
+ F32 decompressionPerf = 0.0f;
+ F32 compressionPerf = 0.0f;
+ F32 decompressionRate = 0.0f;
+ F32 compressionRate = 0.0f;
+
+ F32 totalkBInDecompression = (F32)(mTotalBytesInDecompression) / 1000.0;
+ F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.0;
+ F32 totalkBInCompression = (F32)(mTotalBytesInCompression) / 1000.0;
+ F32 totalkBOutCompression = (F32)(mTotalBytesOutCompression) / 1000.0;
+
+ if (!is_approx_zero(mTotalTimeDecompression))
+ {
+ decompressionPerf = totalkBInDecompression / mTotalTimeDecompression;
+ }
+ if (!is_approx_zero(totalkBInDecompression))
+ {
+ decompressionRate = totalkBOutDecompression / totalkBInDecompression;
+ }
+ if (!is_approx_zero(mTotalTimeCompression))
+ {
+ compressionPerf = totalkBInCompression / mTotalTimeCompression;
+ }
+ if (!is_approx_zero(totalkBOutCompression))
+ {
+ compressionRate = totalkBInCompression / totalkBOutCompression;
+ }
+
+ (*sd)[currentLabel]["Time Decompression (s)"] = (LLSD::Real)mTotalTimeDecompression;
+ (*sd)[currentLabel]["Volume In Decompression (kB)"] = (LLSD::Real)totalkBInDecompression;
+ (*sd)[currentLabel]["Volume Out Decompression (kB)"]= (LLSD::Real)totalkBOutDecompression;
+ (*sd)[currentLabel]["Decompression Ratio (x:1)"] = (LLSD::Real)decompressionRate;
+ (*sd)[currentLabel]["Perf Decompression (kB/s)"] = (LLSD::Real)decompressionPerf;
+
+ (*sd)[currentLabel]["Time Compression (s)"] = (LLSD::Real)mTotalTimeCompression;
+ (*sd)[currentLabel]["Volume In Compression (kB)"] = (LLSD::Real)totalkBInCompression;
+ (*sd)[currentLabel]["Volume Out Compression (kB)"] = (LLSD::Real)totalkBOutCompression;
+ (*sd)[currentLabel]["Compression Ratio (x:1)"] = (LLSD::Real)compressionRate;
+ (*sd)[currentLabel]["Perf Compression (kB/s)"] = (LLSD::Real)compressionPerf;
+}
+
+void LLImageCompressionTester::updateCompressionStats(const F32 deltaTime)
+{
+ mTotalTimeCompression += deltaTime;
+}
+
+void LLImageCompressionTester::updateCompressionStats(const S32 bytesCompress, const S32 bytesRaw)
+{
+ mTotalBytesInCompression += bytesRaw;
+ mRunBytesInCompression += bytesRaw;
+ mTotalBytesOutCompression += bytesCompress;
+ if (mRunBytesInCompression > (1000000))
+ {
+ // Output everything
+ outputTestResults();
+ // Reset the compression data of the run
+ mRunBytesInCompression = 0;
+ }
+}
+
+void LLImageCompressionTester::updateDecompressionStats(const F32 deltaTime)
+{
+ mTotalTimeDecompression += deltaTime;
+}
+
+void LLImageCompressionTester::updateDecompressionStats(const S32 bytesIn, const S32 bytesOut)
+{
+ mTotalBytesInDecompression += bytesIn;
+ mRunBytesInDecompression += bytesIn;
+ mTotalBytesOutDecompression += bytesOut;
+ if (mRunBytesInDecompression > (1000000))
+ {
+ // Output everything
+ outputTestResults();
+ // Reset the decompression data of the run
+ mRunBytesInDecompression = 0;
+ }
+}
+
+//----------------------------------------------------------------------------------------------
+// End of LLTexturePipelineTester
+//----------------------------------------------------------------------------------------------
+
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index cdb3faa207..cc3dabd7d8 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -29,8 +29,11 @@
#include "llimage.h"
#include "llassettype.h"
+#include "llmetricperformancetester.h"
class LLImageJ2CImpl;
+class LLImageCompressionTester ;
+
class LLImageJ2C : public LLImageFormatted
{
protected:
@@ -72,11 +75,12 @@ public:
static void openDSO();
static void closeDSO();
static std::string getEngineInfo();
-
+
protected:
friend class LLImageJ2CImpl;
friend class LLImageJ2COJ;
friend class LLImageJ2CKDU;
+ friend class LLImageCompressionTester;
void decodeFailed();
void updateRawDiscardLevel();
@@ -90,6 +94,9 @@ protected:
BOOL mReversible;
LLImageJ2CImpl *mImpl;
std::string mLastError;
+
+ // Image compression/decompression tester
+ static LLImageCompressionTester* sTesterp;
};
// Derive from this class to implement JPEG2000 decoding
@@ -118,4 +125,40 @@ protected:
#define LINDEN_J2C_COMMENT_PREFIX "LL_"
+//
+// This class is used for performance data gathering only.
+// Tracks the image compression / decompression data,
+// records and outputs them to the log file.
+//
+class LLImageCompressionTester : public LLMetricPerformanceTesterBasic
+{
+ public:
+ LLImageCompressionTester();
+ ~LLImageCompressionTester();
+
+ void updateDecompressionStats(const F32 deltaTime) ;
+ void updateDecompressionStats(const S32 bytesIn, const S32 bytesOut) ;
+ void updateCompressionStats(const F32 deltaTime) ;
+ void updateCompressionStats(const S32 bytesIn, const S32 bytesOut) ;
+
+ protected:
+ /*virtual*/ void outputTestRecord(LLSD* sd);
+
+ private:
+ //
+ // Data size
+ //
+ U32 mTotalBytesInDecompression; // Total bytes fed to decompressor
+ U32 mTotalBytesOutDecompression; // Total bytes produced by decompressor
+ U32 mTotalBytesInCompression; // Total bytes fed to compressor
+ U32 mTotalBytesOutCompression; // Total bytes produced by compressor
+ U32 mRunBytesInDecompression; // Bytes fed to decompressor in this run
+ U32 mRunBytesInCompression; // Bytes fed to compressor in this run
+ //
+ // Time
+ //
+ F32 mTotalTimeDecompression; // Total time spent in computing decompression
+ F32 mTotalTimeCompression; // Total time spent in computing compression
+ };
+
#endif
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 2f2d9099a3..7396117d84 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -286,18 +286,8 @@ public:
}
// No information in header, make a guess
- if (status == 503)
- {
- // ...service unavailable, retry soon
- const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
- return now + SERVICE_UNAVAILABLE_DELAY;
- }
- else
- {
- // ...other unexpected error
- const F64 DEFAULT_DELAY = 3600.0; // 1 hour
- return now + DEFAULT_DELAY;
- }
+ const F64 DEFAULT_DELAY = 120.0; // 2 mintues
+ return now + DEFAULT_DELAY;
}
};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index c0edd92bc1..6ea63809f8 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -610,41 +610,46 @@ void LLGLManager::shutdownGL()
void LLGLManager::initExtensions()
{
#if LL_MESA_HEADLESS
-# if GL_ARB_multitexture
+# ifdef GL_ARB_multitexture
mHasMultitexture = TRUE;
# else
mHasMultitexture = FALSE;
# endif
-# if GL_ARB_texture_env_combine
+# ifdef GL_ARB_texture_env_combine
mHasARBEnvCombine = TRUE;
# else
mHasARBEnvCombine = FALSE;
# endif
-# if GL_ARB_texture_compression
+# ifdef GL_ARB_texture_compression
mHasCompressedTextures = TRUE;
# else
mHasCompressedTextures = FALSE;
# endif
-# if GL_ARB_vertex_buffer_object
+# ifdef GL_ARB_vertex_buffer_object
mHasVertexBufferObject = TRUE;
# else
mHasVertexBufferObject = FALSE;
# endif
-# if GL_EXT_framebuffer_object
+# ifdef GL_EXT_framebuffer_object
mHasFramebufferObject = TRUE;
# else
mHasFramebufferObject = FALSE;
# endif
-# if GL_EXT_framebuffer_multisample
+# ifdef GL_EXT_framebuffer_multisample
mHasFramebufferMultisample = TRUE;
# else
mHasFramebufferMultisample = FALSE;
# endif
-# if GL_ARB_draw_buffers
+# ifdef GL_ARB_draw_buffers
mHasDrawBuffers = TRUE;
#else
mHasDrawBuffers = FALSE;
# endif
+# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
+ mHasDepthClamp = TRUE;
+#else
+ mHasDepthClamp = FALSE;
+#endif
# if GL_EXT_blend_func_separate
mHasBlendFuncSeparate = TRUE;
#else
@@ -671,6 +676,7 @@ void LLGLManager::initExtensions()
mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression");
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", 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
mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts)
&& ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
@@ -694,6 +700,7 @@ void LLGLManager::initExtensions()
if (getenv("LL_GL_NOEXT"))
{
//mHasMultitexture = FALSE; // NEEDED!
+ mHasDepthClamp = FALSE;
mHasARBEnvCombine = FALSE;
mHasCompressedTextures = FALSE;
mHasVertexBufferObject = FALSE;
@@ -755,6 +762,7 @@ void LLGLManager::initExtensions()
if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE;
if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE;
if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S
+ if (strchr(blacklist,'v')) mHasDepthClamp = FALSE;
}
#endif // LL_LINUX || LL_SOLARIS
@@ -1047,6 +1055,33 @@ void flush_glerror()
glGetError();
}
+//this function outputs gl error to the log file, does not crash the code.
+void log_glerror()
+{
+ if (LL_UNLIKELY(!gGLManager.mInited))
+ {
+ return ;
+ }
+ // Create or update texture to be used with this data
+ GLenum error;
+ error = glGetError();
+ while (LL_UNLIKELY(error))
+ {
+ GLubyte const * gl_error_msg = gluErrorString(error);
+ if (NULL != gl_error_msg)
+ {
+ llwarns << "GL Error: " << error << " GL Error String: " << gl_error_msg << llendl ;
+ }
+ else
+ {
+ // gluErrorString returns NULL for some extensions' error codes.
+ // you'll probably have to grep for the number in glext.h.
+ llwarns << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << llendl;
+ }
+ error = glGetError();
+ }
+}
+
void do_assert_glerror()
{
if (LL_UNLIKELY(!gGLManager.mInited))
@@ -2037,7 +2072,7 @@ void LLGLDepthTest::checkState()
}
}
-LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P)
+LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P)
{
for (U32 i = 0; i < 4; i++)
{
@@ -2050,7 +2085,7 @@ LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P)
glMatrixMode(GL_MODELVIEW);
}
-LLGLClampToFarClip::~LLGLClampToFarClip()
+LLGLSquashToFarClip::~LLGLSquashToFarClip()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 5e8965c06a..85fab7a0f8 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -92,6 +92,7 @@ public:
BOOL mHasOcclusionQuery;
BOOL mHasPointParameters;
BOOL mHasDrawBuffers;
+ BOOL mHasDepthClamp;
BOOL mHasTextureRectangle;
// Other extensions.
@@ -157,6 +158,7 @@ void rotate_quat(LLQuaternion& rotation);
void flush_glerror(); // Flush GL errors when we know we're handling them correctly.
+void log_glerror();
void assert_glerror();
void clear_glerror();
@@ -315,11 +317,11 @@ private:
leaves this class.
Does not stack.
*/
-class LLGLClampToFarClip
+class LLGLSquashToFarClip
{
public:
- LLGLClampToFarClip(glh::matrix4f projection);
- ~LLGLClampToFarClip();
+ LLGLSquashToFarClip(glh::matrix4f projection);
+ ~LLGLSquashToFarClip();
};
/*
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index 5a34b46d0c..576969b81a 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -829,5 +829,15 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#endif // LL_MESA / LL_WINDOWS / LL_DARWIN
+// Even when GL_ARB_depth_clamp is available in the driver, the (correct)
+// headers, and therefore GL_DEPTH_CLAMP might not be defined.
+// In that case GL_DEPTH_CLAMP_NV should be defined, but why not just
+// use the known numeric.
+//
+// To avoid #ifdef's in the code. Just define this here.
+#ifndef GL_DEPTH_CLAMP
+// Probably (still) called GL_DEPTH_CLAMP_NV.
+#define GL_DEPTH_CLAMP 0x864F
+#endif
#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 72dd283bc7..65940cb067 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1069,6 +1069,8 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
checkTexSize(true) ;
llcallstacks << fb_x << " : " << fb_y << " : " << x_pos << " : " << y_pos << " : " << width << " : " << height <<
" : " << (S32)mComponents << llcallstacksendl ;
+
+ log_glerror() ;
}
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index e26acd53a3..8eb160f4e7 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -431,6 +431,9 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
if (gGL.mMaxAnisotropy < 1.f)
{
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy);
+
+ llinfos << "gGL.mMaxAnisotropy: " << gGL.mMaxAnisotropy << llendl ;
+ gGL.mMaxAnisotropy = llmax(1.f, gGL.mMaxAnisotropy) ;
}
glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy);
}
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index de4501dd0f..02160b09c4 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -27,7 +27,7 @@
#include "linden_common.h"
#include <boost/static_assert.hpp>
-
+#include "llsys.h"
#include "llvertexbuffer.h"
// #include "llrender.h"
#include "llglheaders.h"
@@ -854,6 +854,14 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
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;
+
//--------------------
//print out more debug info before crash
llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
@@ -875,6 +883,8 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
if (!mMappedIndexData)
{
+ log_glerror();
+
GLint buff;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLIndices)
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 179b32098a..9e4849c58b 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -203,7 +203,8 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::draw()
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
- gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get(),true);
+ F32 alpha = getCurrentTransparency();
+ gl_rect_2d(0,0,width - 1 ,height - 1,mHeaderBGColor.get() % alpha,true);
LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
bool collapsible = (parent && parent->getCollapsible());
@@ -456,8 +457,7 @@ BOOL LLAccordionCtrlTab::handleMouseDown(S32 x, S32 y, MASK mask)
{
if(y >= (getRect().getHeight() - HEADER_HEIGHT) )
{
- LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- header->setFocus(true);
+ mHeader->setFocus(true);
changeOpenClose(getDisplayChildren());
//reset stored state
@@ -509,10 +509,9 @@ void LLAccordionCtrlTab::setAccordionView(LLView* panel)
std::string LLAccordionCtrlTab::getTitle() const
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- return header->getTitle();
+ return mHeader->getTitle();
}
else
{
@@ -522,57 +521,51 @@ std::string LLAccordionCtrlTab::getTitle() const
void LLAccordionCtrlTab::setTitle(const std::string& title, const std::string& hl)
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- header->setTitle(title, hl);
+ mHeader->setTitle(title, hl);
}
}
void LLAccordionCtrlTab::setTitleFontStyle(std::string style)
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- header->setTitleFontStyle(style);
+ mHeader->setTitleFontStyle(style);
}
}
void LLAccordionCtrlTab::setTitleColor(LLUIColor color)
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- header->setTitleColor(color);
+ mHeader->setTitleColor(color);
}
}
boost::signals2::connection LLAccordionCtrlTab::setFocusReceivedCallback(const focus_signal_t::slot_type& cb)
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- return header->setFocusReceivedCallback(cb);
+ return mHeader->setFocusReceivedCallback(cb);
}
return boost::signals2::connection();
}
boost::signals2::connection LLAccordionCtrlTab::setFocusLostCallback(const focus_signal_t::slot_type& cb)
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- return header->setFocusLostCallback(cb);
+ return mHeader->setFocusLostCallback(cb);
}
return boost::signals2::connection();
}
void LLAccordionCtrlTab::setSelected(bool is_selected)
{
- LLAccordionCtrlTabHeader* header = findChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if (header)
+ if (mHeader)
{
- header->setSelected(is_selected);
+ mHeader->setSelected(is_selected);
}
}
@@ -776,8 +769,7 @@ S32 LLAccordionCtrlTab::notify(const LLSD& info)
BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
- LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- if( !header->hasFocus() )
+ if( !mHeader->hasFocus() )
return LLUICtrl::handleKey(key, mask, called_from_parent);
if ( (key == KEY_RETURN )&& mask == MASK_NONE)
@@ -830,15 +822,19 @@ BOOL LLAccordionCtrlTab::handleKey(KEY key, MASK mask, BOOL called_from_parent)
void LLAccordionCtrlTab::showAndFocusHeader()
{
- LLAccordionCtrlTabHeader* header = getChild<LLAccordionCtrlTabHeader>(DD_HEADER_NAME);
- header->setFocus(true);
- header->setSelected(mSelectionEnabled);
+ mHeader->setFocus(true);
+ mHeader->setSelected(mSelectionEnabled);
LLRect screen_rc;
- LLRect selected_rc = header->getRect();
+ LLRect selected_rc = mHeader->getRect();
localRectToScreen(selected_rc, &screen_rc);
- notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
+ // This call to notifyParent() is intended to deliver "scrollToShowRect" command
+ // to the parent LLAccordionCtrl so by calling it from the direct parent of this
+ // accordion tab (assuming that the parent is an LLAccordionCtrl) the calls chain
+ // is shortened and messages from inside the collapsed tabs are avoided.
+ // See STORM-536.
+ getParent()->notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
}
void LLAccordionCtrlTab::storeOpenCloseState()
{
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 65ef3e5f8f..45ceaff696 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -98,7 +98,8 @@ LLButton::Params::Params()
is_toggle("is_toggle", false),
scale_image("scale_image", true),
hover_glow_amount("hover_glow_amount"),
- commit_on_return("commit_on_return", true)
+ commit_on_return("commit_on_return", true),
+ use_draw_context_alpha("use_draw_context_alpha", true)
{
addSynonym(is_toggle, "toggle");
held_down_delay.seconds = 0.5f;
@@ -158,7 +159,8 @@ LLButton::LLButton(const LLButton::Params& p)
mLastDrawCharsCount(0),
mMouseDownSignal(NULL),
mMouseUpSignal(NULL),
- mHeldDownSignal(NULL)
+ mHeldDownSignal(NULL),
+ mUseDrawContextAlpha(p.use_draw_context_alpha)
{
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
@@ -539,7 +541,7 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
// virtual
void LLButton::draw()
{
- F32 alpha = getDrawContext().mAlpha;
+ F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency();
bool flash = FALSE;
static LLUICachedControl<F32> button_flash_rate("ButtonFlashRate", 0);
static LLUICachedControl<S32> button_flash_count("ButtonFlashCount", 0);
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 2d5fefa78c..16aa49b653 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -124,6 +124,8 @@ public:
Optional<F32> hover_glow_amount;
Optional<TimeIntervalParam> held_down_delay;
+ Optional<bool> use_draw_context_alpha;
+
Params();
};
@@ -338,6 +340,8 @@ private:
S32 mImageOverlayTopPad;
S32 mImageOverlayBottomPad;
+ bool mUseDrawContextAlpha;
+
/*
* Space between image_overlay and label
*/
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 2dabbc7767..70014fe4f5 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -769,7 +769,7 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask)
return FALSE;
}
// if selection has changed, pop open list
- else if (mList->getLastSelectedItem() != last_selected_item)
+ else if ((mList->getLastSelectedItem() != last_selected_item) || (key == KEY_DOWN) || (key == KEY_UP))
{
showList();
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index b758070419..7727e154da 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -61,7 +61,6 @@
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
-
std::string LLFloater::sButtonNames[BUTTON_COUNT] =
{
"llfloater_close_btn", //BUTTON_CLOSE
@@ -200,6 +199,21 @@ void LLFloater::initClass()
{
sButtonToolTips[i] = LLTrans::getString( sButtonToolTipsIndex[i] );
}
+
+ LLControlVariable* ctrl = LLUI::sSettingGroups["config"]->getControl("ActiveFloaterTransparency").get();
+ if (ctrl)
+ {
+ ctrl->getSignal()->connect(boost::bind(&LLFloater::updateActiveFloaterTransparency));
+ updateActiveFloaterTransparency();
+ }
+
+ ctrl = LLUI::sSettingGroups["config"]->getControl("InactiveFloaterTransparency").get();
+ if (ctrl)
+ {
+ ctrl->getSignal()->connect(boost::bind(&LLFloater::updateInactiveFloaterTransparency));
+ updateInactiveFloaterTransparency();
+ }
+
}
// defaults for floater param block pulled from widgets/floater.xml
@@ -207,7 +221,7 @@ static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFl
LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
: LLPanel(), // intentionally do not pass params here, see initFromParams
- mDragHandle(NULL),
+ mDragHandle(NULL),
mTitle(p.title),
mShortTitle(p.short_title),
mSingleInstance(p.single_instance),
@@ -347,6 +361,18 @@ void LLFloater::layoutDragHandle()
updateTitleButtons();
}
+// static
+void LLFloater::updateActiveFloaterTransparency()
+{
+ sActiveControlTransparency = LLUI::sSettingGroups["config"]->getF32("ActiveFloaterTransparency");
+}
+
+// static
+void LLFloater::updateInactiveFloaterTransparency()
+{
+ sInactiveControlTransparency = LLUI::sSettingGroups["config"]->getF32("InactiveFloaterTransparency");
+}
+
void LLFloater::addResizeCtrls()
{
// Resize bars (sides)
@@ -1163,6 +1189,7 @@ void LLFloater::setFocus( BOOL b )
last_focus->setFocus(TRUE);
}
}
+ updateTransparency(this, b ? TT_ACTIVE : TT_INACTIVE);
}
// virtual
@@ -1622,7 +1649,8 @@ void LLFloater::onClickCloseBtn()
// virtual
void LLFloater::draw()
{
- F32 alpha = getDrawContext().mAlpha;
+ const F32 alpha = getCurrentTransparency();
+
// draw background
if( isBackgroundVisible() )
{
@@ -1720,7 +1748,6 @@ void LLFloater::draw()
void LLFloater::drawShadow(LLPanel* panel)
{
- F32 alpha = panel->getDrawContext().mAlpha;
S32 left = LLPANEL_BORDER_WIDTH;
S32 top = panel->getRect().getHeight() - LLPANEL_BORDER_WIDTH;
S32 right = panel->getRect().getWidth() - LLPANEL_BORDER_WIDTH;
@@ -1737,10 +1764,32 @@ void LLFloater::drawShadow(LLPanel* panel)
shadow_color.mV[VALPHA] *= 0.5f;
}
gl_drop_shadow(left, top, right, bottom,
- shadow_color % alpha,
+ shadow_color % getCurrentTransparency(),
llround(shadow_offset));
}
+void LLFloater::updateTransparency(LLView* view, ETypeTransparency transparency_type)
+{
+ child_list_t children = *view->getChildList();
+ child_list_t::iterator it = children.begin();
+
+ LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(view);
+ if (ctrl)
+ {
+ ctrl->setTransparencyType(transparency_type);
+ }
+
+ for(; it != children.end(); ++it)
+ {
+ updateTransparency(*it, transparency_type);
+ }
+}
+
+void LLFloater::updateTransparency(ETypeTransparency transparency_type)
+{
+ updateTransparency(this, transparency_type);
+}
+
void LLFloater::setCanMinimize(BOOL can_minimize)
{
// if removing minimize/restore button programmatically,
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 32d03f9f83..bb96272d02 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -284,6 +284,8 @@ public:
static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; }
static LLMultiFloater* getFloaterHost() {return sHostp; }
+
+ void updateTransparency(ETypeTransparency transparency_type);
protected:
@@ -341,6 +343,10 @@ private:
void addDragHandle();
void layoutDragHandle(); // repair layout
+ static void updateActiveFloaterTransparency();
+ static void updateInactiveFloaterTransparency();
+ void updateTransparency(LLView* view, ETypeTransparency transparency_type);
+
public:
// Called when floater is opened, passes mKey
// Public so external views or floaters can watch for this floater opening
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 627957061d..47f2cfaf89 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -41,6 +41,7 @@ static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon");
LLIconCtrl::Params::Params()
: image("image_name"),
color("color"),
+ use_draw_context_alpha("use_draw_context_alpha", true),
scale_image("scale_image")
{
tab_stop = false;
@@ -51,6 +52,7 @@ LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
: LLUICtrl(p),
mColor(p.color()),
mImagep(p.image),
+ mUseDrawContextAlpha(p.use_draw_context_alpha),
mPriority(0),
mDrawWidth(0),
mDrawHeight(0)
@@ -71,7 +73,8 @@ void LLIconCtrl::draw()
{
if( mImagep.notNull() )
{
- mImagep->draw(getLocalRect(), mColor.get() % getDrawContext().mAlpha );
+ const F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency();
+ mImagep->draw(getLocalRect(), mColor.get() % alpha );
}
LLUICtrl::draw();
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index 79a8b0fb28..e9bdab2d47 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -48,6 +48,7 @@ public:
{
Optional<LLUIImage*> image;
Optional<LLUIColor> color;
+ Optional<bool> use_draw_context_alpha;
Ignored scale_image;
Params();
};
@@ -79,6 +80,10 @@ protected:
S32 mDrawWidth ;
S32 mDrawHeight ;
+ // If set to true (default), use the draw context transparency.
+ // If false, will use transparency returned by getCurrentTransparency(). See STORM-698.
+ bool mUseDrawContextAlpha;
+
private:
LLUIColor mColor;
LLPointer<LLUIImage> mImagep;
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 5f5fe851bb..ba73b74052 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1304,7 +1304,7 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
// handle ctrl-uparrow if we have a history enabled line editor.
case KEY_UP:
- if( mHaveHistory && ( MASK_CONTROL == mask ) )
+ if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) )
{
if( mCurrentHistoryLine > mLineHistory.begin() )
{
@@ -1319,9 +1319,9 @@ BOOL LLLineEditor::handleSpecialKey(KEY key, MASK mask)
}
break;
- // handle ctrl-downarrow if we have a history enabled line editor
+ // handle [ctrl]-downarrow if we have a history enabled line editor
case KEY_DOWN:
- if( mHaveHistory && ( MASK_CONTROL == mask ) )
+ if( mHaveHistory && ((mIgnoreArrowKeys == false) || ( MASK_CONTROL == mask )) )
{
if( !mLineHistory.empty() && mCurrentHistoryLine < mLineHistory.end() - 1 )
{
@@ -1530,7 +1530,8 @@ void LLLineEditor::drawBackground()
image = mBgImage;
}
- F32 alpha = getDrawContext().mAlpha;
+ F32 alpha = getCurrentTransparency();
+
// optionally draw programmatic border
if (has_focus)
{
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 3df05f4d3f..ac568a83e4 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -29,7 +29,7 @@
#include "llmenubutton.h"
// Linden library includes
-#include "llmenugl.h"
+#include "lltoggleablemenu.h"
#include "llstring.h"
#include "v4color.h"
@@ -44,58 +44,77 @@ LLMenuButton::Params::Params()
LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
: LLButton(p),
- mMenu(NULL),
- mMenuVisibleLastFrame(false)
+ mIsMenuShown(false),
+ mMenuPosition(MP_BOTTOM_LEFT)
{
std::string menu_filename = p.menu_filename;
if (!menu_filename.empty())
{
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
- if (!mMenu)
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (!menu)
{
llwarns << "Error loading menu_button menu" << llendl;
+ return;
}
+
+ menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
+
+ mMenuHandle = menu->getHandle();
+
+ updateMenuOrigin();
}
}
-void LLMenuButton::toggleMenu()
+boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
{
- if(!mMenu)
- return;
+ return LLUICtrl::setMouseDownCallback(cb);
+}
- if (mMenu->getVisible() || mMenuVisibleLastFrame)
- {
- mMenu->setVisible(FALSE);
- }
- else
+void LLMenuButton::hideMenu()
+{
+ if(mMenuHandle.isDead()) return;
+
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (menu)
{
- LLRect rect = getRect();
- //mMenu->needsArrange(); //so it recalculates the visible elements
- LLMenuGL::showPopup(getParent(), mMenu, rect.mLeft, rect.mBottom);
+ menu->setVisible(FALSE);
}
}
-
-void LLMenuButton::hideMenu()
-{
- if(!mMenu)
- return;
- mMenu->setVisible(FALSE);
+LLToggleableMenu* LLMenuButton::getMenu()
+{
+ return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
}
+void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/)
+{
+ if (!menu) return;
+
+ mMenuHandle = menu->getHandle();
+ mMenuPosition = position;
+
+ menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
+}
BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
{
+ if (mMenuHandle.isDead()) return FALSE;
+
if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
{
+ // *HACK: We emit the mouse down signal to fire the callback bound to the
+ // menu emerging event before actually displaying the menu. See STORM-263.
+ LLUICtrl::handleMouseDown(-1, -1, MASK_NONE);
+
toggleMenu();
return TRUE;
}
- if (mMenu && mMenu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
{
- mMenu->setVisible(FALSE);
+ menu->setVisible(FALSE);
return TRUE;
}
@@ -104,34 +123,77 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
{
- if (hasTabStop() && !getIsChrome())
- {
- setFocus(TRUE);
- }
+ LLButton::handleMouseDown(x, y, mask);
toggleMenu();
- if (getSoundFlags() & MOUSE_DOWN)
- {
- make_ui_sound("UISndClick");
- }
-
return TRUE;
}
-void LLMenuButton::draw()
+void LLMenuButton::toggleMenu()
{
- //we save this off so next frame when we try to close it by
- //button click, and it hides menus before we get to it, we know
- mMenuVisibleLastFrame = mMenu && mMenu->getVisible();
-
- if (mMenuVisibleLastFrame)
+ if(mMenuHandle.isDead()) return;
+
+ LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
+ if (!menu) return;
+
+ // Store the button rectangle to toggle menu visibility if a mouse event
+ // occurred inside or outside the button rect.
+ menu->setButtonRect(this);
+
+ if (!menu->toggleVisibility() && mIsMenuShown)
+ {
+ setForcePressedState(false);
+ mIsMenuShown = false;
+ }
+ else
{
+ menu->buildDrawLabels();
+ menu->arrangeAndClear();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+
+ updateMenuOrigin();
+
+ LLMenuGL::showPopup(getParent(), menu, mX, mY);
+
setForcePressedState(true);
+ mIsMenuShown = true;
}
+}
+
+void LLMenuButton::updateMenuOrigin()
+{
+ if (mMenuHandle.isDead()) return;
- LLButton::draw();
+ LLRect rect = getRect();
- setForcePressedState(false);
+ switch (mMenuPosition)
+ {
+ case MP_TOP_LEFT:
+ {
+ mX = rect.mLeft;
+ mY = rect.mTop + mMenuHandle.get()->getRect().getHeight();
+ break;
+ }
+ case MP_BOTTOM_LEFT:
+ {
+ mX = rect.mLeft;
+ mY = rect.mBottom;
+ break;
+ }
+ }
}
+void LLMenuButton::onMenuVisibilityChange(const LLSD& param)
+{
+ bool new_visibility = param["visibility"].asBoolean();
+ bool is_closed_by_button_click = param["closed_by_button_click"].asBoolean();
+
+ // Reset the button "pressed" state only if the menu is shown by this particular
+ // menu button (not any other control) and is not being closed by a click on the button.
+ if (!new_visibility && !is_closed_by_button_click && mIsMenuShown)
+ {
+ setForcePressedState(false);
+ mIsMenuShown = false;
+ }
+}
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
index 81ca0e047c..9e91b9e99d 100644
--- a/indra/llui/llmenubutton.h
+++ b/indra/llui/llmenubutton.h
@@ -29,7 +29,7 @@
#include "llbutton.h"
-class LLMenuGL;
+class LLToggleableMenu;
class LLMenuButton
: public LLButton
@@ -42,22 +42,41 @@ public:
Optional<std::string> menu_filename;
Params();
- };
+ };
+
+ typedef enum e_menu_position
+ {
+ MP_TOP_LEFT,
+ MP_BOTTOM_LEFT
+ } EMenuPosition;
- void toggleMenu();
- /*virtual*/ void draw();
+ boost::signals2::connection setMouseDownCallback( const mouse_signal_t::slot_type& cb );
+
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
+
void hideMenu();
- LLMenuGL* getMenu() { return mMenu; }
+
+ LLToggleableMenu* getMenu();
+ void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT);
+
+ void setMenuPosition(EMenuPosition position) { mMenuPosition = position; }
protected:
friend class LLUICtrlFactory;
LLMenuButton(const Params&);
+ void toggleMenu();
+ void updateMenuOrigin();
+
+ void onMenuVisibilityChange(const LLSD& param);
+
private:
- LLMenuGL* mMenu;
- bool mMenuVisibleLastFrame;
+ LLHandle<LLView> mMenuHandle;
+ bool mIsMenuShown;
+ EMenuPosition mMenuPosition;
+ S32 mX;
+ S32 mY;
};
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 6d590cf54e..a6cf86d9b8 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1848,89 +1848,104 @@ BOOL LLMenuGL::isOpen()
}
}
-void LLMenuGL::scrollItemsUp()
+
+
+bool LLMenuGL::scrollItems(EScrollingDirection direction)
{
- // Slowing down the items scrolling when arrow button is held
+ // Slowing down items scrolling when arrow button is held
if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem)
{
mScrollItemsTimer.setTimerExpirySec(.033f);
}
else
{
- return;
+ return false;
}
- item_list_t::iterator cur_item_iter;
- item_list_t::iterator prev_item_iter;
- for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
+ switch (direction)
{
- if( (*cur_item_iter) == mFirstVisibleItem)
+ case SD_UP:
+ {
+ item_list_t::iterator cur_item_iter;
+ item_list_t::iterator prev_item_iter;
+ for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
- break;
+ if( (*cur_item_iter) == mFirstVisibleItem)
+ {
+ break;
+ }
+ if ((*cur_item_iter)->getVisible())
+ {
+ prev_item_iter = cur_item_iter;
+ }
}
- if ((*cur_item_iter)->getVisible())
+
+ if ((*prev_item_iter)->getVisible())
{
- prev_item_iter = cur_item_iter;
+ mFirstVisibleItem = *prev_item_iter;
}
+ break;
}
-
- if ((*prev_item_iter)->getVisible())
- {
- mFirstVisibleItem = *prev_item_iter;
- }
-
- mNeedsArrange = TRUE;
- arrangeAndClear();
-}
-
-void LLMenuGL::scrollItemsDown()
-{
- // Slowing down the items scrolling when arrow button is held
- if (mScrollItemsTimer.hasExpired())
- {
- mScrollItemsTimer.setTimerExpirySec(.033f);
- }
- else
- {
- return;
- }
-
- if (NULL == mFirstVisibleItem)
- {
- mFirstVisibleItem = *mItems.begin();
- }
-
- item_list_t::iterator cur_item_iter;
-
- for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
+ case SD_DOWN:
{
- if( (*cur_item_iter) == mFirstVisibleItem)
+ if (NULL == mFirstVisibleItem)
{
- break;
+ mFirstVisibleItem = *mItems.begin();
}
- }
- item_list_t::iterator next_item_iter;
+ item_list_t::iterator cur_item_iter;
- if (cur_item_iter != mItems.end())
- {
- for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
+ for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
- if( (*next_item_iter)->getVisible())
+ if( (*cur_item_iter) == mFirstVisibleItem)
{
break;
}
}
-
- if (next_item_iter != mItems.end() &&
- (*next_item_iter)->getVisible())
+
+ item_list_t::iterator next_item_iter;
+
+ if (cur_item_iter != mItems.end())
{
- mFirstVisibleItem = *next_item_iter;
+ for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
+ {
+ if( (*next_item_iter)->getVisible())
+ {
+ break;
+ }
+ }
+
+ if (next_item_iter != mItems.end() &&
+ (*next_item_iter)->getVisible())
+ {
+ mFirstVisibleItem = *next_item_iter;
+ }
}
+ break;
}
-
+ case SD_BEGIN:
+ {
+ mFirstVisibleItem = *mItems.begin();
+ break;
+ }
+ case SD_END:
+ {
+ item_list_t::reverse_iterator first_visible_item_iter = mItems.rend();
+
+ // Advance by mMaxScrollableItems back from the end of the list
+ // to make the last item visible.
+ std::advance(first_visible_item_iter, mMaxScrollableItems);
+ mFirstVisibleItem = *first_visible_item_iter;
+ break;
+ }
+ default:
+ llwarns << "Unknown scrolling direction: " << direction << llendl;
+ }
+
mNeedsArrange = TRUE;
arrangeAndClear();
+
+ return true;
}
// rearrange the child rects so they fit the shape of the menu.
@@ -2162,7 +2177,7 @@ void LLMenuGL::arrange( void )
LLMenuScrollItem::Params item_params;
item_params.name(ARROW_UP);
item_params.arrow_type(LLMenuScrollItem::ARROW_UP);
- item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsUp, this));
+ item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_UP));
mArrowUpItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
LLUICtrl::addChild(mArrowUpItem);
@@ -2173,7 +2188,7 @@ void LLMenuGL::arrange( void )
LLMenuScrollItem::Params item_params;
item_params.name(ARROW_DOWN);
item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN);
- item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsDown, this));
+ item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_DOWN));
mArrowDownItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
LLUICtrl::addChild(mArrowDownItem);
@@ -2603,14 +2618,8 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
((LLFloater*)getParent())->setFocus(TRUE);
}
- item_list_t::iterator cur_item_iter;
- for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); ++cur_item_iter)
- {
- if( (*cur_item_iter) == cur_item)
- {
- break;
- }
- }
+ // Current item position in the items list
+ item_list_t::iterator cur_item_iter = std::find(mItems.begin(), mItems.end(), cur_item);
item_list_t::iterator next_item_iter;
if (cur_item_iter == mItems.end())
@@ -2621,9 +2630,37 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
{
next_item_iter = cur_item_iter;
next_item_iter++;
+
+ // First visible item position in the items list
+ item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem);
+
if (next_item_iter == mItems.end())
{
next_item_iter = mItems.begin();
+
+ // If current item is the last in the list, the menu is scrolled to the beginning
+ // and the first item is highlighted.
+ if (mScrollable && !scrollItems(SD_BEGIN))
+ {
+ return NULL;
+ }
+ }
+ // If current item is the last visible, the menu is scrolled one item down
+ // and the next item is highlighted.
+ else if (mScrollable &&
+ (U32)std::abs(std::distance(first_visible_item_iter, next_item_iter)) >= mMaxScrollableItems)
+ {
+ // Call highlightNextItem() recursively only if the menu was successfully scrolled down.
+ // If scroll timer hasn't expired yet the menu won't be scrolled and calling
+ // highlightNextItem() will result in an endless recursion.
+ if (scrollItems(SD_DOWN))
+ {
+ return highlightNextItem(cur_item, skip_disabled);
+ }
+ else
+ {
+ return NULL;
+ }
}
}
@@ -2681,14 +2718,8 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa
((LLFloater*)getParent())->setFocus(TRUE);
}
- item_list_t::reverse_iterator cur_item_iter;
- for (cur_item_iter = mItems.rbegin(); cur_item_iter != mItems.rend(); ++cur_item_iter)
- {
- if( (*cur_item_iter) == cur_item)
- {
- break;
- }
- }
+ // Current item reverse position from the end of the list
+ item_list_t::reverse_iterator cur_item_iter = std::find(mItems.rbegin(), mItems.rend(), cur_item);
item_list_t::reverse_iterator prev_item_iter;
if (cur_item_iter == mItems.rend())
@@ -2699,9 +2730,37 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa
{
prev_item_iter = cur_item_iter;
prev_item_iter++;
+
+ // First visible item reverse position in the items list
+ item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem);
+
if (prev_item_iter == mItems.rend())
{
prev_item_iter = mItems.rbegin();
+
+ // If current item is the first in the list, the menu is scrolled to the end
+ // and the last item is highlighted.
+ if (mScrollable && !scrollItems(SD_END))
+ {
+ return NULL;
+ }
+ }
+ // If current item is the first visible, the menu is scrolled one item up
+ // and the previous item is highlighted.
+ else if (mScrollable &&
+ std::distance(first_visible_item_iter, cur_item_iter) <= 0)
+ {
+ // Call highlightNextItem() only if the menu was successfully scrolled up.
+ // If scroll timer hasn't expired yet the menu won't be scrolled and calling
+ // highlightNextItem() will result in an endless recursion.
+ if (scrollItems(SD_UP))
+ {
+ return highlightPrevItem(cur_item, skip_disabled);
+ }
+ else
+ {
+ return NULL;
+ }
}
}
@@ -2872,12 +2931,12 @@ BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks )
if( clicks > 0 )
{
while( clicks-- )
- scrollItemsDown();
+ scrollItems(SD_DOWN);
}
else
{
while( clicks++ )
- scrollItemsUp();
+ scrollItems(SD_UP);
}
return TRUE;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 19b738312e..35544402f4 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -397,6 +397,15 @@ public:
static const std::string ARROW_UP;
static const std::string ARROW_DOWN;
+ // for scrollable menus
+ typedef enum e_scrolling_direction
+ {
+ SD_UP = 0,
+ SD_DOWN = 1,
+ SD_BEGIN = 2,
+ SD_END = 3
+ } EScrollingDirection;
+
protected:
LLMenuGL(const LLMenuGL::Params& p);
friend class LLUICtrlFactory;
@@ -503,8 +512,7 @@ public:
S32 getShortcutPad() { return mShortcutPad; }
- void scrollItemsUp();
- void scrollItemsDown();
+ bool scrollItems(EScrollingDirection direction);
BOOL isScrollable() const { return mScrollable; }
static class LLMenuHolderGL* sMenuContainer;
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index dd6c632d10..a3df6a3ced 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -64,7 +64,7 @@ LLNotificationForm::FormElementBase::FormElementBase()
LLNotificationForm::FormIgnore::FormIgnore()
: text("text"),
control("control"),
- invert_control("invert_control", true),
+ invert_control("invert_control", false),
save_option("save_option", false)
{}
@@ -194,7 +194,7 @@ LLNotificationForm::LLNotificationForm()
LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p)
: mIgnore(IGNORE_NO),
- mInvertSetting(true) // ignore settings by default mean true=show, false=ignore
+ mInvertSetting(false) // ignore settings by default mean true=show, false=ignore
{
if (p.ignore.isProvided())
{
@@ -219,7 +219,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
}
else
{
- LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Ignore notification with this name", TRUE);
+ LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", TRUE);
mIgnoreSetting = LLUI::sSettingGroups["ignores"]->getControl(name);
}
}
@@ -357,15 +357,15 @@ LLControlVariablePtr LLNotificationForm::getIgnoreSetting()
bool LLNotificationForm::getIgnored()
{
- bool ignored = false;
+ bool show = true;
if (mIgnore != LLNotificationForm::IGNORE_NO
&& mIgnoreSetting)
{
- ignored = mIgnoreSetting->getValue().asBoolean();
- if (mInvertSetting) ignored = !ignored;
+ show = mIgnoreSetting->getValue().asBoolean();
+ if (mInvertSetting) show = !show;
}
- return ignored;
+ return !show;
}
void LLNotificationForm::setIgnored(bool ignored)
@@ -373,7 +373,7 @@ void LLNotificationForm::setIgnored(bool ignored)
if (mIgnoreSetting)
{
if (mInvertSetting) ignored = !ignored;
- mIgnoreSetting->setValue(ignored);
+ mIgnoreSetting->setValue(!ignored);
}
}
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index c8e56630f1..ff377ba3a1 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -194,6 +194,8 @@ void LLPanel::draw()
// draw background
if( mBgVisible )
{
+ alpha = getCurrentTransparency();
+
LLRect local_rect = getLocalRect();
if (mBgOpaque )
{
@@ -904,7 +906,7 @@ LLPanel *LLPanel::childGetVisiblePanelWithHelp()
child = *it;
// do we have a panel with a help topic?
LLPanel *panel = dynamic_cast<LLPanel *>(child);
- if (panel && panel->getVisible() && !panel->getHelpTopic().empty())
+ if (panel && panel->isInVisibleChain() && !panel->getHelpTopic().empty())
{
return panel;
}
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 3146418a7d..380c477eb2 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -422,9 +422,10 @@ void LLScrollContainer::draw()
// Draw background
if( mIsOpaque )
{
+ F32 alpha = getCurrentTransparency();
+
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( mBackgroundColor.get().mV );
- gl_rect_2d( mInnerRect );
+ gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha);
}
// Draw mScrolledViews and update scroll bars.
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 7df7c13dc0..8854f0a02e 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1482,8 +1482,9 @@ void LLScrollListCtrl::draw()
// Draw background
if (mBackgroundVisible)
{
+ F32 alpha = getCurrentTransparency();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() : mBgReadOnlyColor.get() );
+ gl_rect_2d(background, getEnabled() ? mBgWriteableColor.get() % alpha : mBgReadOnlyColor.get() % alpha );
}
if (mColumnsDirty)
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 9adeddca99..49537ef78f 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1005,6 +1005,7 @@ void LLTextBase::draw()
if (mBGVisible)
{
+ F32 alpha = getCurrentTransparency();
// clip background rect against extents, if we support scrolling
LLRect bg_rect = mVisibleTextRect;
if (mScroller)
@@ -1016,7 +1017,7 @@ void LLTextBase::draw()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(doc_rect, bg_color, TRUE);
+ gl_rect_2d(doc_rect, bg_color % alpha, TRUE);
}
// draw document view
@@ -1591,7 +1592,10 @@ void LLTextBase::setText(const LLStringExplicit &utf8str, const LLStyle::Params&
// appendText modifies mCursorPos...
appendText(text, false, input_params);
// ...so move cursor to top after appending text
- startOfDoc();
+ if (!mTrackEnd)
+ {
+ startOfDoc();
+ }
onValueChange(0, getLength());
}
@@ -1622,7 +1626,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
style_params.fillFrom(getDefaultStyleParams());
S32 part = (S32)LLTextParser::WHOLE;
- if(mParseHTML)
+ if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
{
S32 start=0,end=0;
LLUrlMatch match;
@@ -2214,19 +2218,39 @@ bool LLTextBase::scrolledToEnd()
return mScroller->isAtBottom();
}
-
bool LLTextBase::setCursor(S32 row, S32 column)
{
- if (0 <= row && row < (S32)mLineInfoList.size())
+ if (row < 0 || column < 0) return false;
+
+ S32 n_lines = mLineInfoList.size();
+ for (S32 line = row; line < n_lines; ++line)
{
- S32 doc_pos = mLineInfoList[row].mDocIndexStart;
- column = llclamp(column, 0, mLineInfoList[row].mDocIndexEnd - mLineInfoList[row].mDocIndexStart - 1);
- doc_pos += column;
- updateCursorXPos();
+ const line_info& li = mLineInfoList[line];
+
+ if (li.mLineNum < row)
+ {
+ continue;
+ }
+ else if (li.mLineNum > row)
+ {
+ break; // invalid column specified
+ }
+
+ // Found the given row.
+ S32 line_length = li.mDocIndexEnd - li.mDocIndexStart;;
+ if (column >= line_length)
+ {
+ column -= line_length;
+ continue;
+ }
+ // Found the given column.
+ updateCursorXPos();
+ S32 doc_pos = li.mDocIndexStart + column;
return setCursorPos(doc_pos);
}
- return false;
+
+ return false; // invalid row or column specified
}
diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp
index 0eb2dc1387..d29260750f 100644
--- a/indra/llui/lltoggleablemenu.cpp
+++ b/indra/llui/lltoggleablemenu.cpp
@@ -35,10 +35,22 @@ static LLDefaultChildRegistry::Register<LLToggleableMenu> r("toggleable_menu");
LLToggleableMenu::LLToggleableMenu(const LLToggleableMenu::Params& p)
: LLMenuGL(p),
mButtonRect(),
+ mVisibilityChangeSignal(NULL),
mClosedByButtonClick(false)
{
}
+LLToggleableMenu::~LLToggleableMenu()
+{
+ delete mVisibilityChangeSignal;
+}
+
+boost::signals2::connection LLToggleableMenu::setVisibilityChangeCallback(const commit_signal_t::slot_type& cb)
+{
+ if (!mVisibilityChangeSignal) mVisibilityChangeSignal = new commit_signal_t();
+ return mVisibilityChangeSignal->connect(cb);
+}
+
// virtual
void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn)
{
@@ -49,6 +61,12 @@ void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn)
{
mClosedByButtonClick = true;
}
+
+ if (mVisibilityChangeSignal)
+ {
+ (*mVisibilityChangeSignal)(this,
+ LLSD().with("visibility", curVisibilityIn).with("closed_by_button_click", mClosedByButtonClick));
+ }
}
void LLToggleableMenu::setButtonRect(const LLRect& rect, LLView* current_view)
diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h
index f036cdfffb..2094bd776f 100644
--- a/indra/llui/lltoggleablemenu.h
+++ b/indra/llui/lltoggleablemenu.h
@@ -41,6 +41,10 @@ protected:
LLToggleableMenu(const Params&);
friend class LLUICtrlFactory;
public:
+ ~LLToggleableMenu();
+
+ boost::signals2::connection setVisibilityChangeCallback( const commit_signal_t::slot_type& cb );
+
virtual void handleVisibilityChange (BOOL curVisibilityIn);
const LLRect& getButtonRect() const { return mButtonRect; }
@@ -57,6 +61,7 @@ public:
protected:
bool mClosedByButtonClick;
LLRect mButtonRect;
+ commit_signal_t* mVisibilityChangeSignal;
};
#endif // LL_LLTOGGLEABLEMENU_H
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index ff9af21e54..1e2fe09cd9 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -950,7 +950,7 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
}
// Draw gray and white checkerboard with black border
-void gl_rect_2d_checkerboard(const LLRect& rect)
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
{
// Initialize the first time this is called.
const S32 PIXELS = 32;
@@ -971,11 +971,11 @@ void gl_rect_2d_checkerboard(const LLRect& rect)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// ...white squares
- gGL.color3f( 1.f, 1.f, 1.f );
+ gGL.color4f( 1.f, 1.f, 1.f, alpha );
gl_rect_2d(rect);
// ...gray squares
- gGL.color3f( .7f, .7f, .7f );
+ gGL.color4f( .7f, .7f, .7f, alpha );
gGL.flush();
glPolygonStipple( checkerboard );
@@ -1620,7 +1620,10 @@ void LLUI::initClass(const settings_map_t& settings,
void LLUI::cleanupClass()
{
- sImageProvider->cleanUp();
+ if(sImageProvider)
+ {
+ sImageProvider->cleanUp();
+ }
}
void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups)
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index fc545c85d5..62d10df8b2 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -79,7 +79,7 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LL
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE );
void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE );
void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE );
-void gl_rect_2d_checkerboard(const LLRect& rect);
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 3ac3bf8c41..afd60cbb3e 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -36,6 +36,9 @@
static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
+F32 LLUICtrl::sActiveControlTransparency = 1.0f;
+F32 LLUICtrl::sInactiveControlTransparency = 1.0f;
+
// Compiler optimization, generate extern template
template class LLUICtrl* LLView::getChild<class LLUICtrl>(
const std::string& name, BOOL recurse) const;
@@ -110,7 +113,8 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
mMouseUpSignal(NULL),
mRightMouseDownSignal(NULL),
mRightMouseUpSignal(NULL),
- mDoubleClickSignal(NULL)
+ mDoubleClickSignal(NULL),
+ mTransparencyType(TT_DEFAULT)
{
mUICtrlHandle.bind(this);
}
@@ -923,6 +927,37 @@ BOOL LLUICtrl::getTentative() const
void LLUICtrl::setColor(const LLColor4& color)
{ }
+F32 LLUICtrl::getCurrentTransparency()
+{
+ F32 alpha = 0;
+
+ switch(mTransparencyType)
+ {
+ case TT_DEFAULT:
+ alpha = getDrawContext().mAlpha;
+ break;
+
+ case TT_ACTIVE:
+ alpha = sActiveControlTransparency;
+ break;
+
+ case TT_INACTIVE:
+ alpha = sInactiveControlTransparency;
+ break;
+
+ case TT_FADING:
+ alpha = sInactiveControlTransparency / 2;
+ break;
+ }
+
+ return alpha;
+}
+
+void LLUICtrl::setTransparencyType(ETypeTransparency type)
+{
+ mTransparencyType = type;
+}
+
boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )
{
if (!mCommitSignal) mCommitSignal = new commit_signal_t();
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 76dfdf754c..b37e9f6b1b 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -120,6 +120,13 @@ public:
Params();
};
+ enum ETypeTransparency
+ {
+ TT_DEFAULT,
+ TT_ACTIVE, // focused floater
+ TT_INACTIVE, // other floaters
+ TT_FADING, // fading toast
+ };
/*virtual*/ ~LLUICtrl();
void initFromParams(const Params& p);
@@ -202,6 +209,11 @@ public:
virtual void setColor(const LLColor4& color);
+ F32 getCurrentTransparency();
+
+ void setTransparencyType(ETypeTransparency type);
+ ETypeTransparency getTransparencyType() const {return mTransparencyType;}
+
BOOL focusNextItem(BOOL text_entry_only);
BOOL focusPrevItem(BOOL text_entry_only);
BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE );
@@ -283,6 +295,10 @@ protected:
boost::signals2::connection mMakeVisibleControlConnection;
LLControlVariable* mMakeInvisibleControlVariable;
boost::signals2::connection mMakeInvisibleControlConnection;
+
+ static F32 sActiveControlTransparency;
+ static F32 sInactiveControlTransparency;
+
private:
BOOL mTabStop;
@@ -290,6 +306,8 @@ private:
BOOL mTentative;
LLRootHandle<LLUICtrl> mUICtrlHandle;
+ ETypeTransparency mTransparencyType;
+
class DefaultTabGroupFirstSorter;
};
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index eff2467bf0..4faa0e070e 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -58,10 +58,12 @@ class LLUIString
public:
// These methods all perform appropriate argument substitution
// and modify mOrig where appropriate
- LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {}
+ LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {}
LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args);
LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); }
+ ~LLUIString() { delete mArgs; }
+
void assign(const std::string& instring);
LLUIString& operator=(const std::string& s) { assign(s); return *this; }
@@ -81,14 +83,14 @@ public:
void clear();
void clearArgs() { if (mArgs) mArgs->clear(); }
-
+
// These utility functions are included for text editing.
// They do not affect mOrig and do not perform argument substitution
void truncate(S32 maxchars);
void erase(S32 charidx, S32 len);
void insert(S32 charidx, const LLWString& wchars);
void replace(S32 charidx, llwchar wc);
-
+
private:
// something changed, requiring reformatting of strings
void dirty();
@@ -100,7 +102,7 @@ private:
void updateResult() const;
void updateWResult() const;
LLStringUtil::format_map_t& getArgs();
-
+
std::string mOrig;
mutable std::string mResult;
mutable LLWString mWResult; // for displaying
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index efb3f1a8be..f25be55665 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -456,8 +456,8 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
LLStyle::Params LLUrlEntryAgent::getStyle() const
{
LLStyle::Params style_params = LLUrlEntryBase::getStyle();
- style_params.color = LLUIColorTable::instance().getColor("AgentLinkColor");
- style_params.readonly_color = LLUIColorTable::instance().getColor("AgentLinkColor");
+ style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
return style_params;
}
@@ -978,7 +978,7 @@ std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const
//
LLUrlEntryNoLink::LLUrlEntryNoLink()
{
- mPattern = boost::regex("<nolink>[^<]*</nolink>",
+ mPattern = boost::regex("<nolink>.*</nolink>",
boost::regex::perl|boost::regex::icase);
}
@@ -995,7 +995,8 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
LLStyle::Params LLUrlEntryNoLink::getStyle() const
{
- return LLStyle::Params();
+ // Don't render as URL (i.e. no context menu or hand cursor).
+ return LLStyle::Params().is_link(false);
}
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 9b91c103ef..1a16056041 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -183,7 +183,7 @@ private:
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
/// that displays various forms of user name
/// This is a base class for the various implementations of name display
-class LLUrlEntryAgentName : public LLUrlEntryBase
+class LLUrlEntryAgentName : public LLUrlEntryBase, public boost::signals2::trackable
{
public:
LLUrlEntryAgentName();
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 938fb008c9..1179180da2 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -83,7 +83,7 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
std::string filename;
std::string fullpath;
S32 result;
- while (getNextFileInDir(dirname, mask, filename, FALSE))
+ while (getNextFileInDir(dirname, mask, filename))
{
fullpath = dirname;
fullpath += getDirDelimiter();
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 4f63c04aab..42996fd051 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -74,8 +74,32 @@ class LLDir
// pure virtual functions
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0;
- virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap) = 0;
- virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname) = 0;
+
+ /// Walk the files in a directory, with file pattern matching
+ virtual BOOL getNextFileInDir(const std::string& dirname, ///< directory path - must end in trailing slash!
+ const std::string& mask, ///< file pattern string (use "*" for all)
+ std::string& fname ///< output: found file name
+ ) = 0;
+ /**<
+ * @returns true if a file was found, false if the entire directory has been scanned.
+ *
+ * @note that this function is NOT thread safe
+ *
+ * This function may not be used to scan part of a directory, then start a new search of a different
+ * directory, and then restart the first search where it left off; the entire search must run to
+ * completion or be abandoned - there is no restart.
+ *
+ * @bug: See http://jira.secondlife.com/browse/VWR-23697
+ * and/or the tests in test/lldir_test.cpp
+ * This is known to fail with patterns that have both:
+ * a wildcard left of a . and more than one sequential ? right of a .
+ * the pattern foo.??x appears to work
+ * but *.??x or foo?.??x do not
+ *
+ * @todo this really should be rewritten as an iterator object, and the
+ * filtering should be done in a platform-independent way.
+ */
+
virtual std::string getCurPath() = 0;
virtual BOOL fileExists(const std::string &filename) const = 0;
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index a1c6669b97..73f2336f94 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -243,8 +243,7 @@ U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &
}
// get the next file in the directory
-// automatically wrap if we've hit the end
-BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
+BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
glob_t g;
BOOL result = FALSE;
@@ -276,11 +275,6 @@ BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string
mCurrentDirIndex++;
- if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
- {
- mCurrentDirIndex = 0;
- }
-
if(mCurrentDirIndex < (int)g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
@@ -308,47 +302,7 @@ BOOL LLDir_Linux::getNextFileInDir(const std::string &dirname, const std::string
}
-// get a random file in the directory
-// automatically wrap if we've hit the end
-void LLDir_Linux::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
- S32 num_files;
- S32 which_file;
- DIR *dirp;
- dirent *entryp = NULL;
-
- fname = "";
- num_files = countFilesInDir(dirname,mask);
- if (!num_files)
- {
- return;
- }
-
- which_file = ll_rand(num_files);
-
-// llinfos << "Random select file #" << which_file << llendl;
-
- // which_file now indicates the (zero-based) index to which file to play
-
- if (!((dirp = opendir(dirname.c_str()))))
- {
- while (which_file--)
- {
- if (!((entryp = readdir(dirp))))
- {
- return;
- }
- }
-
- if ((!which_file) && entryp)
- {
- fname = entryp->d_name;
- }
-
- closedir(dirp);
- }
-}
std::string LLDir_Linux::getCurPath()
{
diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h
index 809959e873..451e81ae93 100644
--- a/indra/llvfs/lldir_linux.h
+++ b/indra/llvfs/lldir_linux.h
@@ -43,8 +43,7 @@ public:
public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
- virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
+ virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index b41b0ec5dd..445285aa43 100644
--- a/indra/llvfs/lldir_mac.cpp
+++ b/indra/llvfs/lldir_mac.cpp
@@ -259,8 +259,7 @@ U32 LLDir_Mac::countFilesInDir(const std::string &dirname, const std::string &ma
}
// get the next file in the directory
-// automatically wrap if we've hit the end
-BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
+BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
glob_t g;
BOOL result = FALSE;
@@ -292,11 +291,6 @@ BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &
mCurrentDirIndex++;
- if((mCurrentDirIndex >= g.gl_pathc) && wrap)
- {
- mCurrentDirIndex = 0;
- }
-
if(mCurrentDirIndex < g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
@@ -323,41 +317,7 @@ BOOL LLDir_Mac::getNextFileInDir(const std::string &dirname, const std::string &
return(result);
}
-// get a random file in the directory
-void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
- S32 which_file;
- glob_t g;
- fname = "";
-
- std::string tmp_str;
- tmp_str = dirname;
- tmp_str += mask;
-
- if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
- {
- if(g.gl_pathc > 0)
- {
-
- which_file = ll_rand(g.gl_pathc);
-
-// llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl;
- // The API wants just the filename, not the full path.
- //fname = g.gl_pathv[which_file];
- char *s = strrchr(g.gl_pathv[which_file], '/');
-
- if(s == NULL)
- s = g.gl_pathv[which_file];
- else if(s[0] == '/')
- s++;
-
- fname = s;
- }
-
- globfree(&g);
- }
-}
S32 LLDir_Mac::deleteFilesInDir(const std::string &dirname, const std::string &mask)
{
diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h
index 04c52dc940..4eac3c3ae6 100644
--- a/indra/llvfs/lldir_mac.h
+++ b/indra/llvfs/lldir_mac.h
@@ -43,8 +43,7 @@ public:
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 getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
- virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname);
+ virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
virtual BOOL fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
index 4323dfd44a..515fd66b6e 100644
--- a/indra/llvfs/lldir_solaris.cpp
+++ b/indra/llvfs/lldir_solaris.cpp
@@ -261,8 +261,7 @@ U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string
}
// get the next file in the directory
-// automatically wrap if we've hit the end
-BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
+BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
glob_t g;
BOOL result = FALSE;
@@ -294,11 +293,6 @@ BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::stri
mCurrentDirIndex++;
- if((mCurrentDirIndex >= (int)g.gl_pathc) && wrap)
- {
- mCurrentDirIndex = 0;
- }
-
if(mCurrentDirIndex < (int)g.gl_pathc)
{
// llinfos << "getNextFileInDir: returning number " << mCurrentDirIndex << ", path is " << g.gl_pathv[mCurrentDirIndex] << llendl;
@@ -326,47 +320,7 @@ BOOL LLDir_Solaris::getNextFileInDir(const std::string &dirname, const std::stri
}
-// get a random file in the directory
-// automatically wrap if we've hit the end
-void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
- S32 num_files;
- S32 which_file;
- DIR *dirp;
- dirent *entryp = NULL;
-
- fname = "";
-
- num_files = countFilesInDir(dirname,mask);
- if (!num_files)
- {
- return;
- }
-
- which_file = ll_rand(num_files);
-
-// llinfos << "Random select file #" << which_file << llendl;
- // which_file now indicates the (zero-based) index to which file to play
-
- if (!((dirp = opendir(dirname.c_str()))))
- {
- while (which_file--)
- {
- if (!((entryp = readdir(dirp))))
- {
- return;
- }
- }
-
- if ((!which_file) && entryp)
- {
- fname = entryp->d_name;
- }
-
- closedir(dirp);
- }
-}
std::string LLDir_Solaris::getCurPath()
{
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
index 6e0c5cfc69..4a1794f539 100644
--- a/indra/llvfs/lldir_solaris.h
+++ b/indra/llvfs/lldir_solaris.h
@@ -43,8 +43,7 @@ public:
public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
- virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
+ virtual BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
private:
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 52d864e26f..4a8526cc96 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -246,21 +246,13 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &
// get the next file in the directory
-// automatically wrap if we've hit the end
-BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
+BOOL LLDir_Win32::getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
- llutf16string dirnamew = utf8str_to_utf16str(dirname);
- return getNextFileInDir(dirnamew, mask, fname, wrap);
-
-}
+ BOOL fileFound = FALSE;
+ fname = "";
-BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap)
-{
WIN32_FIND_DATAW FileData;
-
- fname = "";
- llutf16string pathname = dirname;
- pathname += utf8str_to_utf16str(mask);
+ llutf16string pathname = utf8str_to_utf16str(dirname) + utf8str_to_utf16str(mask);
if (pathname != mCurrentDir)
{
@@ -273,91 +265,44 @@ BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::stri
// and open new one
// Check error opening Directory structure
- if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) == INVALID_HANDLE_VALUE)
- {
-// llinfos << "Unable to locate first file" << llendl;
- return(FALSE);
- }
- }
- else // get next file in list
- {
- // Find next entry
- if (!FindNextFile(mDirSearch_h, &FileData))
+ if ((mDirSearch_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
{
- if (GetLastError() == ERROR_NO_MORE_FILES)
- {
- // No more files, so reset to beginning of directory
- FindClose(mDirSearch_h);
- mCurrentDir[0] = NULL;
-
- if (wrap)
- {
- return(getNextFileInDir(pathname,"",fname,TRUE));
- }
- else
- {
- fname[0] = 0;
- return(FALSE);
- }
- }
- else
- {
- // Error
-// llinfos << "Unable to locate next file" << llendl;
- return(FALSE);
- }
+ fileFound = TRUE;
}
}
- // convert from TCHAR to char
- fname = utf16str_to_utf8str(FileData.cFileName);
-
- // fname now first name in list
- return(TRUE);
-}
-
-
-// get a random file in the directory
-// automatically wrap if we've hit the end
-void LLDir_Win32::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
-{
- S32 num_files;
- S32 which_file;
- HANDLE random_search_h;
-
- fname = "";
-
- llutf16string pathname = utf8str_to_utf16str(dirname);
- pathname += utf8str_to_utf16str(mask);
-
- WIN32_FIND_DATA FileData;
- fname[0] = NULL;
-
- num_files = countFilesInDir(dirname,mask);
- if (!num_files)
- {
- return;
- }
-
- which_file = ll_rand(num_files);
-
-// llinfos << "Random select mp3 #" << which_file << llendl;
-
- // which_file now indicates the (zero-based) index to which file to play
+ // Loop to skip over the current (.) and parent (..) directory entries
+ // (apparently returned in Win7 but not XP)
+ do
+ {
+ if ( fileFound
+ && ( (lstrcmp(FileData.cFileName, (LPCTSTR)TEXT(".")) == 0)
+ ||(lstrcmp(FileData.cFileName, (LPCTSTR)TEXT("..")) == 0)
+ )
+ )
+ {
+ fileFound = FALSE;
+ }
+ } while ( mDirSearch_h != INVALID_HANDLE_VALUE
+ && !fileFound
+ && (fileFound = FindNextFile(mDirSearch_h, &FileData)
+ )
+ );
+
+ if (!fileFound && GetLastError() == ERROR_NO_MORE_FILES)
+ {
+ // No more files, so reset to beginning of directory
+ FindClose(mDirSearch_h);
+ mCurrentDir[0] = '\000';
+ }
- if ((random_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
- {
- while (which_file--)
- {
- if (!FindNextFile(random_search_h, &FileData))
- {
- return;
- }
- }
- FindClose(random_search_h);
-
- fname = utf16str_to_utf8str(llutf16string(FileData.cFileName));
+ if (fileFound)
+ {
+ // convert from TCHAR to char
+ fname = utf16str_to_utf8str(FileData.cFileName);
}
+
+ return fileFound;
}
std::string LLDir_Win32::getCurPath()
diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h
index d3e45dc1f3..4c932c932c 100644
--- a/indra/llvfs/lldir_win32.h
+++ b/indra/llvfs/lldir_win32.h
@@ -40,15 +40,14 @@ public:
/*virtual*/ std::string getCurPath();
/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- /*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
- /*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
+ /*virtual*/ BOOL getNextFileInDir(const std::string &dirname, const std::string &mask, std::string &fname);
/*virtual*/ BOOL fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
private:
- BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap);
+ BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname);
void* mDirSearch_h;
llutf16string mCurrentDir;
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
index bcffa449c8..8788bd63e8 100644
--- a/indra/llvfs/tests/lldir_test.cpp
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -256,5 +256,160 @@ namespace tut
gDirUtilp->getExtension(dottedPathExt),
"ext");
}
+
+ std::string makeTestFile( const std::string& dir, const std::string& file )
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string path = dir + delim + file;
+ LLFILE* handle = LLFile::fopen( path, "w" );
+ ensure("failed to open test file '"+path+"'", handle != NULL );
+ // Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs
+ // returns EOF; otherwise, it returns some other, nonnegative value."
+ ensure("failed to write to test file '"+path+"'", fputs("test file", handle) >= 0);
+ fclose(handle);
+ return path;
+ }
+
+ std::string makeTestDir( const std::string& dirbase )
+ {
+ int counter;
+ std::string uniqueDir;
+ bool foundUnused;
+ std::string delim = gDirUtilp->getDirDelimiter();
+
+ for (counter=0, foundUnused=false; !foundUnused; counter++ )
+ {
+ char counterStr[3];
+ sprintf(counterStr, "%02d", counter);
+ uniqueDir = dirbase + counterStr;
+ foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) );
+ }
+ ensure("test directory '" + uniqueDir + "' creation failed", !LLFile::mkdir(uniqueDir));
+
+ return uniqueDir + delim; // HACK - apparently, the trailing delimiter is needed...
+ }
+
+ static const char* DirScanFilename[5] = { "file1.abc", "file2.abc", "file1.xyz", "file2.xyz", "file1.mno" };
+
+ void scanTest(const std::string& directory, const std::string& pattern, bool correctResult[5])
+ {
+
+ // Scan directory and see if any file1.* files are found
+ std::string scanResult;
+ int found = 0;
+ bool filesFound[5] = { false, false, false, false, false };
+ //std::cerr << "searching '"+directory+"' for '"+pattern+"'\n";
+
+ while ( found <= 5 && gDirUtilp->getNextFileInDir(directory, pattern, scanResult) )
+ {
+ found++;
+ //std::cerr << " found '"+scanResult+"'\n";
+ int check;
+ for (check=0; check < 5 && ! ( scanResult == DirScanFilename[check] ); check++)
+ {
+ }
+ // check is now either 5 (not found) or the index of the matching name
+ if (check < 5)
+ {
+ ensure( "found file '"+(std::string)DirScanFilename[check]+"' twice", ! filesFound[check] );
+ filesFound[check] = true;
+ }
+ else // check is 5 - should not happen
+ {
+ fail( "found unknown file '"+scanResult+"'");
+ }
+ }
+ for (int i=0; i<5; i++)
+ {
+ if (correctResult[i])
+ {
+ ensure("scan of '"+directory+"' using '"+pattern+"' did not return '"+DirScanFilename[i]+"'", filesFound[i]);
+ }
+ else
+ {
+ ensure("scan of '"+directory+"' using '"+pattern+"' incorrectly returned '"+DirScanFilename[i]+"'", !filesFound[i]);
+ }
+ }
+ }
+
+ template<> template<>
+ void LLDirTest_object_t::test<5>()
+ // getNextFileInDir
+ {
+ std::string delim = gDirUtilp->getDirDelimiter();
+ std::string dirTemp = LLFile::tmpdir();
+
+ // Create the same 5 file names of the two directories
+
+ std::string dir1 = makeTestDir(dirTemp + "getNextFileInDir");
+ std::string dir2 = makeTestDir(dirTemp + "getNextFileInDir");
+ std::string dir1files[5];
+ std::string dir2files[5];
+ for (int i=0; i<5; i++)
+ {
+ dir1files[i] = makeTestFile(dir1, DirScanFilename[i]);
+ dir2files[i] = makeTestFile(dir2, DirScanFilename[i]);
+ }
+
+ // Scan dir1 and see if each of the 5 files is found exactly once
+ bool expected1[5] = { true, true, true, true, true };
+ scanTest(dir1, "*", expected1);
+
+ // Scan dir2 and see if only the 2 *.xyz files are found
+ bool expected2[5] = { false, false, true, true, false };
+ scanTest(dir1, "*.xyz", expected2);
+
+ // Scan dir2 and see if only the 1 *.mno file is found
+ bool expected3[5] = { false, false, false, false, true };
+ scanTest(dir2, "*.mno", expected3);
+
+ // Scan dir1 and see if any *.foo files are found
+ bool expected4[5] = { false, false, false, false, false };
+ scanTest(dir1, "*.foo", expected4);
+
+ // Scan dir1 and see if any file1.* files are found
+ bool expected5[5] = { true, false, true, false, true };
+ scanTest(dir1, "file1.*", expected5);
+
+ // Scan dir1 and see if any file1.* files are found
+ bool expected6[5] = { true, true, false, false, false };
+ scanTest(dir1, "file?.abc", expected6);
+
+ // Scan dir2 and see if any file?.x?z files are found
+ bool expected7[5] = { false, false, true, true, false };
+ scanTest(dir2, "file?.x?z", expected7);
+
+ // Scan dir2 and see if any file?.??c files are found
+ // THESE FAIL ON Mac and Windows, SO ARE COMMENTED OUT FOR NOW
+ // bool expected8[5] = { true, true, false, false, false };
+ // scanTest(dir2, "file?.??c", expected8);
+ // scanTest(dir2, "*.??c", expected8);
+
+ // Scan dir1 and see if any *.?n? files are found
+ bool expected9[5] = { false, false, false, false, true };
+ scanTest(dir1, "*.?n?", expected9);
+
+ // Scan dir1 and see if any *.???? files are found
+ // THIS ONE FAILS ON WINDOWS (returns three charater suffixes) SO IS COMMENTED OUT FOR NOW
+ // bool expected10[5] = { false, false, false, false, false };
+ // scanTest(dir1, "*.????", expected10);
+
+ // Scan dir1 and see if any ?????.* files are found
+ bool expected11[5] = { true, true, true, true, true };
+ scanTest(dir1, "?????.*", expected11);
+
+ // Scan dir1 and see if any ??l??.xyz files are found
+ bool expected12[5] = { false, false, true, true, false };
+ scanTest(dir1, "??l??.xyz", expected12);
+
+ // clean up all test files and directories
+ for (int i=0; i<5; i++)
+ {
+ LLFile::remove(dir1files[i]);
+ LLFile::remove(dir2files[i]);
+ }
+ LLFile::rmdir(dir1);
+ LLFile::rmdir(dir2);
+ }
}
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index f9a39826f5..27c694dde9 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -1107,7 +1107,7 @@ bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::strin
return sd.asBoolean();
else
{
- CONTROL_ERRS << "Invalid BOOL value" << llendl;
+ CONTROL_ERRS << "Invalid BOOL value for " << control_name << ": " << sd << llendl;
return FALSE;
}
}
@@ -1119,7 +1119,7 @@ S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string&
return sd.asInteger();
else
{
- CONTROL_ERRS << "Invalid S32 value" << llendl;
+ CONTROL_ERRS << "Invalid S32 value for " << control_name << ": " << sd << llendl;
return 0;
}
}
@@ -1131,7 +1131,7 @@ U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string&
return sd.asInteger();
else
{
- CONTROL_ERRS << "Invalid U32 value" << llendl;
+ CONTROL_ERRS << "Invalid U32 value for " << control_name << ": " << sd << llendl;
return 0;
}
}
@@ -1143,7 +1143,7 @@ F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string&
return (F32) sd.asReal();
else
{
- CONTROL_ERRS << "Invalid F32 value" << llendl;
+ CONTROL_ERRS << "Invalid F32 value for " << control_name << ": " << sd << llendl;
return 0.0f;
}
}
@@ -1155,7 +1155,7 @@ std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, co
return sd.asString();
else
{
- CONTROL_ERRS << "Invalid string value" << llendl;
+ CONTROL_ERRS << "Invalid string value for " << control_name << ": " << sd << llendl;
return LLStringUtil::null;
}
}
@@ -1173,7 +1173,7 @@ LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const
return (LLVector3)sd;
else
{
- CONTROL_ERRS << "Invalid LLVector3 value" << llendl;
+ CONTROL_ERRS << "Invalid LLVector3 value for " << control_name << ": " << sd << llendl;
return LLVector3::zero;
}
}
@@ -1185,7 +1185,7 @@ LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, cons
return (LLVector3d)sd;
else
{
- CONTROL_ERRS << "Invalid LLVector3d value" << llendl;
+ CONTROL_ERRS << "Invalid LLVector3d value for " << control_name << ": " << sd << llendl;
return LLVector3d::zero;
}
}
@@ -1197,7 +1197,7 @@ LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::s
return LLRect(sd);
else
{
- CONTROL_ERRS << "Invalid rect value" << llendl;
+ CONTROL_ERRS << "Invalid rect value for " << control_name << ": " << sd << llendl;
return LLRect::null;
}
}
@@ -1211,19 +1211,19 @@ LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const st
LLColor4 color(sd);
if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
{
- llwarns << "Color " << control_name << " value out of range " << llendl;
+ llwarns << "Color " << control_name << " red value out of range: " << color << llendl;
}
else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
{
- llwarns << "Color " << control_name << " value out of range " << llendl;
+ llwarns << "Color " << control_name << " green value out of range: " << color << llendl;
}
else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
{
- llwarns << "Color " << control_name << " value out of range " << llendl;
+ llwarns << "Color " << control_name << " blue value out of range: " << color << llendl;
}
else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
{
- llwarns << "Color " << control_name << " value out of range " << llendl;
+ llwarns << "Color " << control_name << " alpha value out of range: " << color << llendl;
}
return LLColor4(sd);
@@ -1242,7 +1242,7 @@ LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const st
return sd;
else
{
- CONTROL_ERRS << "Invalid LLColor3 value" << llendl;
+ CONTROL_ERRS << "Invalid LLColor3 value for " << control_name << ": " << sd << llendl;
return LLColor3::white;
}
}
diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp
index e4d100d1ec..5d19e8a889 100644
--- a/indra/mac_updater/mac_updater.cpp
+++ b/indra/mac_updater/mac_updater.cpp
@@ -26,6 +26,9 @@
#include "linden_common.h"
+#include <boost/format.hpp>
+
+#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -61,6 +64,9 @@ Boolean gCancelled = false;
const char *gUpdateURL;
const char *gProductName;
+const char *gBundleID;
+const char *gDmgFile;
+const char *gMarkerPath;
void *updatethreadproc(void*);
@@ -329,6 +335,18 @@ int parse_args(int argc, char **argv)
{
gProductName = argv[j];
}
+ else if ((!strcmp(argv[j], "-bundleid")) && (++j < argc))
+ {
+ gBundleID = argv[j];
+ }
+ else if ((!strcmp(argv[j], "-dmg")) && (++j < argc))
+ {
+ gDmgFile = argv[j];
+ }
+ else if ((!strcmp(argv[j], "-marker")) && (++j < argc))
+ {
+ gMarkerPath = argv[j];;
+ }
}
return 0;
@@ -355,10 +373,13 @@ int main(int argc, char **argv)
//
gUpdateURL = NULL;
gProductName = NULL;
+ gBundleID = NULL;
+ gDmgFile = NULL;
+ gMarkerPath = NULL;
parse_args(argc, argv);
- if (!gUpdateURL)
+ if ((gUpdateURL == NULL) && (gDmgFile == NULL))
{
- llinfos << "Usage: mac_updater -url <url> [-name <product_name>] [-program <program_name>]" << llendl;
+ llinfos << "Usage: mac_updater -url <url> | -dmg <dmg file> [-name <product_name>] [-program <program_name>]" << llendl;
exit(1);
}
else
@@ -372,6 +393,14 @@ int main(int argc, char **argv)
{
gProductName = "Second Life";
}
+ if (gBundleID)
+ {
+ llinfos << "Bundle ID is: " << gBundleID << llendl;
+ }
+ else
+ {
+ gBundleID = "com.secondlife.indra.viewer";
+ }
}
llinfos << "Starting " << gProductName << " Updater" << llendl;
@@ -474,11 +503,18 @@ int main(int argc, char **argv)
NULL,
&retval_mac);
}
-
+
+ if(gMarkerPath != 0)
+ {
+ // Create a install fail marker that can be used by the viewer to
+ // detect install problems.
+ std::ofstream stream(gMarkerPath);
+ if(stream) stream << -1;
+ }
+ exit(-1);
+ } else {
+ exit(0);
}
-
- // Don't dispose of things, just exit. This keeps the update thread from potentially getting hosed.
- exit(0);
if(gWindow != NULL)
{
@@ -592,7 +628,8 @@ static bool isFSRefViewerBundle(FSRef *targetRef)
CFURLRef targetURL = NULL;
CFBundleRef targetBundle = NULL;
CFStringRef targetBundleID = NULL;
-
+ CFStringRef sourceBundleID = NULL;
+
targetURL = CFURLCreateFromFSRef(NULL, targetRef);
if(targetURL == NULL)
@@ -619,7 +656,8 @@ static bool isFSRefViewerBundle(FSRef *targetRef)
}
else
{
- if(CFStringCompare(targetBundleID, CFSTR("com.secondlife.indra.viewer"), 0) == kCFCompareEqualTo)
+ sourceBundleID = CFStringCreateWithCString(NULL, gBundleID, kCFStringEncodingUTF8);
+ if(CFStringCompare(sourceBundleID, targetBundleID, 0) == kCFCompareEqualTo)
{
// This is the bundle we're looking for.
result = true;
@@ -684,17 +722,26 @@ static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app)
// Looks promising. Check to see if it has the right bundle identifier.
if(isFSRefViewerBundle(&ref))
{
+ llinfos << name << " is the one" << llendl;
// This is the one. Return it.
*app = ref;
found = true;
+ break;
+ } else {
+ llinfos << name << " is not the bundle we are looking for; move along" << llendl;
}
+
}
}
}
}
- while(!err && !found);
+ while(!err);
+
+ llinfos << "closing the iterator" << llendl;
FSCloseIterator(iterator);
+
+ llinfos << "closed" << llendl;
}
if(!err && !found)
@@ -905,6 +952,22 @@ void *updatethreadproc(void*)
#endif // 0 *HACK for DEV-11935
+ // Skip downloading the file if the dmg was passed on the command line.
+ std::string dmgName;
+ if(gDmgFile != NULL) {
+ dmgName = basename((char *)gDmgFile);
+ char * dmgDir = dirname((char *)gDmgFile);
+ strncpy(tempDir, dmgDir, sizeof(tempDir));
+ err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);
+ if(err != noErr) throw 0;
+ chdir(tempDir);
+ goto begin_install;
+ } else {
+ // Continue on to download file.
+ dmgName = "SecondLife.dmg";
+ }
+
+
strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1);
if(mkdtemp(temp) == NULL)
{
@@ -963,14 +1026,17 @@ void *updatethreadproc(void*)
fclose(downloadFile);
downloadFile = NULL;
}
-
+
+ begin_install:
sendProgress(0, 0, CFSTR("Mounting image..."));
LLFile::mkdir("mnt", 0700);
// NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder,
// but if our cleanup fails, this makes it much harder for the user to unmount the image.
std::string mountOutput;
- FILE* mounter = popen("hdiutil attach SecondLife.dmg -mountpoint mnt", "r"); /* Flawfinder: ignore */
+ boost::format cmdFormat("hdiutil attach %s -mountpoint mnt");
+ cmdFormat % dmgName;
+ FILE* mounter = popen(cmdFormat.str().c_str(), "r"); /* Flawfinder: ignore */
if(mounter == NULL)
{
@@ -1036,12 +1102,19 @@ void *updatethreadproc(void*)
throw 0;
}
+ sendProgress(0, 0, CFSTR("Searching for the app bundle..."));
err = findAppBundleOnDiskImage(&mountRef, &sourceRef);
if(err != noErr)
{
llinfos << "Couldn't find application bundle on mounted disk image." << llendl;
throw 0;
}
+ else
+ {
+ llinfos << "found the bundle." << llendl;
+ }
+
+ sendProgress(0, 0, CFSTR("Preparing to copy files..."));
FSRef asideRef;
char aside[MAX_PATH]; /* Flawfinder: ignore */
@@ -1061,7 +1134,11 @@ void *updatethreadproc(void*)
// Move aside old version (into work directory)
err = FSMoveObject(&targetRef, &tempDirRef, &asideRef);
if(err != noErr)
+ {
+ llwarns << "failed to move aside old version (error code " <<
+ err << ")" << llendl;
throw 0;
+ }
// Grab the path for later use.
err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside));
@@ -1159,6 +1236,10 @@ void *updatethreadproc(void*)
llinfos << "Moving work directory to the trash." << llendl;
err = FSMoveObject(&tempDirRef, &trashFolderRef, NULL);
+ if(err != noErr) {
+ llwarns << "failed to move files to trash, (error code " <<
+ err << ")" << llendl;
+ }
// snprintf(temp, sizeof(temp), "rm -rf '%s'", tempDir);
// printf("%s\n", temp);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index bf885e5934..679637caf6 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -64,6 +64,7 @@ include_directories(
${LSCRIPT_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
${LLLOGIN_INCLUDE_DIRS}
+ ${UPDATER_INCLUDE_DIRS}
)
set(viewer_SOURCE_FILES
@@ -143,6 +144,7 @@ set(viewer_SOURCE_FILES
lleventnotifier.cpp
lleventpoll.cpp
llexpandabletextbox.cpp
+ llexternaleditor.cpp
llface.cpp
llfasttimerview.cpp
llfavoritesbar.cpp
@@ -200,6 +202,7 @@ set(viewer_SOURCE_FILES
llfloaterpostprocess.cpp
llfloaterpreference.cpp
llfloaterproperties.cpp
+ llfloaterregiondebugconsole.cpp
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
@@ -282,6 +285,7 @@ set(viewer_SOURCE_FILES
llloginhandler.cpp
lllogininstance.cpp
llmachineid.cpp
+ llmainlooprepeater.cpp
llmanip.cpp
llmaniprotate.cpp
llmanipscale.cpp
@@ -290,7 +294,6 @@ set(viewer_SOURCE_FILES
llmediadataclient.cpp
llmemoryview.cpp
llmenucommands.cpp
- llmetricperformancetester.cpp
llmimetypes.cpp
llmorphview.cpp
llmoveview.cpp
@@ -444,6 +447,7 @@ set(viewer_SOURCE_FILES
lltoastimpanel.cpp
lltoastnotifypanel.cpp
lltoastpanel.cpp
+ lltoastscripttextbox.cpp
lltool.cpp
lltoolbrush.cpp
lltoolcomp.cpp
@@ -675,6 +679,7 @@ set(viewer_HEADER_FILES
lleventnotifier.h
lleventpoll.h
llexpandabletextbox.h
+ llexternaleditor.h
llface.h
llfasttimerview.h
llfavoritesbar.h
@@ -732,6 +737,7 @@ set(viewer_HEADER_FILES
llfloaterpostprocess.h
llfloaterpreference.h
llfloaterproperties.h
+ llfloaterregiondebugconsole.h
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h
@@ -814,6 +820,7 @@ set(viewer_HEADER_FILES
llloginhandler.h
lllogininstance.h
llmachineid.h
+ llmainlooprepeater.h
llmanip.h
llmaniprotate.h
llmanipscale.h
@@ -822,7 +829,6 @@ set(viewer_HEADER_FILES
llmediadataclient.h
llmemoryview.h
llmenucommands.h
- llmetricperformancetester.h
llmimetypes.h
llmorphview.h
llmoveview.h
@@ -973,6 +979,7 @@ set(viewer_HEADER_FILES
lltoastimpanel.h
lltoastnotifypanel.h
lltoastpanel.h
+ lltoastscripttextbox.h
lltool.h
lltoolbrush.h
lltoolcomp.h
@@ -1642,7 +1649,14 @@ if (WINDOWS)
endif (PACKAGE)
endif (WINDOWS)
+# *NOTE - this list is very sensitive to ordering, test carefully on all
+# platforms if you change the releative order of the entries here.
+# In particular, cmake 2.6.4 (when buidling with linux/makefile generators)
+# appears to sometimes de-duplicate redundantly listed dependencies improperly.
+# To work around this, higher level modules should be listed before the modules
+# that they depend upon. -brad
target_link_libraries(${VIEWER_BINARY_NAME}
+ ${UPDATER_LIBRARIES}
${LLAUDIO_LIBRARIES}
${LLCHARACTER_LIBRARIES}
${LLIMAGE_LIBRARIES}
@@ -1829,10 +1843,18 @@ if (PACKAGE)
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
endif (LINUX)
+ if(CMAKE_CFG_INTDIR STREQUAL ".")
+ set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
+ else(CMAKE_CFG_INTDIR STREQUAL ".")
+ # set LLBUILD_CONFIG to be a shell variable evaluated at build time
+ # reflecting the configuration we are currently building.
+ set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR})
+ endif(CMAKE_CFG_INTDIR STREQUAL ".")
add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
COMMAND "${PYTHON_EXECUTABLE}"
ARGS
"${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
+ "${LLBUILD_CONFIG}"
"${VIEWER_DIST_DIR}"
"${VIEWER_EXE_GLOBS}"
"${VIEWER_LIB_GLOB}"
@@ -1841,7 +1863,7 @@ if (PACKAGE)
DEPENDS generate_breakpad_symbols.py
VERBATIM
)
- add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}")
+ add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}")
add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}")
add_dependencies(package generate_breakpad_symbols)
endif (PACKAGE)
@@ -1855,7 +1877,9 @@ if (LL_TESTS)
lldateutil.cpp
llmediadataclient.cpp
lllogininstance.cpp
+ llremoteparcelrequest.cpp
llviewerhelputil.cpp
+ llversioninfo.cpp
)
##################################################
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 00d69f805e..1b8393330d 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -118,6 +118,8 @@
<map>
<key>desc</key>
<string>Log metrics for benchmarking</string>
+ <key>count</key>
+ <integer>1</integer>
<key>map-to</key>
<string>LogMetrics</string>
</map>
@@ -361,8 +363,7 @@
<map>
<key>count</key>
<integer>1</integer>
- <key>map-to</key>
- <string>VersionChannelName</string>
+ <!-- Special case. Not mapped to a setting. -->
</map>
<key>loginpage</key>
@@ -391,5 +392,13 @@
<string>CrashOnStartup</string>
</map>
+ <key>disablecrashlogger</key>
+ <map>
+ <key>desc</key>
+ <string>Disables the crash logger and lets the OS handle crashes</string>
+ <key>map-to</key>
+ <string>DisableCrashLogger</string>
+ </map>
+
</map>
</llsd>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ee01ee7833..402a0e85c4 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -24,6 +24,28 @@
<key>Value</key>
<real>300</real>
</map>
+ <key>AdminMenu</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable the debug admin menu from the main menu. Note: This will just allow the menu to be shown; this does not grant admin privileges.</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ActiveFloaterTransparency</key>
+ <map>
+ <key>Comment</key>
+ <string>Transparency of active floaters (floaters that have focus)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.95</real>
+ </map>
<key>AdvanceSnapshot</key>
<map>
<key>Comment</key>
@@ -1343,6 +1365,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>LetterKeysFocusChatBar</key>
+ <map>
+ <key>Comment</key>
+ <string>When printable characters keys (possibly with Shift held) are pressed, the chatbar takes focus</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ChatBubbleOpacity</key>
<map>
<key>Comment</key>
@@ -2567,6 +2600,28 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>EnableGroupChatPopups</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable Incoming Group Chat Popups</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableIMChatPopups</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable Incoming IM Chat Popups</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>DisplayAvatarAgentTarget</key>
<map>
<key>Comment</key>
@@ -3953,6 +4008,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>InactiveFloaterTransparency</key>
+ <map>
+ <key>Comment</key>
+ <string>Transparency of inactive floaters (floaters that have no focus)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.65</real>
+ </map>
<key>InBandwidth</key>
<map>
<key>Comment</key>
@@ -4581,6 +4647,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>LogTextureNetworkTraffic</key>
+ <map>
+ <key>Comment</key>
+ <string>Log network traffic for textures</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>LoginAsGod</key>
<map>
<key>Comment</key>
@@ -5893,6 +5970,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>ObjectCacheEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable the object cache.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>OpenDebugStatAdvanced</key>
<map>
<key>Comment</key>
@@ -8263,6 +8351,17 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>RenderTransparentWater</key>
+ <map>
+ <key>Comment</key>
+ <string>Render water as transparent. Setting to false renders water as opaque with a simple texture applied.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RenderTreeLODFactor</key>
<map>
<key>Comment</key>
@@ -10991,7 +11090,62 @@
<key>Value</key>
<integer>15</integer>
</map>
- <key>UploadBakedTexOld</key>
+ <key>UpdaterServiceActive</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable or disable the updater service.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>UpdaterServiceCheckPeriod</key>
+ <map>
+ <key>Comment</key>
+ <string>Default period between update checking.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>3600</integer>
+ </map>
+ <key>UpdaterServiceURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Default location for the updater service.</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>https://update.secondlife.com</string>
+ </map>
+ <key>UpdaterServicePath</key>
+ <map>
+ <key>Comment</key>
+ <string>Path on the update server host.</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>update</string>
+ </map>
+ <key>UpdaterServiceProtocolVersion</key>
+ <map>
+ <key>Comment</key>
+ <string>The update protocol version to use.</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>v1.0</string>
+ </map>
+ <key>UploadBakedTexOld</key>
<map>
<key>Comment</key>
<string>Forces the baked texture pipeline to upload using the old method.</string>
@@ -11145,6 +11299,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>SpeakerParticipantDefaultOrder</key>
+ <map>
+ <key>Comment</key>
+ <string>Order for displaying speakers in voice controls. 0 = alphabetical. 1 = recent.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>SpeakerParticipantRemoveDelay</key>
<map>
<key>Comment</key>
@@ -11300,27 +11465,38 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>VerboseLogs</key>
+ <key>InterpolationTime</key>
<map>
<key>Comment</key>
- <string>Display source file and line number for each log item for debugging purposes</string>
+ <string>How long to extrapolate object motion after last packet received</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>Boolean</string>
+ <string>F32</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>3.0</integer>
</map>
- <key>VersionChannelName</key>
+ <key>InterpolationPhaseOut</key>
<map>
<key>Comment</key>
- <string>Versioning Channel Name.</string>
+ <string>Seconds to phase out interpolated motion</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>F32</string>
<key>Value</key>
- <string>Second Life Release</string>
+ <integer>1.0</integer>
+ </map>
+ <key>VerboseLogs</key>
+ <map>
+ <key>Comment</key>
+ <string>Display source file and line number for each log item for debugging purposes</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
</map>
<key>VertexShaderEnable</key>
<map>
@@ -11795,10 +11971,10 @@
<key>Value</key>
<real>150000.0</real>
</map>
- <key>XUIEditor</key>
+ <key>ExternalEditor</key>
<map>
<key>Comment</key>
- <string>Path to program used to edit XUI files</string>
+ <string>Path to program used to edit LSL scripts and XUI files, e.g.: /usr/bin/gedit --new-window "%s"</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -12145,5 +12321,16 @@
<key>Value</key>
<real>300.0</real>
</map>
+ <key>GroupMembersSortOrder</key>
+ <map>
+ <key>Comment</key>
+ <string>The order by which group members will be sorted (name|donated|online)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>name</string>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index dc76a4e518..705c73cbf7 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -110,7 +110,17 @@
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
-
+ <key>LogFileNamewithDate</key>
+ <map>
+ <key>Comment</key>
+ <string>Add Date Stamp to chat and IM Logs with format chat-YYYY-MM-DD and 'IM file name'-YYYY-MM. To view old logs goto ..\Second Life\[login name]</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<!-- Settings below are for back compatibility only.
They are not used in current viewer anymore. But they can't be removed to avoid
influence on previous versions of the viewer in case of settings are not used or default value
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index d69842d5f1..a95abd7dd1 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -42,6 +42,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@@ -80,6 +81,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
+RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@@ -108,6 +110,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -135,6 +138,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -162,6 +166,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index efe29005f2..a52b32355d 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -42,6 +42,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@@ -79,6 +80,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
+RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@@ -107,6 +109,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -134,6 +137,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -161,6 +165,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index f030c9f8e5..6dabef53a8 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -43,6 +43,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 3
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@@ -80,6 +81,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
+RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@@ -107,6 +109,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -133,6 +136,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -159,6 +163,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 3
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index dae7705971..a09ba17c62 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -42,6 +42,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVBOEnable 1 1
@@ -80,6 +81,7 @@ RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
+RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 0.5
@@ -108,6 +110,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 1.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -135,6 +138,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 2
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -162,6 +166,7 @@ RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 2.0
diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py
index 8f2dfd2348..4fd04d780e 100644
--- a/indra/newview/generate_breakpad_symbols.py
+++ b/indra/newview/generate_breakpad_symbols.py
@@ -31,6 +31,7 @@ import fnmatch
import itertools
import operator
import os
+import re
import sys
import shlex
import subprocess
@@ -45,8 +46,12 @@ class MissingModuleError(Exception):
Exception.__init__(self, "Failed to find required modules: %r" % modules)
self.modules = modules
-def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file):
- print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
+def main(configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file):
+ print "generate_breakpad_symbols run with args: %s" % str((configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
+
+ if not re.match("release", configuration, re.IGNORECASE):
+ print "skipping breakpad symbol generation for non-release build."
+ return 0
# split up list of viewer_exes
# "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin']
@@ -122,7 +127,7 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil
return 0
if __name__ == "__main__":
- if len(sys.argv) != 6:
+ if len(sys.argv) != 7:
usage()
sys.exit(1)
sys.exit(main(*sys.argv[1:]))
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index d5712f80cf..4e8ed807ee 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -85,6 +85,8 @@ AutoCloseWindow true ; after all files install, close window
InstallDir "$PROGRAMFILES\${INSTNAME}"
InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" ""
DirText $(DirectoryChooseTitle) $(DirectoryChooseSetup)
+Page directory dirPre
+Page instfiles
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Variables
@@ -95,6 +97,8 @@ Var INSTFLAGS
Var INSTSHORTCUT
Var COMMANDLINE ; command line passed to this installer, set in .onInit
Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer
+Var SKIP_DIALOGS ; set from command line in .onInit. autoinstall
+ ; GUI and the defaults.
;;; Function definitions should go before file includes, because calls to
;;; DLLs like LangDLL trigger an implicit file include, so if that call is at
@@ -110,6 +114,9 @@ Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function .onInstSuccess
Push $R0 # Option value, unused
+
+ StrCmp $SKIP_DIALOGS "true" label_launch
+
${GetOptions} $COMMANDLINE "/AUTOSTART" $R0
# If parameter was there (no error) just launch
# Otherwise ask
@@ -128,6 +135,13 @@ label_no_launch:
Pop $R0
FunctionEnd
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Pre-directory page callback
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function dirPre
+ StrCmp $SKIP_DIALOGS "true" 0 +2
+ Abort
+FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Make sure we're not on Windows 98 / ME
@@ -145,7 +159,8 @@ Function CheckWindowsVersion
StrCmp $R0 "NT" win_ver_bad
Return
win_ver_bad:
- MessageBox MB_YESNO $(CheckWindowsVersionMB) IDNO win_ver_abort
+ StrCmp $SKIP_DIALOGS "true" +2 ; If skip_dialogs is set just install
+ MessageBox MB_YESNO $(CheckWindowsVersionMB) IDNO win_ver_abort
Return
win_ver_abort:
Quit
@@ -184,13 +199,13 @@ FunctionEnd
; If it has, allow user to bail out of install process.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function CheckIfAlreadyCurrent
- Push $0
- ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version"
- StrCmp $0 ${VERSION_LONG} 0 DONE
- MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK DONE
+ Push $0
+ ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version"
+ StrCmp $0 ${VERSION_LONG} 0 continue_install
+ StrCmp $SKIP_DIALOGS "true" continue_install
+ MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK continue_install
Quit
-
- DONE:
+continue_install:
Pop $0
Return
FunctionEnd
@@ -203,7 +218,9 @@ Function CloseSecondLife
Push $0
FindWindow $0 "Second Life" ""
IntCmp $0 0 DONE
- MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL
+
+ StrCmp $SKIP_DIALOGS "true" CLOSE
+ MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL
CANCEL_INSTALL:
Quit
@@ -659,23 +676,29 @@ FunctionEnd
Function .onInit
Push $0
${GetParameters} $COMMANDLINE ; get our command line
+
+ ${GetOptions} $COMMANDLINE "/SKIP_DIALOGS" $0
+ IfErrors +2 0 ; If error jump past setting SKIP_DIALOGS
+ StrCpy $SKIP_DIALOGS "true"
+
${GetOptions} $COMMANDLINE "/LANGID=" $0 ; /LANGID=1033 implies US English
; If no language (error), then proceed
- IfErrors lbl_check_silent
+ IfErrors lbl_configure_default_lang
; No error means we got a language, so use it
StrCpy $LANGUAGE $0
Goto lbl_return
-lbl_check_silent:
- ; For silent installs, no language prompt, use default
- IfSilent lbl_return
-
- ; If we currently have a version of SL installed, default to the language of that install
+lbl_configure_default_lang:
+ ; If we currently have a version of SL installed, default to the language of that install
; Otherwise don't change $LANGUAGE and it will default to the OS UI language.
- ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" "InstallerLanguage"
- IfErrors lbl_build_menu
+ ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" "InstallerLanguage"
+ IfErrors +2 0 ; If error skip the copy instruction
StrCpy $LANGUAGE $0
+ ; For silent installs, no language prompt, use default
+ IfSilent lbl_return
+ StrCmp $SKIP_DIALOGS "true" lbl_return
+
lbl_build_menu:
Push ""
# Use separate file so labels can be UTF-16 but we can still merge changes
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index c9bd7851ed..001a6a8851 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -56,9 +56,9 @@
#include "llparcel.h"
#include "llrendersphere.h"
#include "llsdutil.h"
-#include "llsidetray.h"
#include "llsky.h"
#include "llsmoothstep.h"
+#include "llstartup.h"
#include "llstatusbar.h"
#include "llteleportflags.h"
#include "lltool.h"
@@ -1726,9 +1726,6 @@ void LLAgent::endAnimationUpdateUI()
LLBottomTray::getInstance()->onMouselookModeOut();
- LLSideTray::getInstance()->getButtonsPanel()->setVisible(TRUE);
- LLSideTray::getInstance()->updateSidetrayVisibility();
-
LLPanelStandStopFlying::getInstance()->setVisible(TRUE);
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
@@ -1828,9 +1825,6 @@ void LLAgent::endAnimationUpdateUI()
LLBottomTray::getInstance()->onMouselookModeIn();
- LLSideTray::getInstance()->getButtonsPanel()->setVisible(FALSE);
- LLSideTray::getInstance()->updateSidetrayVisibility();
-
LLPanelStandStopFlying::getInstance()->setVisible(FALSE);
// clear out camera lag effect
@@ -2452,7 +2446,7 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
BOOL LLAgent::canJoinGroups() const
{
- return mGroups.count() < MAX_AGENT_GROUPS;
+ return mGroups.count() < gMaxAgentGroups;
}
LLQuaternion LLAgent::getHeadRotation()
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 6c598d5d71..aebebad96a 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -33,6 +33,7 @@
#include "llagentconstants.h"
#include "llagentdata.h" // gAgentID, gAgentSessionID
#include "llcharacter.h" // LLAnimPauseRequest
+#include "llcoordframe.h" // for mFrameAgent
#include "llpointer.h"
#include "lluicolor.h"
#include "llvoavatardefines.h"
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 68e408d3e4..7c953cd2dc 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -296,8 +296,11 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
LLSelectMgr::getInstance()->deselectAll();
}
- // Hide all popup menus
- gMenuHolder->hideMenus();
+ if (gMenuHolder != NULL)
+ {
+ // Hide all popup menus
+ gMenuHolder->hideMenus();
+ }
}
if (change_camera && !gSavedSettings.getBOOL("FreezeTime"))
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index ed5e8ceee3..4e0bfb2e22 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2204,12 +2204,11 @@ void LLAppearanceMgr::updateIsDirty()
base_outfit = catp->getUUID();
}
- if(base_outfit.isNull())
- {
- // no outfit link found, display "unsaved outfit"
- mOutfitIsDirty = true;
- }
- else
+ // Set dirty to "false" if no base outfit found to disable "Save"
+ // and leave only "Save As" enabled in My Outfits.
+ mOutfitIsDirty = false;
+
+ if (base_outfit.notNull())
{
LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK);
@@ -2248,8 +2247,6 @@ void LLAppearanceMgr::updateIsDirty()
return;
}
}
-
- mOutfitIsDirty = false;
}
}
@@ -2440,6 +2437,12 @@ public:
virtual ~LLShowCreatedOutfit()
{
+ if (!LLApp::isRunning())
+ {
+ llwarns << "called during shutdown, skipping" << llendl;
+ return;
+ }
+
LLSD key;
//EXT-7727. For new accounts LLShowCreatedOutfit is created during login process
@@ -2635,6 +2638,7 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items,
LLAppearanceMgr::LLAppearanceMgr():
mAttachmentInvLinkEnabled(false),
mOutfitIsDirty(false),
+ mOutfitLocked(false),
mIsInUpdateAppearanceFromCOF(false)
{
LLOutfitObserver& outfit_observer = LLOutfitObserver::instance();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ba14c248aa..6c07974f69 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -30,6 +30,7 @@
// Viewer includes
#include "llversioninfo.h"
+#include "llversionviewer.h"
#include "llfeaturemanager.h"
#include "lluictrlfactory.h"
#include "lltexteditor.h"
@@ -82,6 +83,7 @@
#include "llweb.h"
#include "llsecondlifeurls.h"
+#include "llupdaterservice.h"
// Linden library includes
#include "llavatarnamecache.h"
@@ -195,6 +197,8 @@
#include "llsecapi.h"
#include "llmachineid.h"
+#include "llmainlooprepeater.h"
+
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
// this app, or another 'component' of the viewer. App globals should be
@@ -509,16 +513,10 @@ class LLFastTimerLogThread : public LLThread
public:
std::string mFile;
- LLFastTimerLogThread() : LLThread("fast timer log")
+ LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
{
- if(LLFastTimer::sLog)
- {
- mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp");
- }
- if(LLFastTimer::sMetricLog)
- {
- mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp");
- }
+ std::string file_name = test_name + std::string(".slp");
+ mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
}
void run()
@@ -534,6 +532,7 @@ public:
os.close();
}
+
};
//virtual
@@ -580,7 +579,8 @@ LLAppViewer::LLAppViewer() :
mAgentRegionLastAlive(false),
mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
- mFastTimerLogThread(NULL)
+ mFastTimerLogThread(NULL),
+ mUpdater(new LLUpdaterService())
{
if(NULL != sInstance)
{
@@ -656,10 +656,13 @@ bool LLAppViewer::init()
initThreads();
writeSystemInfo();
- // Build a string representing the current version number.
- gCurrentVersion = llformat("%s %s",
- gSavedSettings.getString("VersionChannelName").c_str(),
- LLVersionInfo::getVersion().c_str());
+ // Initialize updater service (now that we have an io pump)
+ initUpdater();
+ if(isQuitting())
+ {
+ // Early out here because updater set the quitting flag.
+ return true;
+ }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -803,6 +806,9 @@ bool LLAppViewer::init()
return 1;
}
+ // Initialize the repeater service.
+ LLMainLoopRepeater::instance().start();
+
//
// Initialize the window
//
@@ -899,7 +905,8 @@ bool LLAppViewer::init()
gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
// Save the current version to the prefs file
- gSavedSettings.setString("LastRunVersion", gCurrentVersion);
+ gSavedSettings.setString("LastRunVersion",
+ LLVersionInfo::getChannelAndVersion());
gSimLastTime = gRenderStartTime.getElapsedTimeF32();
gSimFrames = (F32)gFrameCount;
@@ -974,13 +981,14 @@ bool LLAppViewer::mainLoop()
gServicePump = new LLPumpIO(gAPRPoolp);
LLHTTPClient::setPump(*gServicePump);
LLCurl::setCAFile(gDirUtilp->getCAFile());
-
+
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
LLVoiceChannel::initClass();
LLVoiceClient::getInstance()->init(gServicePump);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
+ LLFrameTimer memCheckTimer;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
joystick->setNeedsReset(true);
@@ -991,11 +999,29 @@ bool LLAppViewer::mainLoop()
// point of posting.
LLSD newFrame;
+ const F32 memory_check_interval = 1.0f ; //second
+
// Handle messages
while (!LLApp::isExiting())
{
LLFastTimer::nextFrame(); // Should be outside of any timer instances
+ //clear call stack records
+ llclearcallstacks;
+
+ //check memory availability information
+ {
+ if(memory_check_interval < memCheckTimer.getElapsedTimeF32())
+ {
+ memCheckTimer.reset() ;
+
+ //update the availability of memory
+ LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
+ }
+ llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ;
+ llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ;
+ }
+
try
{
pingMainloopTimeout("Main:MiscNativeWindowEvents");
@@ -1222,11 +1248,20 @@ bool LLAppViewer::mainLoop()
resumeMainloopTimeout();
pingMainloopTimeout("Main:End");
- }
-
+ }
}
catch(std::bad_alloc)
{
+ {
+ llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ;
+ llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ;
+
+ LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
+
+ llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ;
+ llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ;
+ }
+
//stop memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
@@ -1329,11 +1364,14 @@ bool LLAppViewer::cleanup()
llinfos << "Cleaning Up" << llendflush;
// Must clean up texture references before viewer window is destroyed.
- LLHUDManager::getInstance()->updateEffects();
- LLHUDObject::updateAll();
- LLHUDManager::getInstance()->cleanupEffects();
- LLHUDObject::cleanupHUDObjects();
- llinfos << "HUD Objects cleaned up" << llendflush;
+ if(LLHUDManager::instanceExists())
+ {
+ LLHUDManager::getInstance()->updateEffects();
+ LLHUDObject::updateAll();
+ LLHUDManager::getInstance()->cleanupEffects();
+ LLHUDObject::cleanupHUDObjects();
+ llinfos << "HUD Objects cleaned up" << llendflush;
+ }
LLKeyframeDataCache::clear();
@@ -1345,8 +1383,10 @@ bool LLAppViewer::cleanup()
// Note: this is where gWorldMap used to be deleted.
// Note: this is where gHUDManager used to be deleted.
- LLHUDManager::getInstance()->shutdownClass();
-
+ if(LLHUDManager::instanceExists())
+ {
+ LLHUDManager::getInstance()->shutdownClass();
+ }
delete gAssetStorage;
gAssetStorage = NULL;
@@ -1614,22 +1654,16 @@ bool LLAppViewer::cleanup()
{
llinfos << "Analyzing performance" << llendl;
- if(LLFastTimer::sLog)
- {
- LLFastTimerView::doAnalysis(
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_baseline.slp"),
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp"),
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_report.csv"));
- }
- if(LLFastTimer::sMetricLog)
- {
- LLFastTimerView::doAnalysis(
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_baseline.slp"),
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp"),
- gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
- }
+ std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
+ std::string current_name = LLFastTimer::sLogName + ".slp";
+ std::string report_name = LLFastTimer::sLogName + "_report.csv";
+
+ LLFastTimerView::doAnalysis(
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
+ gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
}
- LLMetricPerformanceTester::cleanClass() ;
+ LLMetricPerformanceTesterBasic::cleanClass() ;
llinfos << "Cleaning up Media and Textures" << llendflush;
@@ -1648,7 +1682,10 @@ bool LLAppViewer::cleanup()
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Auditing VFS" << llendl;
- gVFS->audit();
+ if(gVFS)
+ {
+ gVFS->audit();
+ }
#endif
llinfos << "Misc Cleanup" << llendflush;
@@ -1689,6 +1726,8 @@ bool LLAppViewer::cleanup()
llinfos << "File launched." << llendflush;
}
+ LLMainLoopRepeater::instance().stop();
+
ll_close_fail_log();
llinfos << "Goodbye!" << llendflush;
@@ -1736,7 +1775,7 @@ bool LLAppViewer::initThreads()
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
{
LLFastTimer::sLogLock = new LLMutex(NULL);
- mFastTimerLogThread = new LLFastTimerLogThread();
+ mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
mFastTimerLogThread->start();
}
@@ -1935,8 +1974,6 @@ bool LLAppViewer::initConfiguration()
gSavedSettings.setString("ClientSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
- gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel());
-
#ifndef LL_RELEASE_FOR_DOWNLOAD
// provide developer build only overrides for these control variables that are not
// persisted to settings.xml
@@ -2019,6 +2056,15 @@ bool LLAppViewer::initConfiguration()
// - apply command line settings
clp.notify();
+ // Register the core crash option as soon as we can
+ // if we want gdb post-mortem on cores we need to be up and running
+ // ASAP or we might miss init issue etc.
+ if(clp.hasOption("disablecrashlogger"))
+ {
+ llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl;
+ LLAppViewer::instance()->disableCrashlogger();
+ }
+
// Handle initialization from settings.
// Start up the debugging console before handling other options.
if (gSavedSettings.getBOOL("ShowConsoleWindow"))
@@ -2068,6 +2114,11 @@ bool LLAppViewer::initConfiguration()
}
}
+ if(clp.hasOption("channel"))
+ {
+ LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
+ }
+
// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
if(clp.hasOption("crashonstartup"))
@@ -2078,11 +2129,25 @@ bool LLAppViewer::initConfiguration()
if (clp.hasOption("logperformance"))
{
LLFastTimer::sLog = TRUE;
+ LLFastTimer::sLogName = std::string("performance");
}
- if(clp.hasOption("logmetrics"))
+ if (clp.hasOption("logmetrics"))
{
LLFastTimer::sMetricLog = TRUE ;
+ // '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
+ // In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
+ std::string test_name = clp.getOption("logmetrics")[0];
+ llinfos << "'--logmetrics' argument : " << test_name << llendl;
+ if (test_name == "")
+ {
+ llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl;
+ LLFastTimer::sLogName = DEFAULT_METRIC_NAME;
+ }
+ else
+ {
+ LLFastTimer::sLogName = test_name;
+ }
}
if (clp.hasOption("graphicslevel"))
@@ -2323,6 +2388,58 @@ bool LLAppViewer::initConfiguration()
return true; // Config was successful.
}
+namespace {
+ // *TODO - decide if there's a better place for this function.
+ // do we need a file llupdaterui.cpp or something? -brad
+ bool notify_update(LLSD const & evt)
+ {
+ switch (evt["type"].asInteger())
+ {
+ case LLUpdaterService::DOWNLOAD_COMPLETE:
+ LLNotificationsUtil::add("DownloadBackground");
+ break;
+ case LLUpdaterService::INSTALL_ERROR:
+ LLNotificationsUtil::add("FailedUpdateInstall");
+ break;
+ default:
+ llinfos << "unhandled update event " << evt << llendl;
+ break;
+ }
+
+ // let others also handle this event by default
+ return false;
+ }
+};
+
+void LLAppViewer::initUpdater()
+{
+ // Initialize the updater service.
+ // Generate URL to the udpater service
+ // Get Channel
+ // Get Version
+ std::string url = gSavedSettings.getString("UpdaterServiceURL");
+ std::string channel = LLVersionInfo::getChannel();
+ std::string version = LLVersionInfo::getVersion();
+ std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion");
+ std::string service_path = gSavedSettings.getString("UpdaterServicePath");
+ U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
+
+ mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
+ mUpdater->initialize(protocol_version,
+ url,
+ service_path,
+ channel,
+ version);
+ mUpdater->setCheckPeriod(check_period);
+ if(gSavedSettings.getBOOL("UpdaterServiceActive"))
+ {
+ bool install_if_ready = true;
+ mUpdater->startChecking(install_if_ready);
+ }
+
+ LLEventPump & updater_pump = LLEventPumps::instance().obtain(LLUpdaterService::pumpName());
+ updater_pump.listen("notify_update", &notify_update);
+}
void LLAppViewer::checkForCrash(void)
{
@@ -2483,15 +2600,18 @@ void LLAppViewer::cleanupSavedSettings()
// save window position if not maximized
// as we don't track it in callbacks
- BOOL maximized = gViewerWindow->mWindow->getMaximized();
- if (!maximized)
+ if(NULL != gViewerWindow)
{
- LLCoordScreen window_pos;
-
- if (gViewerWindow->mWindow->getPosition(&window_pos))
+ BOOL maximized = gViewerWindow->mWindow->getMaximized();
+ if (!maximized)
{
- gSavedSettings.setS32("WindowX", window_pos.mX);
- gSavedSettings.setS32("WindowY", window_pos.mY);
+ LLCoordScreen window_pos;
+
+ if (gViewerWindow->mWindow->getPosition(&window_pos))
+ {
+ gSavedSettings.setS32("WindowX", window_pos.mX);
+ gSavedSettings.setS32("WindowY", window_pos.mY);
+ }
}
}
@@ -2514,7 +2634,7 @@ void LLAppViewer::writeSystemInfo()
{
gDebugInfo["SLLog"] = LLError::logFileName();
- gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
+ gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
@@ -2595,6 +2715,11 @@ void LLAppViewer::handleViewerCrash()
abort();
}
+ if (LLApp::isCrashloggerDisabled())
+ {
+ abort();
+ }
+
// Returns whether a dialog was shown.
// Only do the logic in here once
if (pApp->mReportedCrash)
@@ -2612,7 +2737,7 @@ void LLAppViewer::handleViewerCrash()
//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version
//to check against no matter what
- gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
+ gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
@@ -2990,7 +3115,7 @@ void LLAppViewer::migrateCacheDirectory()
S32 file_count = 0;
std::string file_name;
std::string mask = delimiter + "*.*";
- while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name, false))
+ while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name))
{
if (file_name == "." || file_name == "..") continue;
std::string source_path = old_cache_dir + delimiter + file_name;
@@ -3209,7 +3334,7 @@ bool LLAppViewer::initCache()
dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
std::string found_file;
- if (gDirUtilp->getNextFileInDir(dir, mask, found_file, false))
+ if (gDirUtilp->getNextFileInDir(dir, mask, found_file))
{
old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file;
@@ -4225,7 +4350,10 @@ void LLAppViewer::disconnectViewer()
// This is where we used to call gObjectList.destroy() and then delete gWorldp.
// Now we just ask the LLWorld singleton to cleanly shut down.
- LLWorld::getInstance()->destroyClass();
+ if(LLWorld::instanceExists())
+ {
+ LLWorld::getInstance()->destroyClass();
+ }
// call all self-registered classes
LLDestroyClassList::instance().fireCallbacks();
@@ -4339,7 +4467,7 @@ void LLAppViewer::handleLoginComplete()
initMainloopTimeout("Mainloop Init");
// Store some data to DebugInfo in case of a freeze.
- gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
+ gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
@@ -4445,7 +4573,7 @@ void LLAppViewer::launchUpdater()
// *TODO change userserver to be grid on both viewer and sim, since
// userserver no longer exists.
query_map["userserver"] = LLGridManager::getInstance()->getGridLabel();
- query_map["channel"] = gSavedSettings.getString("VersionChannelName");
+ query_map["channel"] = LLVersionInfo::getChannel();
// *TODO constantize this guy
// *NOTE: This URL is also used in win_setup/lldownloader.cpp
LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
@@ -4513,6 +4641,8 @@ void LLAppViewer::launchUpdater()
LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -bundleid \"";
+ LLAppViewer::sUpdaterInfo->mUpdateExePath += LL_VERSION_BUNDLE_ID;
LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index fdc3b9ef9e..aa4256a2bd 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -39,7 +39,7 @@ class LLTextureCache;
class LLImageDecodeThread;
class LLTextureFetch;
class LLWatchdogTimeout;
-class LLCommandLineParser;
+class LLUpdaterService;
struct apr_dso_handle_t;
@@ -186,7 +186,7 @@ private:
bool initThreads(); // Initialize viewer threads, return false on failure.
bool initConfiguration(); // Initialize settings from the command line/config file.
-
+ void initUpdater(); // Initialize the updater service.
bool initCache(); // Initialize local client cache.
@@ -251,7 +251,9 @@ private:
LLWatchdogTimeout* mMainloopTimeout;
+ // For performance and metric gathering
LLThread* mFastTimerLogThread;
+
// for tracking viewer<->region circuit death
bool mAgentRegionLastAlive;
LLUUID mAgentRegionLastID;
@@ -260,7 +262,16 @@ private:
std::set<struct apr_dso_handle_t*> mPlugins;
+ U32 mAvailPhysicalMemInKB ;
+ U32 mAvailVirtualMemInKB ;
+
+ boost::scoped_ptr<LLUpdaterService> mUpdater;
+
+ //---------------------------------------------
+ //*NOTE: Mani - legacy updater stuff
+ // Still useable?
public:
+
//some information for updater
typedef struct
{
@@ -270,6 +281,7 @@ public:
static LLUpdaterInfo *sUpdaterInfo ;
void launchUpdater();
+ //---------------------------------------------
};
// consts from viewer.h
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 7629265730..898cc1c0ba 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -504,8 +504,7 @@ std::string LLAppViewerLinux::generateSerialNumber()
// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
std::string this_name;
- BOOL wrap = FALSE;
- while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name, wrap))
+ while (gDirUtilp->getNextFileInDir(uuiddir, "*", this_name))
{
if (this_name.length() > best.length() ||
(this_name.length() == best.length() &&
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index a56dc129d4..30eecfe323 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -41,7 +41,7 @@
bool LLAvatarListItem::sStaticInitialized = false;
S32 LLAvatarListItem::sLeftPadding = 0;
-S32 LLAvatarListItem::sRightNamePadding = 0;
+S32 LLAvatarListItem::sNameRightPadding = 0;
S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT];
static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(&typeid(LLAvatarListItem::Params), "avatar_list_item");
@@ -52,7 +52,8 @@ LLAvatarListItem::Params::Params()
voice_call_joined_style("voice_call_joined_style"),
voice_call_left_style("voice_call_left_style"),
online_style("online_style"),
- offline_style("offline_style")
+ offline_style("offline_style"),
+ name_right_pad("name_right_pad", 0)
{};
@@ -119,6 +120,9 @@ BOOL LLAvatarListItem::postBuild()
// so that we can hide and show them again later.
initChildrenWidths(this);
+ // Right padding between avatar name text box and nearest visible child.
+ sNameRightPadding = LLUICtrlFactory::getDefaultParams<LLAvatarListItem>().name_right_pad;
+
sStaticInitialized = true;
}
@@ -486,7 +490,6 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item)
S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft;
sLeftPadding = avatar_item->mAvatarIcon->getRect().mLeft;
- sRightNamePadding = avatar_item->mLastInteractionTime->getRect().mLeft - avatar_item->mAvatarName->getRect().mRight;
S32 index = ALIC_COUNT;
sChildrenWidths[--index] = icon_width;
@@ -565,7 +568,7 @@ void LLAvatarListItem::updateChildren()
// apply paddings
name_new_width -= sLeftPadding;
- name_new_width -= sRightNamePadding;
+ name_new_width -= sNameRightPadding;
name_view_rect.setLeftTopAndSize(
name_new_left,
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index a069838ac3..c95ac39696 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -51,6 +51,8 @@ public:
online_style,
offline_style;
+ Optional<S32> name_right_pad;
+
Params();
};
@@ -215,7 +217,7 @@ private:
static bool sStaticInitialized; // this variable is introduced to improve code readability
static S32 sLeftPadding; // padding to first left visible child (icon or name)
- static S32 sRightNamePadding; // right padding from name to next visible child
+ static S32 sNameRightPadding; // right padding from name to next visible child
/**
* Contains widths of each child specified by EAvatarListItemChildIndex
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 29c2b7565e..6ccb5aaf54 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -1365,20 +1365,33 @@ void LLBottomTray::processExtendButtons(S32& available_width)
processExtendButton(*it, available_width);
}
+ const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+ static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+ const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
+
// then try to extend Speak button
- if (available_width > 0)
+ if (available_width > 0 || available_width_chiclet > 0)
{
S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK];
S32 panel_width = mSpeakPanel->getRect().getWidth();
S32 possible_extend_width = panel_max_width - panel_width;
- if (possible_extend_width >= 0 && possible_extend_width <= available_width) // HACK: this button doesn't change size so possible_extend_width will be 0
+
+ if (possible_extend_width >= 0 && possible_extend_width <= available_width + available_width_chiclet) // HACK: this button doesn't change size so possible_extend_width will be 0
{
mSpeakBtn->setLabelVisible(true);
mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight());
log(mSpeakBtn, "speak button is extended");
- available_width -= possible_extend_width;
-
+ if( available_width > possible_extend_width)
+ {
+ available_width -= possible_extend_width;
+ }
+ else
+ {
+ S32 required_width = possible_extend_width - available_width;
+ available_width = 0;
+ mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_width, mChicletPanel->getParent()->getRect().getHeight());
+ }
lldebugs << "Extending Speak button panel: " << mSpeakPanel->getName()
<< ", extended width: " << possible_extend_width
<< ", rest width to process: " << available_width
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 078bd73379..328c326278 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -45,6 +45,7 @@
#include "llspeakers.h"
#include "lltextutil.h"
#include "lltransientfloatermgr.h"
+#include "llviewercontrol.h"
#include "llviewerdisplayname.h"
#include "llviewerwindow.h"
#include "llvoicechannel.h"
@@ -166,6 +167,7 @@ BOOL LLCallFloater::postBuild()
//chrome="true" hides floater caption
if (mDragHandle)
mDragHandle->setTitleVisible(TRUE);
+ updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
updateSession();
@@ -205,6 +207,17 @@ void LLCallFloater::draw()
}
// virtual
+void LLCallFloater::setFocus( BOOL b )
+{
+ LLTransientDockableFloater::setFocus(b);
+
+ // Force using active floater transparency (STORM-730).
+ // We have to override setFocus() for LLCallFloater because selecting an item
+ // of the voice morphing combobox causes the floater to lose focus and thus become transparent.
+ updateTransparency(TT_ACTIVE);
+}
+
+// virtual
void LLCallFloater::onParticipantsChanged()
{
if (NULL == mParticipants) return;
@@ -335,8 +348,9 @@ void LLCallFloater::refreshParticipantList()
{
mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false);
mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
- mParticipants->setSortOrder(LLParticipantList::E_SORT_BY_RECENT_SPEAKERS);
-
+ const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
+ mParticipants->setSortOrder(LLParticipantList::EParticipantSortOrder(speaker_sort_order));
+
if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
{
mAvatarList->setNoItemsCommentText(getString("no_one_near"));
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 3bc7043353..00a3f76e56 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -64,6 +64,7 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void draw();
+ /*virtual*/ void setFocus( BOOL b );
/**
* Is called by LLVoiceClient::notifyParticipantObservers when voice participant list is changed.
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 9153f7325f..6e778de2d8 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -789,22 +789,26 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
// set the link for the object name to be the objectim SLapp
// (don't let object names with hyperlinks override our objectim Url)
LLStyle::Params link_params(style_params);
- link_params.color.control = "HTMLLinkColor";
+ LLColor4 link_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ link_params.color = link_color;
+ link_params.readonly_color = link_color;
+ link_params.is_link = true;
link_params.link_href = url;
- mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter,
+
+ mEditor->appendText(chat.mFromName + delimiter,
false, link_params);
}
else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)
{
LLStyle::Params link_params(style_params);
link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));
+
// Add link to avatar's inspector and delimiter to message.
- mEditor->appendText(link_params.link_href, false, style_params);
- mEditor->appendText(delimiter, false, style_params);
+ mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params);
}
else
{
- mEditor->appendText(chat.mFromName + delimiter, false, style_params);
+ mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params);
}
}
}
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index ababa71348..3afddc1145 100644
--- a/indra/newview/llchatitemscontainerctrl.cpp
+++ b/indra/newview/llchatitemscontainerctrl.cpp
@@ -31,6 +31,7 @@
#include "llchatmsgbox.h"
#include "llavatariconctrl.h"
+#include "llcommandhandler.h"
#include "llfloaterreg.h"
#include "lllocalcliprect.h"
#include "lltrans.h"
@@ -45,6 +46,40 @@ static const S32 msg_right_offset = 10;
static const S32 msg_height_pad = 5;
//*******************************************************************************************************************
+// LLObjectHandler
+//*******************************************************************************************************************
+
+// handle secondlife:///app/object/<ID>/inspect SLURLs
+class LLObjectHandler : public LLCommandHandler
+{
+public:
+ LLObjectHandler() : LLCommandHandler("object", UNTRUSTED_BLOCK) { }
+
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ if (params.size() < 2) return false;
+
+ LLUUID object_id;
+ if (!object_id.set(params[0], FALSE))
+ {
+ return false;
+ }
+
+ const std::string verb = params[1].asString();
+
+ if (verb == "inspect")
+ {
+ LLFloaterReg::showInstance("inspect_object", LLSD().with("object_id", object_id));
+ return true;
+ }
+
+ return false;
+ }
+};
+
+LLObjectHandler gObjectHandler;
+
+//*******************************************************************************************************************
//LLNearbyChatToastPanel
//*******************************************************************************************************************
@@ -169,30 +204,43 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
{
std::string str_sender;
- str_sender = "<nolink>"; // disable parsing URLs in object names (STORM-358)
- str_sender += fromName;
- str_sender += "</nolink>";
+ str_sender = fromName;
str_sender+=" ";
- //append user name
+ //append sender name
+ if (mSourceType == CHAT_SOURCE_AGENT || mSourceType == CHAT_SOURCE_OBJECT)
{
LLStyle::Params style_params_name;
- LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor");
+ std::string href;
+
+ if (mSourceType == CHAT_SOURCE_AGENT)
+ {
+ href = LLSLURL("agent", mFromID, "about").getSLURLString();
+ }
+ else
+ {
+ href = LLSLURL("object", mFromID, "inspect").getSLURLString();
+ }
- style_params_name.color(userNameColor);
+ style_params_name.color(textColor);
std::string font_name = LLFontGL::nameFromFont(messageFont);
std::string font_style_size = LLFontGL::sizeFromFont(messageFont);
style_params_name.font.name(font_name);
style_params_name.font.size(font_style_size);
- style_params_name.link_href = LLSLURL("agent",mFromID,"about").getSLURLString();
+ style_params_name.link_href = href;
+ style_params_name.is_link = true;
msg_text->appendText(str_sender, FALSE, style_params_name);
}
+ else
+ {
+ msg_text->appendText(str_sender, false);
+ }
}
//append text
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 8f385160e9..885d553524 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -1092,9 +1092,11 @@ LLChicletPanel::LLChicletPanel(const Params&p)
LLChicletPanel::~LLChicletPanel()
{
- LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
- LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
-
+ if(LLTransientFloaterMgr::instanceExists())
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
+ LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
+ }
}
void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index c9a526a3be..4a1ba6f1b5 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -53,6 +53,7 @@ LLColorSwatchCtrl::Params::Params()
alpha_background_image("alpha_background_image"),
border_color("border_color"),
label_width("label_width", -1),
+ label_height("label_height", -1),
caption_text("caption_text"),
border("border")
{
@@ -68,17 +69,20 @@ LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p)
mOnCancelCallback(p.cancel_callback()),
mOnSelectCallback(p.select_callback()),
mBorderColor(p.border_color()),
- mLabelWidth(p.label_width)
+ mLabelWidth(p.label_width),
+ mLabelHeight(p.label_height)
{
LLTextBox::Params tp = p.caption_text;
+ // use custom label height if it is provided
+ mLabelHeight = mLabelHeight != -1 ? mLabelHeight : BTN_HEIGHT_SMALL;
// label_width is specified, not -1
if(mLabelWidth!= -1)
{
- tp.rect(LLRect( 0, BTN_HEIGHT_SMALL, mLabelWidth, 0 ));
+ tp.rect(LLRect( 0, mLabelHeight, mLabelWidth, 0 ));
}
else
{
- tp.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 ));
+ tp.rect(LLRect( 0, mLabelHeight, getRect().getWidth(), 0 ));
}
tp.initial_value(p.label());
@@ -88,7 +92,7 @@ LLColorSwatchCtrl::LLColorSwatchCtrl(const Params& p)
LLRect border_rect = getLocalRect();
border_rect.mTop -= 1;
border_rect.mRight -=1;
- border_rect.mBottom += BTN_HEIGHT_SMALL;
+ border_rect.mBottom += mLabelHeight;
LLViewBorder::Params params = p.border;
params.rect(border_rect);
@@ -191,10 +195,12 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
// assumes GL state is set for 2D
void LLColorSwatchCtrl::draw()
{
- F32 alpha = getDrawContext().mAlpha;
+ // If we're in a focused floater, don't apply the floater's alpha to the color swatch (STORM-676).
+ F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
+
mBorder->setKeyboardFocusHighlight(hasFocus());
// Draw border
- LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL );
+ LLRect border( 0, getRect().getHeight(), getRect().getWidth(), mLabelHeight );
gl_rect_2d( border, mBorderColor.get(), FALSE );
LLRect interior = border;
@@ -203,19 +209,29 @@ void LLColorSwatchCtrl::draw()
// Check state
if ( mValid )
{
+ if (!mColor.isOpaque())
+ {
+ // Draw checker board.
+ gl_rect_2d_checkerboard(interior, alpha);
+ }
+
// Draw the color swatch
- gl_rect_2d_checkerboard( interior );
- gl_rect_2d(interior, mColor, TRUE);
- LLColor4 opaque_color = mColor;
- opaque_color.mV[VALPHA] = 1.f;
- gGL.color4fv(opaque_color.mV);
- if (mAlphaGradientImage.notNull())
+ gl_rect_2d(interior, mColor % alpha, TRUE);
+
+ if (!mColor.isOpaque())
{
- gGL.pushMatrix();
+ // Draw semi-transparent center area in filled with mColor.
+ LLColor4 opaque_color = mColor;
+ opaque_color.mV[VALPHA] = alpha;
+ gGL.color4fv(opaque_color.mV);
+ if (mAlphaGradientImage.notNull())
{
- mAlphaGradientImage->draw(interior, mColor);
+ gGL.pushMatrix();
+ {
+ mAlphaGradientImage->draw(interior, mColor % alpha);
+ }
+ gGL.popMatrix();
}
- gGL.popMatrix();
}
}
else
diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h
index a4ce1ca099..cd859ea128 100644
--- a/indra/newview/llcolorswatch.h
+++ b/indra/newview/llcolorswatch.h
@@ -61,6 +61,7 @@ public:
Optional<commit_callback_t> select_callback;
Optional<LLUIColor> border_color;
Optional<S32> label_width;
+ Optional<S32> label_height;
Optional<LLTextBox::Params> caption_text;
Optional<LLViewBorder::Params> border;
@@ -112,6 +113,7 @@ protected:
commit_callback_t mOnCancelCallback;
commit_callback_t mOnSelectCallback;
S32 mLabelWidth;
+ S32 mLabelHeight;
LLPointer<LLUIImage> mAlphaGradientImage;
std::string mFallbackImageName;
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index ee8646aad0..f31ff14df6 100644
--- a/indra/newview/llcommandlineparser.cpp
+++ b/indra/newview/llcommandlineparser.cpp
@@ -267,7 +267,11 @@ bool LLCommandLineParser::parseAndStoreResults(po::command_line_parser& clp)
{
clp.options(gOptionsDesc);
clp.positional(gPositionalOptions);
- clp.style(po::command_line_style::default_style
+ // SNOW-626: Boost 1.42 erroneously added allow_guessing to the default style
+ // (see http://groups.google.com/group/boost-list/browse_thread/thread/545d7bf98ff9bb16?fwc=2&pli=1)
+ // Remove allow_guessing from the default style, because that is not allowed
+ // when we have options that are a prefix of other options (aka, --help and --helperuri).
+ clp.style((po::command_line_style::default_style & ~po::command_line_style::allow_guessing)
| po::command_line_style::allow_long_disguise);
if(mExtraParser)
{
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 2b92b228b3..b4a1457f47 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -166,7 +166,7 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()
gAgent.getSecureSessionID().asString());
keywordArgs.appendString("language", LLUI::getLanguage());
keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
- keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+ keywordArgs.appendString("viewerChannel", LLVersionInfo::getChannel());
keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
@@ -241,7 +241,7 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
{
keywordArgs.appendString("password", password);
}
- keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+ keywordArgs.appendString("viewerChannel", LLVersionInfo::getChannel());
keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 583bb54160..8106fada11 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -358,6 +358,7 @@ void LLDrawable::makeActive()
{
U32 pcode = mVObjp->getPCode();
if (pcode == LLViewerObject::LL_VO_WATER ||
+ pcode == LLViewerObject::LL_VO_VOID_WATER ||
pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||
pcode == LLViewerObject::LL_VO_PART_GROUP ||
pcode == LLViewerObject::LL_VO_HUD_PART_GROUP ||
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index cb651f9d3a..ba576ff97f 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -89,6 +89,7 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
case POOL_SKY:
poolp = new LLDrawPoolSky();
break;
+ case POOL_VOIDWATER:
case POOL_WATER:
poolp = new LLDrawPoolWater();
break;
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 221f81ec25..1d6f99d346 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -57,6 +57,7 @@ public:
POOL_BUMP,
POOL_INVISIBLE, // see below *
POOL_AVATAR,
+ POOL_VOIDWATER,
POOL_WATER,
POOL_GLOW,
POOL_ALPHA,
@@ -167,7 +168,6 @@ public:
LLFacePool(const U32 type);
virtual ~LLFacePool();
- virtual void renderForSelect() = 0;
BOOL isDead() { return mReferences.empty(); }
virtual LLViewerTexture *getTexture();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 8cf4dc1b95..dbd5da31a6 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -743,79 +743,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
-//-----------------------------------------------------------------------------
-// renderForSelect()
-//-----------------------------------------------------------------------------
-void LLDrawPoolAvatar::renderForSelect()
-{
-
-
- if (mDrawFace.empty())
- {
- return;
- }
-
- const LLFace *facep = mDrawFace[0];
- if (!facep->getDrawable())
- {
- return;
- }
- LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
-
- if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull())
- {
- return;
- }
-
- S32 curr_shader_level = getVertexShaderLevel();
- S32 name = avatarp->mDrawable->getVObj()->mGLName;
- LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name);
-
- BOOL impostor = avatarp->isImpostor();
- if (impostor)
- {
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_COLOR);
- gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
-
- avatarp->renderImpostor(color);
-
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
- return;
- }
-
- sVertexProgram = &gAvatarPickProgram;
- if (curr_shader_level > 0)
- {
- gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
- }
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
-
- glColor4ubv(color.mV);
-
- if (curr_shader_level > 0) // for hardware blending
- {
- sRenderingSkinned = TRUE;
- sVertexProgram->bind();
- enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
- }
-
- avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
-
- // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
- if (curr_shader_level > 0)
- {
- sRenderingSkinned = FALSE;
- sVertexProgram->unbind();
- disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
- }
-
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- // restore texture mode
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-}
//-----------------------------------------------------------------------------
// getDebugTexture()
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index c46fed824e..f536d3c911 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -64,7 +64,6 @@ public:
/*virtual*/ void endRenderPass(S32 pass);
/*virtual*/ void prerender();
/*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderForSelect();
/*virtual*/ S32 getNumDeferredPasses();
/*virtual*/ void beginDeferredPass(S32 pass);
diff --git a/indra/newview/lldrawpoolclouds.cpp b/indra/newview/lldrawpoolclouds.cpp
index f7da144671..5db1d8cfed 100644
--- a/indra/newview/lldrawpoolclouds.cpp
+++ b/indra/newview/lldrawpoolclouds.cpp
@@ -95,6 +95,3 @@ void LLDrawPoolClouds::render(S32 pass)
}
-void LLDrawPoolClouds::renderForSelect()
-{
-}
diff --git a/indra/newview/lldrawpoolclouds.h b/indra/newview/lldrawpoolclouds.h
index 548720ed9c..019f11a795 100644
--- a/indra/newview/lldrawpoolclouds.h
+++ b/indra/newview/lldrawpoolclouds.h
@@ -49,7 +49,6 @@ public:
/*virtual*/ void enqueue(LLFace *face);
/*virtual*/ void beginRenderPass(S32 pass);
/*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderForSelect();
};
#endif // LL_LLDRAWPOOLSKY_H
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index e950fbfa82..ce07e62122 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -68,7 +68,7 @@ void LLDrawPoolGround::render(S32 pass)
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLGLClampToFarClip far_clip(glh_get_current_projection());
+ LLGLSquashToFarClip far_clip(glh_get_current_projection());
F32 water_height = gAgent.getRegion()->getWaterHeight();
glPushMatrix();
@@ -85,7 +85,3 @@ void LLDrawPoolGround::render(S32 pass)
glPopMatrix();
}
-void LLDrawPoolGround::renderForSelect()
-{
-}
-
diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h
index c6c7cbf964..a4f8a3fcf5 100644
--- a/indra/newview/lldrawpoolground.h
+++ b/indra/newview/lldrawpoolground.h
@@ -47,7 +47,6 @@ public:
/*virtual*/ void prerender();
/*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderForSelect();
};
#endif // LL_LLDRAWPOOLGROUND_H
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index d811ab8c54..6b45c5abb0 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -97,7 +97,7 @@ void LLDrawPoolSky::render(S32 pass)
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLGLClampToFarClip far_clip(glh_get_current_projection());
+ LLGLSquashToFarClip far_clip(glh_get_current_projection());
LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
@@ -143,10 +143,6 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side)
}
}
-void LLDrawPoolSky::renderForSelect()
-{
-}
-
void LLDrawPoolSky::endRenderPass( S32 pass )
{
}
diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h
index 15d643c886..098bd2134a 100644
--- a/indra/newview/lldrawpoolsky.h
+++ b/indra/newview/lldrawpoolsky.h
@@ -58,7 +58,6 @@ public:
/*virtual*/ void prerender();
/*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void renderForSelect();
/*virtual*/ void endRenderPass(S32 pass);
void setSkyTex(LLSkyTex* const st) { mSkyTex = st; }
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 3dede9d8fc..84eeace9c6 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -899,27 +899,6 @@ void LLDrawPoolTerrain::renderOwnership()
}
-void LLDrawPoolTerrain::renderForSelect()
-{
- if (mDrawFace.empty())
- {
- return;
- }
-
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *facep = *iter;
- if (!facep->getDrawable()->isDead() && (facep->getDrawable()->getVObj()->mGLName))
- {
- facep->renderForSelect(LLVertexBuffer::MAP_VERTEX);
- }
- }
-}
-
void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures)
{
LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(mTexturep) ;
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 730298609d..3056da44d5 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -66,7 +66,6 @@ public:
/*virtual*/ void prerender();
/*virtual*/ void beginRenderPass( S32 pass );
/*virtual*/ void endRenderPass( S32 pass );
- /*virtual*/ void renderForSelect();
/*virtual*/ void dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures);
/*virtual*/ LLViewerTexture *getTexture();
/*virtual*/ LLViewerTexture *getDebugTexture();
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 09cca8b73c..f1198c9a8d 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -183,68 +183,6 @@ void LLDrawPoolTree::endShadowPass(S32 pass)
}
-void LLDrawPoolTree::renderForSelect()
-{
- if (mDrawFace.empty())
- {
- return;
- }
-
- LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f);
-
- LLGLSObjectSelectAlpha gls_alpha;
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
-
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
- gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
-
- if (gSavedSettings.getBOOL("RenderAnimateTrees"))
- {
- renderTree(TRUE);
- }
- else
- {
- gGL.getTexUnit(sDiffTex)->bind(mTexturep);
-
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
- iter != mDrawFace.end(); iter++)
- {
- LLFace *face = *iter;
- LLDrawable *drawablep = face->getDrawable();
-
- if (drawablep->isDead() || face->mVertexBuffer.isNull())
- {
- continue;
- }
-
- // Render each of the trees
- LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get();
-
- LLColor4U color(255,255,255,255);
-
- if (treep->mGLName != 0)
- {
- S32 name = treep->mGLName;
- color = LLColor4U((U8)(name >> 16), (U8)(name >> 8), (U8)name, 255);
-
- LLFacePool::LLOverrideFaceColor col(this, color);
-
- face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
- face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0);
- gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices());
- }
- }
- }
-
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-}
-
void LLDrawPoolTree::renderTree(BOOL selecting)
{
LLGLState normalize(GL_NORMALIZE, TRUE);
diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h
index cebe41f75f..ddb259bb82 100644
--- a/indra/newview/lldrawpooltree.h
+++ b/indra/newview/lldrawpooltree.h
@@ -62,7 +62,6 @@ public:
/*virtual*/ void render(S32 pass = 0);
/*virtual*/ void endRenderPass( S32 pass );
/*virtual*/ S32 getNumPasses() { return 1; }
- /*virtual*/ void renderForSelect();
/*virtual*/ BOOL verify() const;
/*virtual*/ LLViewerTexture *getTexture();
/*virtual*/ LLViewerTexture *getDebugTexture();
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index ce1b899d55..dc94924da4 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -48,7 +48,8 @@
#include "llviewershadermgr.h"
#include "llwaterparammanager.h"
-const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
+const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004");
+const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055");
static float sTime;
@@ -71,10 +72,14 @@ LLDrawPoolWater::LLDrawPoolWater() :
gGL.getTexUnit(0)->bind(mHBTex[1]);
mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
- mWaterImagep = LLViewerTextureManager::getFetchedTexture(WATER_TEST);
- mWaterImagep->setNoDelete() ;
+
+ mWaterImagep = LLViewerTextureManager::getFetchedTexture(TRANSPARENT_WATER_TEXTURE);
+ llassert(mWaterImagep);
+ mWaterImagep->setNoDelete();
+ mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(OPAQUE_WATER_TEXTURE);
+ llassert(mOpaqueWaterImagep);
mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL);
- mWaterNormp->setNoDelete() ;
+ mWaterNormp->setNoDelete();
restoreGL();
}
@@ -161,6 +166,14 @@ void LLDrawPoolWater::render(S32 pass)
std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
+ // See if we are rendering water as opaque or not
+ if (!gSavedSettings.getBOOL("RenderTransparentWater"))
+ {
+ // render water for low end hardware
+ renderOpaqueLegacyWater();
+ return;
+ }
+
LLGLEnable blend(GL_BLEND);
if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
@@ -314,6 +327,87 @@ void LLDrawPoolWater::render(S32 pass)
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
+// for low end hardware
+void LLDrawPoolWater::renderOpaqueLegacyWater()
+{
+ LLVOSky *voskyp = gSky.mVOSkyp;
+
+ stop_glerror();
+
+ // Depth sorting and write to depth buffer
+ // since this is opaque, we should see nothing
+ // behind the water. No blending because
+ // of no transparency. And no face culling so
+ // that the underside of the water is also opaque.
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
+ LLGLDisable no_cull(GL_CULL_FACE);
+ LLGLDisable no_blend(GL_BLEND);
+
+ gPipeline.disableLights();
+
+ mOpaqueWaterImagep->addTextureStats(1024.f*1024.f);
+
+ // Activate the texture binding and bind one
+ // texture since all images will have the same texture
+ gGL.getTexUnit(0)->activate();
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->bind(mOpaqueWaterImagep);
+
+ // Automatically generate texture coords for water texture
+ glEnable(GL_TEXTURE_GEN_S); //texture unit 0
+ glEnable(GL_TEXTURE_GEN_T); //texture unit 0
+ glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+ // Use the fact that we know all water faces are the same size
+ // to save some computation
+
+ // Slowly move texture coordinates over time so the watter appears
+ // to be moving.
+ F32 movement_period_secs = 50.f;
+
+ F32 offset = fmod(gFrameTimeSeconds, movement_period_secs);
+
+ if (movement_period_secs != 0)
+ {
+ offset /= movement_period_secs;
+ }
+ else
+ {
+ offset = 0;
+ }
+
+ F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset };
+ F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset };
+
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
+
+ glColor3f(1.f, 1.f, 1.f);
+
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *face = *iter;
+ if (voskyp->isReflFace(face))
+ {
+ continue;
+ }
+
+ face->renderIndexed();
+ }
+
+ stop_glerror();
+
+ // Reset the settings back to expected values
+ glDisable(GL_TEXTURE_GEN_S); //texture unit 0
+ glDisable(GL_TEXTURE_GEN_T); //texture unit 0
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+}
+
+
void LLDrawPoolWater::renderReflection(LLFace* face)
{
LLVOSky *voskyp = gSky.mVOSkyp;
@@ -532,6 +626,7 @@ void LLDrawPoolWater::shade()
glColor4fv(water_color.mV);
{
+ LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
LLGLDisable cullface(GL_CULL_FACE);
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
iter != mDrawFace.end(); iter++)
@@ -548,30 +643,19 @@ void LLDrawPoolWater::shade()
sNeedsReflectionUpdate = TRUE;
- if (water->getUseTexture())
+ if (water->getUseTexture() || !water->getIsEdgePatch())
{
sNeedsDistortionUpdate = TRUE;
face->renderIndexed();
}
+ else if (gGLManager.mHasDepthClamp || deferred_render)
+ {
+ face->renderIndexed();
+ }
else
- { //smash background faces to far clip plane
- if (water->getIsEdgePatch())
- {
- if (deferred_render)
- {
- face->renderIndexed();
- }
- else
- {
- LLGLClampToFarClip far_clip(glh_get_current_projection());
- face->renderIndexed();
- }
- }
- else
- {
- sNeedsDistortionUpdate = TRUE;
- face->renderIndexed();
- }
+ {
+ LLGLSquashToFarClip far_clip(glh_get_current_projection());
+ face->renderIndexed();
}
}
}
@@ -601,12 +685,6 @@ void LLDrawPoolWater::shade()
}
-void LLDrawPoolWater::renderForSelect()
-{
- // Can't select water!
- return;
-}
-
LLViewerTexture *LLDrawPoolWater::getDebugTexture()
{
return LLViewerFetchedTexture::sSmokeImagep;
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index 3ab4bc5e2c..99b541ca5a 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -39,6 +39,7 @@ class LLDrawPoolWater: public LLFacePool
protected:
LLPointer<LLViewerTexture> mHBTex[2];
LLPointer<LLViewerTexture> mWaterImagep;
+ LLPointer<LLViewerTexture> mOpaqueWaterImagep;
LLPointer<LLViewerTexture> mWaterNormp;
public:
@@ -74,13 +75,15 @@ public:
/*virtual*/ S32 getNumPasses();
/*virtual*/ void render(S32 pass = 0);
/*virtual*/ void prerender();
- /*virtual*/ void renderForSelect();
/*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
void renderReflection(LLFace* face);
void shade();
+
+protected:
+ void renderOpaqueLegacyWater();
};
void cgErrorCallback();
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 41a299151e..eaa6aa7e37 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -260,7 +260,7 @@ void LLDrawPoolWLSky::render(S32 pass)
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
LLGLDisable clip(GL_CLIP_PLANE0);
- LLGLClampToFarClip far_clip(glh_get_current_projection());
+ LLGLSquashToFarClip far_clip(glh_get_current_projection());
renderSkyHaze(camHeightLocal);
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
new file mode 100644
index 0000000000..54968841ab
--- /dev/null
+++ b/indra/newview/llexternaleditor.cpp
@@ -0,0 +1,192 @@
+/**
+ * @file llexternaleditor.cpp
+ * @brief A convenient class to run external editor.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llexternaleditor.h"
+
+#include "llui.h"
+
+// static
+const std::string LLExternalEditor::sFilenameMarker = "%s";
+
+// static
+const std::string LLExternalEditor::sSetting = "ExternalEditor";
+
+bool LLExternalEditor::setCommand(const std::string& env_var, const std::string& override)
+{
+ std::string cmd = findCommand(env_var, override);
+ if (cmd.empty())
+ {
+ llwarns << "Empty editor command" << llendl;
+ return false;
+ }
+
+ // Add the filename marker if missing.
+ if (cmd.find(sFilenameMarker) == std::string::npos)
+ {
+ cmd += " \"" + sFilenameMarker + "\"";
+ llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
+ }
+
+ string_vec_t tokens;
+ if (tokenize(tokens, cmd) < 2) // 2 = bin + at least one arg (%s)
+ {
+ llwarns << "Error parsing editor command" << llendl;
+ return false;
+ }
+
+ // Check executable for existence.
+ std::string bin_path = tokens[0];
+ if (!LLFile::isfile(bin_path))
+ {
+ llwarns << "Editor binary [" << bin_path << "] not found" << llendl;
+ return false;
+ }
+
+ // Save command.
+ mProcess.setExecutable(bin_path);
+ mArgs.clear();
+ for (size_t i = 1; i < tokens.size(); ++i)
+ {
+ if (i > 1) mArgs += " ";
+ mArgs += "\"" + tokens[i] + "\"";
+ }
+ llinfos << "Setting command [" << bin_path << " " << mArgs << "]" << llendl;
+
+ return true;
+}
+
+bool LLExternalEditor::run(const std::string& file_path)
+{
+ std::string args = mArgs;
+ if (mProcess.getExecutable().empty() || args.empty())
+ {
+ llwarns << "Editor command not set" << llendl;
+ return false;
+ }
+
+ // Substitute the filename marker in the command with the actual passed file name.
+ LLStringUtil::replaceString(args, sFilenameMarker, file_path);
+
+ // Split command into separate tokens.
+ string_vec_t tokens;
+ tokenize(tokens, args);
+
+ // Set process arguments taken from the command.
+ mProcess.clearArguments();
+ for (string_vec_t::const_iterator arg_it = tokens.begin(); arg_it != tokens.end(); ++arg_it)
+ {
+ mProcess.addArgument(*arg_it);
+ }
+
+ // Run the editor.
+ llinfos << "Running editor command [" << mProcess.getExecutable() + " " + args << "]" << llendl;
+ int result = mProcess.launch();
+ if (result == 0)
+ {
+ // Prevent killing the process in destructor (will add it to the zombies list).
+ mProcess.orphan();
+ }
+
+ return result == 0;
+}
+
+// static
+size_t LLExternalEditor::tokenize(string_vec_t& tokens, const std::string& str)
+{
+ tokens.clear();
+
+ // Split the argument string into separate strings for each argument
+ typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("", "\" ", boost::drop_empty_tokens);
+
+ tokenizer tokens_list(str, sep);
+ tokenizer::iterator token_iter;
+ BOOL inside_quotes = FALSE;
+ BOOL last_was_space = FALSE;
+ for (token_iter = tokens_list.begin(); token_iter != tokens_list.end(); ++token_iter)
+ {
+ if (!strncmp("\"",(*token_iter).c_str(),2))
+ {
+ inside_quotes = !inside_quotes;
+ }
+ else if (!strncmp(" ",(*token_iter).c_str(),2))
+ {
+ if(inside_quotes)
+ {
+ tokens.back().append(std::string(" "));
+ last_was_space = TRUE;
+ }
+ }
+ else
+ {
+ std::string to_push = *token_iter;
+ if (last_was_space)
+ {
+ tokens.back().append(to_push);
+ last_was_space = FALSE;
+ }
+ else
+ {
+ tokens.push_back(to_push);
+ }
+ }
+ }
+
+ return tokens.size();
+}
+
+// static
+std::string LLExternalEditor::findCommand(
+ const std::string& env_var,
+ const std::string& override)
+{
+ std::string cmd;
+
+ // Get executable path.
+ if (!override.empty()) // try the supplied override first
+ {
+ cmd = override;
+ llinfos << "Using override" << llendl;
+ }
+ else if (!LLUI::sSettingGroups["config"]->getString(sSetting).empty())
+ {
+ cmd = LLUI::sSettingGroups["config"]->getString(sSetting);
+ llinfos << "Using setting" << llendl;
+ }
+ else // otherwise use the path specified by the environment variable
+ {
+ char* env_var_val = getenv(env_var.c_str());
+ if (env_var_val)
+ {
+ cmd = env_var_val;
+ llinfos << "Using env var " << env_var << llendl;
+ }
+ }
+
+ llinfos << "Found command [" << cmd << "]" << llendl;
+ return cmd;
+}
diff --git a/indra/newview/llexternaleditor.h b/indra/newview/llexternaleditor.h
new file mode 100644
index 0000000000..6ea210d5e2
--- /dev/null
+++ b/indra/newview/llexternaleditor.h
@@ -0,0 +1,91 @@
+/**
+ * @file llexternaleditor.h
+ * @brief A convenient class to run external editor.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLEXTERNALEDITOR_H
+#define LL_LLEXTERNALEDITOR_H
+
+#include <llprocesslauncher.h>
+
+/**
+ * Usage:
+ * LLExternalEditor ed;
+ * ed.setCommand("MY_EXTERNAL_EDITOR_VAR");
+ * ed.run("/path/to/file1");
+ * ed.run("/other/path/to/file2");
+ */
+class LLExternalEditor
+{
+ typedef std::vector<std::string> string_vec_t;
+
+public:
+
+ /**
+ * Set editor command.
+ *
+ * @param env_var Environment variable of the same purpose.
+ * @param override Optional override.
+ *
+ * First tries the override, then a predefined setting (sSetting),
+ * then the environment variable.
+ *
+ * @return Command if found, empty string otherwise.
+ *
+ * @see sSetting
+ */
+ bool setCommand(const std::string& env_var, const std::string& override = LLStringUtil::null);
+
+ /**
+ * Run the editor with the given file.
+ *
+ * @param file_path File to edit.
+ * @return true on success, false on error.
+ */
+ bool run(const std::string& file_path);
+
+private:
+
+ static std::string findCommand(
+ const std::string& env_var,
+ const std::string& override);
+
+ static size_t tokenize(string_vec_t& tokens, const std::string& str);
+
+ /**
+ * Filename placeholder that gets replaced with an actual file name.
+ */
+ static const std::string sFilenameMarker;
+
+ /**
+ * Setting that can specify the editor command.
+ */
+ static const std::string sSetting;
+
+
+ std::string mArgs;
+ LLProcessLauncher mProcess;
+};
+
+#endif // LL_LLEXTERNALEDITOR_H
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index d22950cad3..2471da9da5 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -399,84 +399,6 @@ void LLFace::updateCenterAgent()
}
}
-void LLFace::renderForSelect(U32 data_mask)
-{
- if(mDrawablep.isNull() || mVertexBuffer.isNull())
- {
- return;
- }
-
- LLSpatialGroup* group = mDrawablep->getSpatialGroup();
- if (!group || group->isState(LLSpatialGroup::GEOM_DIRTY))
- {
- return;
- }
-
- if (mVObjp->mGLName)
- {
- S32 name = mVObjp->mGLName;
-
- LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name);
-#if 0 // *FIX: Postponing this fix until we have texcoord pick info...
- if (mTEOffset != -1)
- {
- color.mV[VALPHA] = (U8)(getTextureEntry()->getColor().mV[VALPHA] * 255.f);
- }
-#endif
- glColor4ubv(color.mV);
-
- if (!getPool())
- {
- switch (getPoolType())
- {
- case LLDrawPool::POOL_ALPHA:
- gGL.getTexUnit(0)->bind(getTexture());
- break;
- default:
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- break;
- }
- }
-
- mVertexBuffer->setBuffer(data_mask);
-#if !LL_RELEASE_FOR_DOWNLOAD
- LLGLState::checkClientArrays("", data_mask);
-#endif
- if (mTEOffset != -1)
- {
- // mask off high 4 bits (16 total possible faces)
- color.mV[0] &= 0x0f;
- color.mV[0] |= (mTEOffset & 0x0f) << 4;
- glColor4ubv(color.mV);
- }
-
- if (mIndicesCount)
- {
- if (isState(GLOBAL))
- {
- if (mDrawablep->getVOVolume())
- {
- glPushMatrix();
- glMultMatrixf((float*) mDrawablep->getRegion()->mRenderMatrix.mMatrix);
- mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
- glPopMatrix();
- }
- else
- {
- mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
- }
- }
- else
- {
- glPushMatrix();
- glMultMatrixf((float*)getRenderMatrix().mMatrix);
- mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
- glPopMatrix();
- }
- }
- }
-}
-
void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
{
if (mDrawablep->getSpatialGroup() == NULL)
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 0166e45bee..6c941bd092 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -173,7 +173,6 @@ public:
void updateCenterAgent(); // Update center when xform has changed.
void renderSelectedUV();
- void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
void renderSelected(LLViewerTexture *image, const LLColor4 &color);
F32 getKey() const { return mDistance; }
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index a09c0ea0f8..92a3b9b2f5 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -1086,14 +1086,22 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
//static
void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target, std::string output)
{
+ // Open baseline and current target, exit if one is inexistent
+ std::ifstream base_is(baseline.c_str());
+ std::ifstream target_is(target.c_str());
+ if (!base_is.is_open() || !target_is.is_open())
+ {
+ llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
+ base_is.close();
+ target_is.close();
+ return;
+ }
//analyze baseline
- std::ifstream base_is(baseline.c_str());
LLSD base = analyzePerformanceLogDefault(base_is);
base_is.close();
//analyze current
- std::ifstream target_is(target.c_str());
LLSD current = analyzePerformanceLogDefault(target_is);
target_is.close();
@@ -1154,15 +1162,15 @@ LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
{
std::string label = iter->first;
- LLMetricPerformanceTester* tester = LLMetricPerformanceTester::getTester(iter->second["Name"].asString()) ;
+ LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
if(tester)
{
ret[label]["Name"] = iter->second["Name"] ;
- S32 num_of_strings = tester->getNumOfMetricStrings() ;
- for(S32 index = 0 ; index < num_of_strings ; index++)
+ S32 num_of_metrics = tester->getNumberOfMetrics() ;
+ for(S32 index = 0 ; index < num_of_metrics ; index++)
{
- ret[label][ tester->getMetricString(index) ] = iter->second[ tester->getMetricString(index) ] ;
+ ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
}
}
}
@@ -1172,20 +1180,43 @@ LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
}
//static
+void LLFastTimerView::outputAllMetrics()
+{
+ if (LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
+ {
+ for (LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin();
+ iter != LLMetricPerformanceTesterBasic::sTesterMap.end(); ++iter)
+ {
+ LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second);
+ tester->outputTestResults();
+ }
+ }
+}
+
+//static
void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
{
- if(!LLMetricPerformanceTester::hasMetricPerformanceTesters())
+ if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
{
return ;
}
- //analyze baseline
+ // Open baseline and current target, exit if one is inexistent
std::ifstream base_is(baseline.c_str());
+ std::ifstream target_is(target.c_str());
+ if (!base_is.is_open() || !target_is.is_open())
+ {
+ llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
+ base_is.close();
+ target_is.close();
+ return;
+ }
+
+ //analyze baseline
LLSD base = analyzeMetricPerformanceLog(base_is);
base_is.close();
//analyze current
- std::ifstream target_is(target.c_str());
LLSD current = analyzeMetricPerformanceLog(target_is);
target_is.close();
@@ -1193,10 +1224,10 @@ void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target
std::ofstream os(output.c_str());
os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
- for(LLMetricPerformanceTester::name_tester_map_t::iterator iter = LLMetricPerformanceTester::sTesterMap.begin() ;
- iter != LLMetricPerformanceTester::sTesterMap.end() ; ++iter)
+ for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ;
+ iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter)
{
- LLMetricPerformanceTester* tester = ((LLMetricPerformanceTester*)iter->second) ;
+ LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ;
tester->analyzePerformance(&os, &base, &current) ;
}
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index 3788897cec..1a54a53f09 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -37,6 +37,7 @@ public:
static BOOL sAnalyzePerformance;
+ static void outputAllMetrics();
static void doAnalysis(std::string baseline, std::string target, std::string output);
private:
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 3981b887ad..a1ba370c26 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -414,6 +414,9 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
{
*accept = ACCEPT_NO;
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ if (LLToolDragAndDrop::SOURCE_AGENT != source && LLToolDragAndDrop::SOURCE_LIBRARY != source) return FALSE;
+
switch (cargo_type)
{
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 135137069c..8ae3ccbae3 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -213,7 +213,7 @@ LLSD LLFloaterAbout::getInfo()
info["VIEWER_VERSION_STR"] = LLVersionInfo::getVersion();
info["BUILD_DATE"] = __DATE__;
info["BUILD_TIME"] = __TIME__;
- info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
+ info["CHANNEL"] = LLVersionInfo::getChannel();
info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
@@ -291,7 +291,7 @@ static std::string get_viewer_release_notes_url()
std::string url = LLTrans::getString("RELEASE_NOTES_BASE_URL");
if (! LLStringUtil::endsWith(url, "/"))
url += "/";
- url += gSavedSettings.getString("VersionChannelName") + "/";
+ url += LLVersionInfo::getChannel() + "/";
url += LLVersionInfo::getShortVersion();
return LLWeb::escapeURL(url);
}
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index ad24c6534a..90a9879949 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -343,6 +343,7 @@ BOOL LLFloaterCamera::postBuild()
{
setIsChrome(TRUE);
setTitleVisible(TRUE); // restore title visibility after chrome applying
+ updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
mRotate = getChild<LLJoystickCameraRotate>(ORBIT);
mZoom = findChild<LLPanelCameraZoom>(ZOOM);
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 69f1774ff8..659e52271a 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -472,6 +472,12 @@ void LLFloaterColorPicker::onMouseCaptureLost()
setMouseDownInLumRegion(FALSE);
}
+F32 LLFloaterColorPicker::getSwatchTransparency()
+{
+ // If the floater is focused, don't apply its alpha to the color swatch (STORM-676).
+ return getTransparencyType() == TT_ACTIVE ? 1.f : LLFloater::getCurrentTransparency();
+}
+
//////////////////////////////////////////////////////////////////////////////
//
void LLFloaterColorPicker::draw()
@@ -533,8 +539,10 @@ void LLFloaterColorPicker::draw()
// base floater stuff
LLFloater::draw ();
+ const F32 alpha = getSwatchTransparency();
+
// draw image for RGB area (not really RGB but you'll see what I mean...
- gl_draw_image ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBImage, LLColor4::white );
+ gl_draw_image ( mRGBViewerImageLeft, mRGBViewerImageTop - mRGBViewerImageHeight, mRGBImage, LLColor4::white % alpha);
// update 'cursor' into RGB Section
S32 xPos = ( S32 ) ( ( F32 )mRGBViewerImageWidth * getCurH () ) - 8;
@@ -556,7 +564,7 @@ void LLFloaterColorPicker::draw()
mRGBViewerImageTop - mRGBViewerImageHeight,
mRGBViewerImageLeft + mRGBViewerImageWidth + 1,
mRGBViewerImageTop,
- LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ),
+ LLColor4 ( 0.0f, 0.0f, 0.0f, alpha ),
FALSE );
// draw luminance slider
@@ -569,7 +577,7 @@ void LLFloaterColorPicker::draw()
mLumRegionTop - mLumRegionHeight + y,
mLumRegionLeft + mLumRegionWidth,
mLumRegionTop - mLumRegionHeight + y - 1,
- LLColor4 ( rValSlider, gValSlider, bValSlider, 1.0f ) );
+ LLColor4 ( rValSlider, gValSlider, bValSlider, alpha ) );
}
@@ -594,7 +602,7 @@ void LLFloaterColorPicker::draw()
mSwatchRegionTop - mSwatchRegionHeight,
mSwatchRegionLeft + mSwatchRegionWidth,
mSwatchRegionTop,
- LLColor4 ( getCurR (), getCurG (), getCurB (), 1.0f ),
+ LLColor4 ( getCurR (), getCurG (), getCurB (), alpha ),
TRUE );
// draw selected color swatch outline
@@ -634,6 +642,7 @@ const LLColor4& LLFloaterColorPicker::getComplimentaryColor ( const LLColor4& ba
void LLFloaterColorPicker::drawPalette ()
{
S32 curEntry = 0;
+ const F32 alpha = getSwatchTransparency();
for ( S32 y = 0; y < numPaletteRows; ++y )
{
@@ -648,7 +657,7 @@ void LLFloaterColorPicker::drawPalette ()
// draw palette entry color
if ( mPalette [ curEntry ] )
{
- gl_rect_2d ( x1 + 2, y1 - 2, x2 - 2, y2 + 2, *mPalette [ curEntry++ ], TRUE );
+ gl_rect_2d ( x1 + 2, y1 - 2, x2 - 2, y2 + 2, *mPalette [ curEntry++ ] % alpha, TRUE );
gl_rect_2d ( x1 + 1, y1 - 1, x2 - 1, y2 + 1, LLColor4 ( 0.0f, 0.0f, 0.0f, 1.0f ), FALSE );
}
}
diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h
index 110fa43b9c..8e387c4f7c 100644
--- a/indra/newview/llfloatercolorpicker.h
+++ b/indra/newview/llfloatercolorpicker.h
@@ -55,6 +55,7 @@ class LLFloaterColorPicker
virtual BOOL handleMouseUp ( S32 x, S32 y, MASK mask );
virtual BOOL handleHover ( S32 x, S32 y, MASK mask );
virtual void onMouseCaptureLost();
+ virtual F32 getSwatchTransparency();
// implicit methods
void createUI ();
diff --git a/indra/newview/llfloaterevent.cpp b/indra/newview/llfloaterevent.cpp
index 0b5ac8e798..a6dafda3e6 100644
--- a/indra/newview/llfloaterevent.cpp
+++ b/indra/newview/llfloaterevent.cpp
@@ -117,8 +117,3 @@ void LLFloaterEvent::setEventID(const U32 event_id)
}
}
-
-void LLFloaterEvent::draw()
-{
- LLPanel::draw();
-}
diff --git a/indra/newview/llfloaterevent.h b/indra/newview/llfloaterevent.h
index b1963309da..ed90055d95 100644
--- a/indra/newview/llfloaterevent.h
+++ b/indra/newview/llfloaterevent.h
@@ -43,7 +43,6 @@ public:
/*virtual*/ ~LLFloaterEvent();
/*virtual*/ BOOL postBuild();
- /*virtual*/ void draw();
void setEventID(const U32 event_id);
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index 662e1c4f42..a34e0353ec 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -209,13 +209,6 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
llassert(msg);
if (!msg) return;
- LLHost host = msg->getSender();
- if (host != gAgent.getRegionHost())
- {
- // update is for a different region than the one we're in
- return;
- }
-
//const S32 SIM_NAME_BUF = 256;
U32 region_flags;
U8 sim_access;
@@ -233,6 +226,8 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
S32 redirect_grid_y;
LLUUID cache_id;
+ LLHost host = msg->getSender();
+
msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name);
msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, estate_id);
msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, parent_estate_id);
@@ -242,6 +237,15 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, object_bonus_factor);
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor);
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height);
+
+ if (host != gAgent.getRegionHost())
+ {
+ // Update is for a different region than the one we're in.
+ // Just check for a waterheight change.
+ LLWorld::getInstance()->waterHeightRegionInfo(sim_name, water_height);
+ return;
+ }
+
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit);
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit);
msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter, price_per_meter);
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index 234a09d157..d84364a68a 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -41,6 +41,7 @@
#include "llbutton.h"
#include "llgroupactions.h"
#include "llscrolllistctrl.h"
+#include "llstartup.h"
#include "lltextbox.h"
#include "lluictrlfactory.h"
#include "lltrans.h"
@@ -171,7 +172,7 @@ void LLPanelGroups::reset()
group_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count()));
- getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",MAX_AGENT_GROUPS));
+ getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",gMaxAgentGroups));
init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID());
enableButtons();
@@ -182,7 +183,7 @@ BOOL LLPanelGroups::postBuild()
childSetCommitCallback("group list", onGroupList, this);
getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count()));
- getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",MAX_AGENT_GROUPS));
+ getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",gMaxAgentGroups));
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("group list");
if (list)
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index a1d291fea6..351b9ac5da 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -43,6 +43,8 @@
#include "lldraghandle.h"
#include "lltextbox.h"
#include "llviewermenu.h"
+#include "llfloaterworldmap.h"
+#include "llagent.h"
//
// Constants
@@ -122,11 +124,36 @@ BOOL LLFloaterMap::postBuild()
return TRUE;
}
-BOOL LLFloaterMap::handleDoubleClick( S32 x, S32 y, MASK mask )
+BOOL LLFloaterMap::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// If floater is minimized, minimap should be shown on doubleclick (STORM-299)
- std::string floater_to_show = this->isMinimized() ? "mini_map" : "world_map";
- LLFloaterReg::showInstance(floater_to_show);
+ if (isMinimized())
+ {
+ setMinimized(FALSE);
+ return TRUE;
+ }
+
+ LLVector3d pos_global = mMap->viewPosToGlobal(x, y);
+
+ // If we're not tracking a beacon already, double-click will set one
+ if (!LLTracker::isTracking(NULL))
+ {
+ LLFloaterWorldMap* world_map = LLFloaterWorldMap::getInstance();
+ if (world_map)
+ {
+ world_map->trackLocation(pos_global);
+ }
+ }
+
+ if (gSavedSettings.getBOOL("DoubleClickTeleport"))
+ {
+ // If DoubleClickTeleport is on, double clicking the minimap will teleport there
+ gAgent.teleportViaLocationLookAt(pos_global);
+ }
+ else
+ {
+ LLFloaterReg::showInstance("world_map");
+ }
return TRUE;
}
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index e8e9f76912..f0c9d52ccd 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -128,6 +128,8 @@ void LLFloaterPostcard::draw()
if(!isMinimized() && mViewerImage.notNull() && mJPEGImage.notNull())
{
+ // Force the texture to be 100% opaque when the floater is focused.
+ F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
LLRect rect(getRect());
// first set the max extents of our preview
@@ -149,7 +151,7 @@ void LLFloaterPostcard::draw()
}
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
+ gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f) % alpha);
rect.stretch(-1);
}
{
@@ -164,7 +166,7 @@ void LLFloaterPostcard::draw()
rect.getWidth(),
rect.getHeight(),
mViewerImage.get(),
- LLColor4::white);
+ LLColor4::white % alpha);
}
glMatrixMode(GL_TEXTURE);
glPopMatrix();
@@ -361,9 +363,7 @@ void LLFloaterPostcard::sendPostcard()
{
gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE);
}
-
- // give user feedback of the event
- gViewerWindow->playSnapshotAnimAndSound();
+
LLUploadDialog::modalUploadDialog(getString("upload_message"));
// don't destroy the window until the upload is done
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 2bea3d37ff..6a7b5171b5 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -282,7 +282,9 @@ std::string LLFloaterPreference::sSkin = "";
LLFloaterPreference::LLFloaterPreference(const LLSD& key)
: LLFloater(key),
mGotPersonalInfo(false),
- mOriginalIMViaEmail(false)
+ mOriginalIMViaEmail(false),
+ mLanguageChanged(false),
+ mDoubleClickActionDirty(false)
{
//Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
@@ -320,6 +322,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
mCommitCallbackRegistrar.add("Pref.MaturitySettings", boost::bind(&LLFloaterPreference::onChangeMaturity, this));
mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this));
+ mCommitCallbackRegistrar.add("Pref.CommitDoubleClickChekbox", boost::bind(&LLFloaterPreference::onDoubleClickCheckBox, this, _1));
+ mCommitCallbackRegistrar.add("Pref.CommitRadioDoubleClick", boost::bind(&LLFloaterPreference::onDoubleClickRadio, this));
sSkin = gSavedSettings.getString("SkinCurrent");
@@ -342,10 +346,14 @@ BOOL LLFloaterPreference::postBuild()
if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
tabcontainer->selectFirstTab();
+ updateDoubleClickControls();
+
getChild<LLUICtrl>("cache_location")->setEnabled(FALSE); // make it read-only but selectable (STORM-227)
std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
setCacheLocation(cache_location);
+ getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this));
+
// if floater is opened before login set default localized busy message
if (LLStartUp::getStartupState() < STATE_STARTED)
{
@@ -475,6 +483,12 @@ void LLFloaterPreference::apply()
gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);
}
}
+
+ if (mDoubleClickActionDirty)
+ {
+ updateDoubleClickSettings();
+ mDoubleClickActionDirty = false;
+ }
}
void LLFloaterPreference::cancel()
@@ -501,6 +515,12 @@ void LLFloaterPreference::cancel()
// reverts any changes to current skin
gSavedSettings.setString("SkinCurrent", sSkin);
+
+ if (mDoubleClickActionDirty)
+ {
+ updateDoubleClickControls();
+ mDoubleClickActionDirty = false;
+ }
}
void LLFloaterPreference::onOpen(const LLSD& key)
@@ -553,6 +573,9 @@ void LLFloaterPreference::onOpen(const LLSD& key)
getChildView("maturity_desired_combobox")->setVisible( false);
}
+ // Forget previous language changes.
+ mLanguageChanged = false;
+
// Display selected maturity icons.
onChangeMaturity();
@@ -710,6 +733,18 @@ void LLFloaterPreference::onClickBrowserClearCache()
LLNotificationsUtil::add("ConfirmClearBrowserCache", LLSD(), LLSD(), callback_clear_browser_cache);
}
+// Called when user changes language via the combobox.
+void LLFloaterPreference::onLanguageChange()
+{
+ // Let the user know that the change will only take effect after restart.
+ // Do it only once so that we're not too irritating.
+ if (!mLanguageChanged)
+ {
+ LLNotificationsUtil::add("ChangeLanguage");
+ mLanguageChanged = true;
+ }
+}
+
void LLFloaterPreference::onClickSetCache()
{
std::string cur_name(gSavedSettings.getString("CacheLocation"));
@@ -803,7 +838,7 @@ void LLFloaterPreference::buildPopupLists()
LLScrollListItem* item = NULL;
- bool show_popup = formp->getIgnored();
+ bool show_popup = !formp->getIgnored();
if (!show_popup)
{
if (ignore == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
@@ -1155,7 +1190,7 @@ void LLFloaterPreference::onClickDisablePopup()
for (itor = items.begin(); itor != items.end(); ++itor)
{
LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate(*(std::string*)((*itor)->getUserdata()));
- templatep->mForm->setIgnored(false);
+ templatep->mForm->setIgnored(true);
}
buildPopupLists();
@@ -1169,7 +1204,7 @@ void LLFloaterPreference::resetAllIgnored()
{
if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- iter->second->mForm->setIgnored(true);
+ iter->second->mForm->setIgnored(false);
}
}
}
@@ -1182,7 +1217,7 @@ void LLFloaterPreference::setAllIgnored()
{
if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- iter->second->mForm->setIgnored(false);
+ iter->second->mForm->setIgnored(true);
}
}
}
@@ -1246,7 +1281,7 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
getChildView("show_timestamps_check_im")->setEnabled(TRUE);
getChildView("log_path_string")->setEnabled(FALSE);// LineEditor becomes readonly in this case.
getChildView("log_path_button")->setEnabled(TRUE);
-
+ childEnable("logfile_name_datestamp");
std::string display_email(email);
getChild<LLUICtrl>("email_address")->setValue(display_email);
@@ -1318,6 +1353,68 @@ void LLFloaterPreference::onClickBlockList()
}
}
+void LLFloaterPreference::onDoubleClickCheckBox(LLUICtrl* ctrl)
+{
+ if (!ctrl) return;
+ mDoubleClickActionDirty = true;
+ LLRadioGroup* radio_double_click_action = getChild<LLRadioGroup>("double_click_action");
+ if (!radio_double_click_action) return;
+ // select default value("teleport") in radio-group.
+ radio_double_click_action->setSelectedIndex(0);
+ // set radio-group enabled depending on state of checkbox
+ radio_double_click_action->setEnabled(ctrl->getValue());
+}
+
+void LLFloaterPreference::onDoubleClickRadio()
+{
+ mDoubleClickActionDirty = true;
+}
+
+void LLFloaterPreference::updateDoubleClickSettings()
+{
+ LLCheckBoxCtrl* double_click_action_cb = getChild<LLCheckBoxCtrl>("double_click_chkbox");
+ if (!double_click_action_cb) return;
+ bool enable = double_click_action_cb->getValue().asBoolean();
+
+ LLRadioGroup* radio_double_click_action = getChild<LLRadioGroup>("double_click_action");
+ if (!radio_double_click_action) return;
+
+ // enable double click radio-group depending on state of checkbox
+ radio_double_click_action->setEnabled(enable);
+
+ if (!enable)
+ {
+ // set double click action settings values to false if checkbox was unchecked
+ gSavedSettings.setBOOL("DoubleClickAutoPilot", false);
+ gSavedSettings.setBOOL("DoubleClickTeleport", false);
+ }
+ else
+ {
+ std::string selected = radio_double_click_action->getValue().asString();
+ bool teleport_selected = selected == "radio_teleport";
+ // set double click action settings values depending on chosen radio-button
+ gSavedSettings.setBOOL( "DoubleClickTeleport", teleport_selected );
+ gSavedSettings.setBOOL( "DoubleClickAutoPilot", !teleport_selected );
+ }
+}
+
+void LLFloaterPreference::updateDoubleClickControls()
+{
+ // check is one of double-click actions settings enabled
+ bool double_click_action_enabled = gSavedSettings.getBOOL("DoubleClickAutoPilot") || gSavedSettings.getBOOL("DoubleClickTeleport");
+ LLCheckBoxCtrl* double_click_action_cb = getChild<LLCheckBoxCtrl>("double_click_chkbox");
+ if (double_click_action_cb)
+ {
+ // check checkbox if one of double-click actions settings enabled, uncheck otherwise
+ double_click_action_cb->setValue(double_click_action_enabled);
+ }
+ LLRadioGroup* double_click_action_radio = getChild<LLRadioGroup>("double_click_action");
+ if (!double_click_action_radio) return;
+ // set radio-group enabled if one of double-click actions settings enabled
+ double_click_action_radio->setEnabled(double_click_action_enabled);
+ // select button in radio-group depending on setting
+ double_click_action_radio->setSelectedIndex(gSavedSettings.getBOOL("DoubleClickAutoPilot"));
+}
void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
{
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index e99731b92e..bb871e7e25 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -83,6 +83,7 @@ protected:
void onBtnApply();
void onClickBrowserClearCache();
+ void onLanguageChange();
// set value of "BusyResponseChanged" in account settings depending on whether busy response
// string differs from default after user changes.
@@ -95,6 +96,14 @@ protected:
void setHardwareDefaults();
// callback for when client turns on shaders
void onVertexShaderEnable();
+ // callback for changing double click action checkbox
+ void onDoubleClickCheckBox(LLUICtrl* ctrl);
+ // callback for selecting double click action radio-button
+ void onDoubleClickRadio();
+ // updates double-click action settings depending on controls from preferences
+ void updateDoubleClickSettings();
+ // updates double-click action controls depending on values from settings.xml
+ void updateDoubleClickControls();
// This function squirrels away the current values of the controls so that
// cancel() can restore them.
@@ -145,8 +154,12 @@ public:
static void refreshSkin(void* data);
private:
static std::string sSkin;
+ // set true if state of double-click action checkbox or radio-group was changed by user
+ // (reset back to false on apply or cancel)
+ bool mDoubleClickActionDirty;
bool mGotPersonalInfo;
bool mOriginalIMViaEmail;
+ bool mLanguageChanged;
bool mOriginalHideOnlineStatus;
std::string mDirectoryVisibility;
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
new file mode 100644
index 0000000000..b3b7645dd4
--- /dev/null
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -0,0 +1,227 @@
+/**
+ * @file llfloaterregiondebugconsole.h
+ * @author Brad Kittenbrink <brad@lindenlab.com>
+ * @brief Quick and dirty console for region debug settings
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010-2010, 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 "llfloaterregiondebugconsole.h"
+
+#include "llagent.h"
+#include "llhttpclient.h"
+#include "llhttpnode.h"
+#include "lllineeditor.h"
+#include "lltexteditor.h"
+#include "llviewerregion.h"
+
+// Two versions of the sim console API are supported.
+//
+// SimConsole capability (deprecated):
+// This is the initial implementation that is supported by some versions of the
+// simulator. It is simple and straight forward, just POST a command and the
+// body of the response has the result. This API is deprecated because it
+// doesn't allow the sim to use any asynchronous API.
+//
+// SimConsoleAsync capability:
+// This capability replaces the original SimConsole capability. It is similar
+// in that the command is POSTed to the SimConsoleAsync cap, but the response
+// comes in through the event poll, which gives the simulator more flexibility
+// and allows it to perform complex operations without blocking any frames.
+//
+// We will assume the SimConsoleAsync capability is available, and fall back to
+// the SimConsole cap if it is not. The simulator will only support one or the
+// other.
+
+namespace
+{
+ // Signal used to notify the floater of responses from the asynchronous
+ // API.
+ typedef boost::signals2::signal<
+ void (const std::string& output)> console_reply_signal_t;
+ console_reply_signal_t sConsoleReplySignal;
+
+ const std::string PROMPT("\n\n> ");
+ const std::string UNABLE_TO_SEND_COMMAND(
+ "ERROR: The last command was not received by the server.");
+ const std::string CONSOLE_UNAVAILABLE(
+ "ERROR: No console available for this region/simulator.");
+ const std::string CONSOLE_NOT_SUPPORTED(
+ "This region does not support the simulator console.");
+
+ // This responder handles the initial response. Unless error() is called
+ // we assume that the simulator has received our request. Error will be
+ // called if this request times out.
+ class AsyncConsoleResponder : public LLHTTPClient::Responder
+ {
+ public:
+ /* virtual */
+ void error(U32 status, const std::string& reason)
+ {
+ sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
+ }
+ };
+
+ class ConsoleResponder : public LLHTTPClient::Responder
+ {
+ public:
+ ConsoleResponder(LLTextEditor *output) : mOutput(output)
+ {
+ }
+
+ /*virtual*/
+ void error(U32 status, const std::string& reason)
+ {
+ if (mOutput)
+ {
+ mOutput->appendText(
+ UNABLE_TO_SEND_COMMAND + PROMPT,
+ false);
+ }
+ }
+
+ /*virtual*/
+ void result(const LLSD& content)
+ {
+ if (mOutput)
+ {
+ mOutput->appendText(
+ content.asString() + PROMPT, false);
+ }
+ }
+
+ LLTextEditor * mOutput;
+ };
+
+ // This handles responses for console commands sent via the asynchronous
+ // API.
+ class ConsoleResponseNode : public LLHTTPNode
+ {
+ public:
+ /* virtual */
+ void post(
+ LLHTTPNode::ResponsePtr reponse,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ llinfos << "Received response from the debug console: "
+ << input << llendl;
+ sConsoleReplySignal(input["body"].asString());
+ }
+ };
+}
+
+LLFloaterRegionDebugConsole::LLFloaterRegionDebugConsole(LLSD const & key)
+: LLFloater(key), mOutput(NULL)
+{
+ mReplySignalConnection = sConsoleReplySignal.connect(
+ boost::bind(
+ &LLFloaterRegionDebugConsole::onReplyReceived,
+ this,
+ _1));
+}
+
+LLFloaterRegionDebugConsole::~LLFloaterRegionDebugConsole()
+{
+ mReplySignalConnection.disconnect();
+}
+
+BOOL LLFloaterRegionDebugConsole::postBuild()
+{
+ LLLineEditor* input = getChild<LLLineEditor>("region_debug_console_input");
+ input->setEnableLineHistory(true);
+ input->setCommitCallback(boost::bind(&LLFloaterRegionDebugConsole::onInput, this, _1, _2));
+ input->setFocus(true);
+ input->setCommitOnFocusLost(false);
+
+ mOutput = getChild<LLTextEditor>("region_debug_console_output");
+
+ std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
+ if (url.empty())
+ {
+ // Fall back to see if the old API is supported.
+ url = gAgent.getRegion()->getCapability("SimConsole");
+ if (url.empty())
+ {
+ mOutput->appendText(
+ CONSOLE_NOT_SUPPORTED + PROMPT,
+ false);
+ return TRUE;
+ }
+ }
+
+ mOutput->appendText("> ", false);
+ return TRUE;
+}
+
+void LLFloaterRegionDebugConsole::onInput(LLUICtrl* ctrl, const LLSD& param)
+{
+ LLLineEditor* input = static_cast<LLLineEditor*>(ctrl);
+ std::string text = input->getText() + "\n";
+
+ std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
+ if (url.empty())
+ {
+ // Fall back to the old API
+ url = gAgent.getRegion()->getCapability("SimConsole");
+ if (url.empty())
+ {
+ text += CONSOLE_UNAVAILABLE + PROMPT;
+ }
+ else
+ {
+ // Using SimConsole (deprecated)
+ LLHTTPClient::post(
+ url,
+ LLSD(input->getText()),
+ new ConsoleResponder(mOutput));
+ }
+ }
+ else
+ {
+ // Using SimConsoleAsync
+ LLHTTPClient::post(
+ url,
+ LLSD(input->getText()),
+ new AsyncConsoleResponder);
+ }
+
+ mOutput->appendText(text, false);
+ input->clear();
+}
+
+void LLFloaterRegionDebugConsole::onReplyReceived(const std::string& output)
+{
+ mOutput->appendText(output + PROMPT, false);
+}
+
+LLHTTPRegistration<ConsoleResponseNode>
+ gHTTPRegistrationMessageDebugConsoleResponse(
+ "/message/SimConsoleResponse");
diff --git a/indra/newview/llfloaterregiondebugconsole.h b/indra/newview/llfloaterregiondebugconsole.h
new file mode 100644
index 0000000000..4171a4da6b
--- /dev/null
+++ b/indra/newview/llfloaterregiondebugconsole.h
@@ -0,0 +1,63 @@
+/**
+ * @file llfloaterregiondebugconsole.h
+ * @author Brad Kittenbrink <brad@lindenlab.com>
+ * @brief Quick and dirty console for region debug settings
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2010-2010, 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_LLFLOATERREGIONDEBUGCONSOLE_H
+#define LL_LLFLOATERREGIONDEBUGCONSOLE_H
+
+#include <boost/signals2.hpp>
+
+#include "llfloater.h"
+#include "llhttpclient.h"
+
+class LLTextEditor;
+
+class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Responder
+{
+public:
+ LLFloaterRegionDebugConsole(LLSD const & key);
+ virtual ~LLFloaterRegionDebugConsole();
+
+ // virtual
+ BOOL postBuild();
+
+ void onInput(LLUICtrl* ctrl, const LLSD& param);
+
+ LLTextEditor * mOutput;
+
+ private:
+ void onReplyReceived(const std::string& output);
+
+ boost::signals2::connection mReplySignalConnection;
+};
+
+#endif // LL_LLFLOATERREGIONDEBUGCONSOLE_H
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 36e8ad9dfc..1aba5ef92f 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -908,6 +908,8 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
}
+
+ gViewerWindow->playSnapshotAnimAndSound();
}
previewp->getWindow()->decBusyCount();
// only show fullscreen preview when in freeze frame mode
@@ -1004,7 +1006,6 @@ void LLSnapshotLivePreview::saveTexture()
LLFloaterPerms::getEveryonePerms(),
"Snapshot : " + pos_string,
callback, expected_upload_cost, userdata);
- gViewerWindow->playSnapshotAnimAndSound();
}
else
{
@@ -1026,10 +1027,6 @@ BOOL LLSnapshotLivePreview::saveLocal()
mDataSize = 0;
updateSnapshot(FALSE, FALSE);
- if(success)
- {
- gViewerWindow->playSnapshotAnimAndSound();
- }
return success;
}
@@ -1049,8 +1046,6 @@ void LLSnapshotLivePreview::saveWeb()
LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(),
boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, jpg, metadata, _1, _2, _3, _4));
-
- gViewerWindow->playSnapshotAnimAndSound();
}
void LLSnapshotLivePreview::regionNameCallback(LLImageJPEG* snapshot, LLSD& metadata, const std::string& name, S32 x, S32 y, S32 z)
@@ -1212,8 +1207,6 @@ LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSna
type = LLViewerWindow::SNAPSHOT_TYPE_COLOR;
else if (id == "depth")
type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH;
- else if (id == "objects")
- type = LLViewerWindow::SNAPSHOT_TYPE_OBJECT_ID;
return type;
}
@@ -2191,9 +2184,11 @@ void LLFloaterSnapshot::draw()
S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ;
glMatrixMode(GL_MODELVIEW);
+ // Apply floater transparency to the texture unless the floater is focused.
+ F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
gl_draw_scaled_image(offset_x, offset_y,
previewp->getThumbnailWidth(), previewp->getThumbnailHeight(),
- previewp->getThumbnailImage(), LLColor4::white);
+ previewp->getThumbnailImage(), LLColor4::white % alpha);
previewp->drawPreviewRect(offset_x, offset_y) ;
}
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index e5c4547226..2aaf403d5f 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -147,17 +147,6 @@ void LLFloaterTopObjects::handle_land_reply(LLMessageSystem* msg, void** data)
}
-void LLFloaterTopObjects::onAvatarNameCache(const LLUUID& agent_id,
- const LLAvatarName& av_name,
- LLSD element)
-{
- LLScrollListCtrl *list = getChild<LLScrollListCtrl>("objects_list");
-
- element["columns"][2]["value"] = av_name.getCompleteName();
-
- list->addElement(element);
-}
-
void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
{
U32 request_flags;
@@ -182,7 +171,6 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
F32 mono_score = 0.f;
bool have_extended_data = false;
S32 public_urls = 0;
- LLUUID owner_id;
msg->getU32Fast(_PREHASH_ReportData, _PREHASH_TaskLocalID, task_local_id, block);
msg->getUUIDFast(_PREHASH_ReportData, _PREHASH_TaskID, task_id, block);
@@ -198,10 +186,8 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
msg->getU32("DataExtended", "TimeStamp", time_stamp, block);
msg->getF32("DataExtended", "MonoScore", mono_score, block);
msg->getS32(_PREHASH_ReportData,"PublicURLs",public_urls,block);
- msg->getUUID("DataExtended","OwnerID",owner_id,block);
}
-
LLSD element;
element["id"] = task_id;
@@ -252,16 +238,8 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
columns[6]["font"] = "SANSSERIF";
}
element["columns"] = columns;
+ list->addElement(element);
- if (!owner_id.isNull())
- {
- LLAvatarNameCache::get(owner_id, boost::bind(&LLFloaterTopObjects::onAvatarNameCache, this, _1, _2, element));
- }
- else
- {
- list->addElement(element);
- }
-
mObjectListData.append(element);
mObjectListIDs.push_back(task_id);
diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h
index edd91c491f..a608ca20f1 100644
--- a/indra/newview/llfloatertopobjects.h
+++ b/indra/newview/llfloatertopobjects.h
@@ -29,11 +29,8 @@
#include "llfloater.h"
-class LLAvatarName;
class LLUICtrl;
-#include <boost/signals2.hpp> // boost::signals2::trackable
-
class LLFloaterTopObjects : public LLFloater
{
friend class LLFloaterReg;
@@ -54,8 +51,6 @@ public:
static void setMode(U32 mode);
- void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name, LLSD element);
-
private:
LLFloaterTopObjects(const LLSD& key);
~LLFloaterTopObjects();
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 5dc8067648..11b3379814 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -36,6 +36,7 @@
// Internal utility
#include "lleventtimer.h"
+#include "llexternaleditor.h"
#include "llrender.h"
#include "llsdutil.h"
#include "llxmltree.h"
@@ -160,6 +161,8 @@ public:
DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors
private:
+ LLExternalEditor mExternalEditor;
+
// XUI elements for this floater
LLScrollListCtrl* mFileList; // scroll list control for file list
LLLineEditor* mEditorPathTextBox; // text field for path to editor executable
@@ -185,7 +188,7 @@ private:
std::string mSavedDiffPath; // stored diff file path so closing this floater doesn't reset it
// Internal functionality
- static void popupAndPrintWarning(std::string& warning); // pop up a warning
+ static void popupAndPrintWarning(const std::string& warning); // pop up a warning
std::string getLocalizedDirectory(); // build and return the path to the XUI directory for the currently-selected localization
void scanDiffFile(LLXmlTreeNode* file_node); // scan a given XML node for diff entries and highlight them in its associated file
void highlightChangedElements(); // look up the list of elements to highlight and highlight them in the current floater
@@ -480,7 +483,7 @@ BOOL LLFloaterUIPreview::postBuild()
mLanguageSelection->removeall(); // clear out anything temporarily in list from XML
while(found) // for every directory
{
- if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory, FALSE))) // get next directory
+ if((found = gDirUtilp->getNextFileInDir(xui_dir, "*", language_directory))) // get next directory
{
std::string full_path = xui_dir + language_directory;
if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it
@@ -597,7 +600,7 @@ void LLFloaterUIPreview::onClose(bool app_quitting)
// Error handling (to avoid code repetition)
// *TODO: this is currently unlocalized. Add to alerts/notifications.xml, someday, maybe.
-void LLFloaterUIPreview::popupAndPrintWarning(std::string& warning)
+void LLFloaterUIPreview::popupAndPrintWarning(const std::string& warning)
{
llwarns << warning << llendl;
LLSD args;
@@ -634,7 +637,7 @@ void LLFloaterUIPreview::refreshList()
BOOL found = TRUE;
while(found) // for every floater file that matches the pattern
{
- if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name, FALSE))) // get next file matching pattern
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "floater_*.xml", name))) // get next file matching pattern
{
addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
}
@@ -642,7 +645,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every inspector file that matches the pattern
{
- if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name, FALSE))) // get next file matching pattern
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "inspect_*.xml", name))) // get next file matching pattern
{
addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
}
@@ -650,7 +653,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every menu file that matches the pattern
{
- if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name, FALSE))) // get next file matching pattern
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "menu_*.xml", name))) // get next file matching pattern
{
addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
}
@@ -658,7 +661,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every panel file that matches the pattern
{
- if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name, FALSE))) // get next file matching pattern
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "panel_*.xml", name))) // get next file matching pattern
{
addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
}
@@ -667,7 +670,7 @@ void LLFloaterUIPreview::refreshList()
found = TRUE;
while(found) // for every sidepanel file that matches the pattern
{
- if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name, FALSE))) // get next file matching pattern
+ if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name))) // get next file matching pattern
{
addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path)
}
@@ -998,190 +1001,55 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
// Respond to button click to edit currently-selected floater
void LLFloaterUIPreview::onClickEditFloater()
{
- std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
- if(std::string("") == file_name) // if no item is selected
- {
- return; // ignore click
- }
- std::string path = getLocalizedDirectory() + file_name;
-
- // stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
- llstat dummy;
- if(LLFile::stat(path.c_str(), &dummy)) // if the file does not exist
- {
- std::string warning = "No file for this floater exists in the selected localization. Opening the EN version instead.";
- popupAndPrintWarning(warning);
-
- path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
- }
-
- // get executable path
- const char* exe_path_char;
- std::string path_in_textfield = mEditorPathTextBox->getText();
- if(std::string("") != path_in_textfield) // if the text field is not emtpy, use its path
- {
- exe_path_char = path_in_textfield.c_str();
- }
- else if (!LLUI::sSettingGroups["config"]->getString("XUIEditor").empty())
- {
- exe_path_char = LLUI::sSettingGroups["config"]->getString("XUIEditor").c_str();
- }
- else // otherwise use the path specified by the environment variable
+ // Determine file to edit.
+ std::string file_path;
{
- exe_path_char = getenv("LL_XUI_EDITOR");
- }
-
- // error check executable path
- if(NULL == exe_path_char)
- {
- std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR or specifying its path in the \"Editor Path\" field.";
- popupAndPrintWarning(warning);
- return;
- }
- std::string exe_path = exe_path_char; // do this after error check, otherwise internal strlen call fails on bad char*
-
- // remove any quotes; they're added back in later where necessary
- int found_at;
- while((found_at = exe_path.find("\"")) != -1 || (found_at = exe_path.find("'")) != -1)
- {
- exe_path.erase(found_at,1);
- }
-
- llstat s;
- if(!LLFile::stat(exe_path.c_str(), &s)) // If the executable exists
- {
- // build paths and arguments
- std::string quote = std::string("\"");
- std::string args;
- std::string custom_args = mEditorArgsTextBox->getText();
- int position_of_file = custom_args.find(std::string("%FILE%"), 0); // prepare to replace %FILE% with actual file path
- std::string first_part_of_args = "";
- std::string second_part_of_args = "";
- if(-1 == position_of_file) // default: Executable.exe File.xml
- {
- args = quote + path + quote; // execute the command Program.exe "File.xml"
- }
- else // use advanced command-line arguments, e.g. "Program.exe -safe File.xml" -windowed for "-safe %FILE% -windowed"
+ std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
+ if (file_name.empty()) // if no item is selected
{
- first_part_of_args = custom_args.substr(0,position_of_file); // get part of args before file name
- second_part_of_args = custom_args.substr(position_of_file+6,custom_args.length()); // get part of args after file name
- custom_args = first_part_of_args + std::string("\"") + path + std::string("\"") + second_part_of_args; // replace %FILE% with "<file path>" and put back together
- args = custom_args; // and save in the variable that is actually used
+ llwarns << "No file selected" << llendl;
+ return; // ignore click
}
+ file_path = getLocalizedDirectory() + file_name;
- // find directory in which executable resides by taking everything after last slash
- int last_slash_position = exe_path.find_last_of(mDelim);
- if(-1 == last_slash_position)
- {
- std::string warning = std::string("Unable to find a valid path to the specified executable for XUI XML editing: ") + exe_path;
- popupAndPrintWarning(warning);
- return;
- }
- std::string exe_dir = exe_path.substr(0,last_slash_position); // strip executable off, e.g. get "C:\Program Files\TextPad 5" (with or without trailing slash)
-
-#if LL_WINDOWS
- PROCESS_INFORMATION pinfo;
- STARTUPINFOA sinfo;
- memset(&sinfo, 0, sizeof(sinfo));
- memset(&pinfo, 0, sizeof(pinfo));
-
- std::string exe_name = exe_path.substr(last_slash_position+1);
- args = quote + exe_name + quote + std::string(" ") + args; // and prepend the executable name, so we get 'Program.exe "Arg1"'
-
- char *args2 = new char[args.size() + 1]; // Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
- strcpy(args2, args.c_str());
-
- // we don't want the current directory to be the executable directory, since the file path is now relative. By using
- // NULL for the current directory instead of exe_dir.c_str(), the path to the target file will work.
- if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo))
- {
- // DWORD dwErr = GetLastError();
- std::string warning = "Creating editor process failed!";
- popupAndPrintWarning(warning);
- }
- else
+ // stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
+ llstat dummy;
+ if(LLFile::stat(file_path.c_str(), &dummy)) // if the file does not exist
{
- // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
- // sGatewayHandle = pinfo.hProcess;
- CloseHandle(pinfo.hThread); // stops leaks - nothing else
+ popupAndPrintWarning("No file for this floater exists in the selected localization. Opening the EN version instead.");
+ file_path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
}
+ }
- delete[] args2;
-#else // if !LL_WINDOWS
- // This code was copied from the code to run SLVoice, with some modification; should work in UNIX (Mac/Darwin or Linux)
+ // Set the editor command.
+ std::string cmd_override;
+ {
+ std::string bin = mEditorPathTextBox->getText();
+ if (!bin.empty())
{
- std::vector<std::string> arglist;
- arglist.push_back(exe_path.c_str());
-
- // Split the argument string into separate strings for each argument
- typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("","\" ", boost::drop_empty_tokens);
-
- tokenizer tokens(args, sep);
- tokenizer::iterator token_iter;
- BOOL inside_quotes = FALSE;
- BOOL last_was_space = FALSE;
- for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
- {
- if(!strncmp("\"",(*token_iter).c_str(),2))
- {
- inside_quotes = !inside_quotes;
- }
- else if(!strncmp(" ",(*token_iter).c_str(),2))
- {
- if(inside_quotes)
- {
- arglist.back().append(std::string(" "));
- last_was_space = TRUE;
- }
- }
- else
- {
- std::string to_push = *token_iter;
- if(last_was_space)
- {
- arglist.back().append(to_push);
- last_was_space = FALSE;
- }
- else
- {
- arglist.push_back(to_push);
- }
- }
- }
-
- // create an argv vector for the child process
- char **fakeargv = new char*[arglist.size() + 1];
- int i;
- for(i=0; i < arglist.size(); i++)
- fakeargv[i] = const_cast<char*>(arglist[i].c_str());
-
- fakeargv[i] = NULL;
-
- fflush(NULL); // flush all buffers before the child inherits them
- pid_t id = vfork();
- if(id == 0)
+ // surround command with double quotes for the case if the path contains spaces
+ if (bin.find("\"") == std::string::npos)
{
- // child
- execv(exe_path.c_str(), fakeargv);
-
- // If we reach this point, the exec failed.
- // Use _exit() instead of exit() per the vfork man page.
- std::string warning = "Creating editor process failed (vfork/execv)!";
- popupAndPrintWarning(warning);
- _exit(0);
+ bin = "\"" + bin + "\"";
}
- // parent
- delete[] fakeargv;
- // sGatewayPID = id;
+ std::string args = mEditorArgsTextBox->getText();
+ cmd_override = bin + " " + args;
}
-#endif // LL_WINDOWS
}
- else
+ if (!mExternalEditor.setCommand("LL_XUI_EDITOR", cmd_override))
{
- std::string warning = "Unable to find path to external XML editor for XUI preview tool";
+ std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR "
+ "or the ExternalEditor setting or specifying its path in the \"Editor Path\" field.";
popupAndPrintWarning(warning);
+ return;
+ }
+
+ // Run the editor.
+ if (!mExternalEditor.run(file_path))
+ {
+ popupAndPrintWarning("Failed to run editor");
+ return;
}
}
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 7236894542..ba0eb8a711 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -635,7 +635,7 @@ void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos )
// convert global specified position to a local one
F32 region_local_x = (F32)fmod( pos.mdV[VX], (F64)REGION_WIDTH_METERS );
F32 region_local_y = (F32)fmod( pos.mdV[VY], (F64)REGION_WIDTH_METERS );
- F32 region_local_z = (F32)fmod( pos.mdV[VZ], (F64)REGION_WIDTH_METERS );
+ F32 region_local_z = (F32)llclamp( pos.mdV[VZ], 0.0, (F64)REGION_HEIGHT_METERS );
// write in the values
childSetValue("teleport_coordinate_x", region_local_x );
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index c38cd4d090..62ba746a02 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -2429,6 +2429,7 @@ S32 LLFolderView::notify(const LLSD& info)
{
setFocus(true);
selectFirstItem();
+ scrollToShowSelection();
return 1;
}
@@ -2436,6 +2437,7 @@ S32 LLFolderView::notify(const LLSD& info)
{
setFocus(true);
selectLastItem();
+ scrollToShowSelection();
return 1;
}
}
diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp
index 260e15c714..f990b9294d 100644
--- a/indra/newview/llgiveinventory.cpp
+++ b/indra/newview/llgiveinventory.cpp
@@ -128,7 +128,7 @@ bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item)
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
- if (gAgentAvatarp->isWearingAttachment(item->getUUID()))
+ if (get_is_item_worn(item->getUUID()))
{
acceptable = false;
}
@@ -139,7 +139,7 @@ bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item)
BOOL copyable = false;
if (item->getPermissions().allowCopyBy(gAgentID)) copyable = true;
- if (!copyable && gAgentWearables.isWearingItem(item->getUUID()))
+ if (!copyable && get_is_item_worn(item->getUUID()))
{
acceptable = false;
}
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index d43b3a5d6e..842911ecc0 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -663,35 +663,27 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV
x2 = x1 + PARCEL_GRID_STEP_METERS;
y2 = y1;
- if (gRenderForSelect)
- {
- LLColor4U color((U8)(GL_NAME_PARCEL_WALL >> 16), (U8)(GL_NAME_PARCEL_WALL >> 8), (U8)GL_NAME_PARCEL_WALL);
- gGL.color4ubv(color.mV);
- }
- else
- {
- dy = (pos_y - y1) + DIST_OFFSET;
-
- if (pos_x < x1)
- dx = pos_x - x1;
- else if (pos_x > x2)
- dx = pos_x - x2;
- else
- dx = 0;
+ dy = (pos_y - y1) + DIST_OFFSET;
- dist = dx*dx+dy*dy;
-
- if (dist < MIN_DIST_SQ)
- alpha = MAX_ALPHA;
- else if (dist > MAX_DIST_SQ)
- alpha = 0.0f;
- else
- alpha = 30/dist;
-
- alpha = llclamp(alpha, 0.0f, MAX_ALPHA);
-
- gGL.color4f(1.f, 1.f, 1.f, alpha);
- }
+ if (pos_x < x1)
+ dx = pos_x - x1;
+ else if (pos_x > x2)
+ dx = pos_x - x2;
+ else
+ dx = 0;
+
+ dist = dx*dx+dy*dy;
+
+ if (dist < MIN_DIST_SQ)
+ alpha = MAX_ALPHA;
+ else if (dist > MAX_DIST_SQ)
+ alpha = 0.0f;
+ else
+ alpha = 30/dist;
+
+ alpha = llclamp(alpha, 0.0f, MAX_ALPHA);
+
+ gGL.color4f(1.f, 1.f, 1.f, alpha);
if ((pos_y - y1) < 0) direction = SOUTH_MASK;
else direction = NORTH_MASK;
@@ -709,35 +701,27 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV
x2 = x1;
y2 = y1 + PARCEL_GRID_STEP_METERS;
- if (gRenderForSelect)
- {
- LLColor4U color((U8)(GL_NAME_PARCEL_WALL >> 16), (U8)(GL_NAME_PARCEL_WALL >> 8), (U8)GL_NAME_PARCEL_WALL);
- gGL.color4ubv(color.mV);
- }
+ dx = (pos_x - x1) + DIST_OFFSET;
+
+ if (pos_y < y1)
+ dy = pos_y - y1;
+ else if (pos_y > y2)
+ dy = pos_y - y2;
+ else
+ dy = 0;
+
+ dist = dx*dx+dy*dy;
+
+ if (dist < MIN_DIST_SQ)
+ alpha = MAX_ALPHA;
+ else if (dist > MAX_DIST_SQ)
+ alpha = 0.0f;
else
- {
- dx = (pos_x - x1) + DIST_OFFSET;
-
- if (pos_y < y1)
- dy = pos_y - y1;
- else if (pos_y > y2)
- dy = pos_y - y2;
- else
- dy = 0;
-
- dist = dx*dx+dy*dy;
-
- if (dist < MIN_DIST_SQ)
- alpha = MAX_ALPHA;
- else if (dist > MAX_DIST_SQ)
- alpha = 0.0f;
- else
- alpha = 30/dist;
-
- alpha = llclamp(alpha, 0.0f, MAX_ALPHA);
+ alpha = 30/dist;
+
+ alpha = llclamp(alpha, 0.0f, MAX_ALPHA);
- gGL.color4f(1.f, 1.f, 1.f, alpha);
- }
+ gGL.color4f(1.f, 1.f, 1.f, alpha);
if ((pos_x - x1) > 0) direction = WEST_MASK;
else direction = EAST_MASK;
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index aea8c5928b..568b0ae585 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -201,11 +201,6 @@ void LLHUDIcon::render()
renderIcon(FALSE);
}
-void LLHUDIcon::renderForSelect()
-{
- renderIcon(TRUE);
-}
-
BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3* intersection)
{
if (mHidden)
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index 8d7b8d4288..644daa0299 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -52,7 +52,6 @@ friend class LLHUDObject;
public:
/*virtual*/ void render();
- /*virtual*/ void renderForSelect();
/*virtual*/ void markDead();
/*virtual*/ F32 getDistance() const { return mDistance; }
diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp
index 09200ee5be..5e762ee037 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -284,27 +284,6 @@ void LLHUDObject::renderAll()
}
// static
-void LLHUDObject::renderAllForSelect()
-{
- LLHUDObject *hud_objp;
-
- hud_object_list_t::iterator object_it;
- for (object_it = sHUDObjects.begin(); object_it != sHUDObjects.end(); )
- {
- hud_object_list_t::iterator cur_it = object_it++;
- hud_objp = (*cur_it);
- if (hud_objp->getNumRefs() == 1)
- {
- sHUDObjects.erase(cur_it);
- }
- else if (hud_objp->isVisible())
- {
- hud_objp->renderForSelect();
- }
- }
-}
-
-// static
void LLHUDObject::renderAllForTimer()
{
LLHUDObject *hud_objp;
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index 4282ade34d..33e6394445 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -104,7 +104,6 @@ protected:
~LLHUDObject();
virtual void render() = 0;
- virtual void renderForSelect() {};
virtual void renderForTimer() {};
protected:
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 6a423e529a..f7e5103d88 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -113,36 +113,21 @@ void LLHUDText::render()
if (!mOnHUDAttachment && sDisplayText)
{
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- renderText(FALSE);
+ renderText();
}
}
-void LLHUDText::renderForSelect()
-{
- if (!mOnHUDAttachment)
- {
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- renderText(TRUE);
- }
-}
-
-void LLHUDText::renderText(BOOL for_select)
+void LLHUDText::renderText()
{
if (!mVisible || mHidden)
{
return;
}
- // don't pick text
- if (for_select)
- {
- return;
- }
-
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
- LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
+ LLGLState gls_blend(GL_BLEND, TRUE);
+ LLGLState gls_alpha(GL_ALPHA_TEST, TRUE);
LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f);
F32 alpha_factor = 1.f;
@@ -594,7 +579,7 @@ void LLHUDText::renderAllHUD()
for (text_it = sVisibleHUDTextObjects.begin(); text_it != sVisibleHUDTextObjects.end(); ++text_it)
{
- (*text_it)->renderText(FALSE);
+ (*text_it)->renderText();
}
}
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index f05ee4d594..36015d51f0 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -128,8 +128,7 @@ protected:
LLHUDText(const U8 type);
/*virtual*/ void render();
- /*virtual*/ void renderForSelect();
- void renderText(BOOL for_select);
+ void renderText();
static void updateAll();
S32 getMaxLines();
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index e000abda2a..bdc0dfa7e2 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -680,8 +680,6 @@ void LLIMFloater::updateMessages()
if (messages.size())
{
-// LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor");
-
LLSD chat_args;
chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 02a693b9a0..2f40f51763 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -131,6 +131,20 @@ void toast_callback(const LLSD& msg){
return;
}
+ // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea
+ LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(
+ msg["session_id"]);
+ if (!gSavedSettings.getBOOL("EnableGroupChatPopups")
+ && session->isGroupSessionType())
+ {
+ return;
+ }
+ if (!gSavedSettings.getBOOL("EnableIMChatPopups")
+ && !session->isGroupSessionType())
+ {
+ return;
+ }
+
// Skip toasting if we have open window of IM with this session id
LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]);
if (open_im_floater && open_im_floater->getVisible())
@@ -523,15 +537,14 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
void LLIMModel::LLIMSession::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
{
- if (av_name.mLegacyFirstName.empty())
+ if (av_name.mUsername.empty())
{
- // if mLegacyFirstName is empty it means display names is off and the
- // data came from the gCacheName, mDisplayName will be the legacy name
- mHistoryFileName = LLCacheName::cleanFullName(av_name.mDisplayName);
+ // display names is off, use mDisplayName which will be the legacy name
+ mHistoryFileName = LLCacheName::buildUsername(av_name.mDisplayName);
}
else
{
- mHistoryFileName = LLCacheName::cleanFullName(av_name.getLegacyName());
+ mHistoryFileName = av_name.mUsername;
}
}
@@ -542,7 +555,12 @@ void LLIMModel::LLIMSession::buildHistoryFileName()
//ad-hoc requires sophisticated chat history saving schemes
if (isAdHoc())
{
- //in case of outgoing ad-hoc sessions
+ /* in case of outgoing ad-hoc sessions we need to make specilized names
+ * if this naming system is ever changed then the filtering definitions in
+ * lllogchat.cpp need to be change acordingly so that the filtering for the
+ * date stamp code introduced in STORM-102 will work properly and not add
+ * a date stamp to the Ad-hoc conferences.
+ */
if (mInitialTargetIDs.size())
{
std::set<LLUUID> sorted_uuids(mInitialTargetIDs.begin(), mInitialTargetIDs.end());
@@ -1064,17 +1082,27 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
if( session == 0)//??? shouldn't really happen
{
LLRecentPeople::instance().add(other_participant_id);
+ return;
}
- else
+ // IM_SESSION_INVITE means that this is an Ad-hoc incoming chat
+ // (it can be also Group chat but it is checked above)
+ // In this case mInitialTargetIDs contains Ad-hoc session ID and it should not be added
+ // to Recent People to prevent showing of an item with (???)(???). See EXT-8246.
+ // Concrete participants will be added into this list once they sent message in chat.
+ if (IM_SESSION_INVITE == dialog) return;
+
+ if (IM_SESSION_CONFERENCE_START == dialog) // outgoing ad-hoc session
{
- // IM_SESSION_INVITE means that this is an Ad-hoc incoming chat
- // (it can be also Group chat but it is checked above)
- // In this case mInitialTargetIDs contains Ad-hoc session ID and it should not be added
- // to Recent People to prevent showing of an item with (???)(???). See EXT-8246.
- // Concrete participants will be added into this list once they sent message in chat.
- if (IM_SESSION_INVITE == dialog) return;
- // Add only online members to recent (EXT-8658)
- addSpeakersToRecent(im_session_id);
+ // Add only online members of conference to recent list (EXT-8658)
+ addSpeakersToRecent(im_session_id);
+ }
+ else // outgoing P2P session
+ {
+ // Add the recepient of the session.
+ if (!session->mInitialTargetIDs.empty())
+ {
+ LLRecentPeople::instance().add(*(session->mInitialTargetIDs.begin()));
+ }
}
}
}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 650d329e18..3f72d66bfb 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -62,7 +62,7 @@ class LLIMModel : public LLSingleton<LLIMModel>
{
public:
- struct LLIMSession
+ struct LLIMSession : public boost::signals2::trackable
{
typedef enum e_session_type
{ // for now we have 4 predefined types for a session
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 29dcb2c4d3..91ede6d221 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -53,6 +53,7 @@
#include "llfloaterreg.h"
#include "llmenubutton.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "lltooltip.h" // positionViewNearMouse()
#include "lltrans.h"
#include "lluictrl.h"
@@ -402,8 +403,8 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
// if neither the gear menu or self gear menu are open
void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask)
{
- LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
- LLMenuGL* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu();
+ LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
+ LLToggleableMenu* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu();
if ( gear_menu && gear_menu->getVisible() &&
gear_menu_self && gear_menu_self->getVisible() )
{
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
index 532ffca4be..ee076f68ea 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -47,6 +47,7 @@
#include "llsafehandle.h"
#include "llsidetray.h"
#include "lltextbox.h" // for description truncation
+#include "lltoggleablemenu.h"
#include "lltrans.h"
#include "llui.h" // positionViewNearMouse()
#include "lluictrl.h"
@@ -568,7 +569,7 @@ void LLInspectObject::updateSecureBrowsing()
// if the gear menu is not open
void LLInspectObject::onMouseLeave(S32 x, S32 y, MASK mask)
{
- LLMenuGL* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
+ LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu();
if ( gear_menu && gear_menu->getVisible() )
{
return;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b15dcd993a..5ba87423c7 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1643,16 +1643,19 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
&& (LLToolDragAndDrop::SOURCE_AGENT == source);
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+
BOOL accept = FALSE;
if (is_agent_inventory)
{
const LLUUID &cat_id = inv_cat->getUUID();
const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
- const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT);
- const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
//--------------------------------------------------------------------------------
// Determine if folder can be moved.
@@ -1690,6 +1693,21 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
+ if (move_is_into_landmarks)
+ {
+ for (S32 i=0; i < descendent_items.count(); ++i)
+ {
+ LLViewerInventoryItem* item = descendent_items[i];
+
+ // Don't move anything except landmarks and categories into Landmarks folder.
+ // We use getType() instead of getActua;Type() to allow links to landmarks and folders.
+ if (LLAssetType::AT_LANDMARK != item->getType() && LLAssetType::AT_CATEGORY != item->getType())
+ {
+ is_movable = FALSE;
+ break; // It's generally movable, but not into Landmarks.
+ }
+ }
+ }
//
//--------------------------------------------------------------------------------
@@ -1777,6 +1795,17 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
LLUUID category_id = mUUID;
accept = move_inv_category_world_to_agent(object_id, category_id, drop);
}
+ else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
+ {
+ // Accept folders that contain complete outfits.
+ accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID());
+
+ if (accept && drop)
+ {
+ LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, true, false);
+ }
+ }
+
return accept;
}
@@ -2661,6 +2690,8 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data)
{
+ LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
+
//llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
BOOL accept = FALSE;
switch(cargo_type)
@@ -2676,9 +2707,24 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_BODYPART:
case DAD_ANIMATION:
case DAD_GESTURE:
+ accept = dragItemIntoFolder(inv_item, drop);
+ break;
case DAD_LINK:
- accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
- drop);
+ // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER.
+ // If we have an item of AT_LINK_FOLDER type we should process the linked
+ // category being dragged or dropped into folder.
+ if (inv_item && LLAssetType::AT_LINK_FOLDER == inv_item->getActualType())
+ {
+ LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID());
+ if (linked_category)
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop);
+ }
+ }
+ else
+ {
+ accept = dragItemIntoFolder(inv_item, drop);
+ }
break;
case DAD_CATEGORY:
if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
@@ -2862,6 +2908,7 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr
{
if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) &&
(inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) &&
+ (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) &&
(inv_item->getInventoryType() != LLInventoryType::IT_OBJECT))
{
return FALSE;
@@ -2875,6 +2922,24 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr
return TRUE;
}
+// Returns TRUE if item is a landmark or a link to a landmark
+// and can be moved to Favorites or Landmarks folder.
+static BOOL can_move_to_landmarks(LLInventoryItem* inv_item)
+{
+ // Need to get the linked item to know its type because LLInventoryItem::getType()
+ // returns actual type AT_LINK for links, not the asset type of a linked item.
+ if (LLAssetType::AT_LINK == inv_item->getType())
+ {
+ LLInventoryItem* linked_item = gInventory.getItem(inv_item->getLinkedUUID());
+ if (linked_item)
+ {
+ return LLAssetType::AT_LANDMARK == linked_item->getType();
+ }
+ }
+
+ return LLAssetType::AT_LANDMARK == inv_item->getType();
+}
+
void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
{
// use callback to rearrange favorite landmarks after adding
@@ -2931,9 +2996,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
+ const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_favorites = (mUUID == favorites_id);
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
BOOL accept = FALSE;
@@ -2944,7 +3012,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID());
- const BOOL folder_allows_reorder = (mUUID == favorites_id);
//--------------------------------------------------------------------------------
// Determine if item can be moved.
@@ -2990,12 +3057,16 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
if (!is_movable)
accept = FALSE;
- if ((mUUID == inv_item->getParentUUID()) && !folder_allows_reorder)
+ if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites)
accept = FALSE;
if (move_is_into_current_outfit || move_is_into_outfit)
{
accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
}
+ else if (move_is_into_favorites || move_is_into_landmarks)
+ {
+ accept = can_move_to_landmarks(inv_item);
+ }
if(accept && drop)
{
@@ -3021,8 +3092,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
//
// REORDER
- // (only reorder the item)
- if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder)
+ // (only reorder the item in Favorites folder)
+ if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites)
{
LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
@@ -3036,7 +3107,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// FAVORITES folder
// (copy the item)
- else if (favorites_id == mUUID)
+ else if (move_is_into_favorites)
{
dropToFavorites(inv_item);
}
@@ -3101,6 +3172,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = FALSE;
}
+ // Don't allow to move a single item to Favorites or Landmarks
+ // if it is not a landmark or a link to a landmark.
+ else if ((move_is_into_favorites || move_is_into_landmarks)
+ && !can_move_to_landmarks(inv_item))
+ {
+ accept = FALSE;
+ }
if(drop && accept)
{
@@ -3146,12 +3224,18 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
}
+ // Don't allow to move a single item to Favorites or Landmarks
+ // if it is not a landmark or a link to a landmark.
+ else if (move_is_into_favorites || move_is_into_landmarks)
+ {
+ accept = can_move_to_landmarks(inv_item);
+ }
if (accept && drop)
{
// FAVORITES folder
// (copy the item)
- if (favorites_id == mUUID)
+ if (move_is_into_favorites)
{
dropToFavorites(inv_item);
}
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f3d9639dee..ef20869114 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -487,12 +487,9 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryIte
return false;
break;
case LLAssetType::AT_OBJECT:
- if (isAgentAvatarValid() && !gAgentAvatarp->isWearingAttachment(item->getUUID()))
- return true;
- break;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
- if(!gAgentWearables.isWearingItem(item->getUUID()))
+ if (!get_is_item_worn(item->getUUID()))
return true;
break;
default:
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 7216d61e7f..3f4f33e88d 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -50,7 +50,7 @@ public:
LLIconDictionary::LLIconDictionary()
{
addEntry(LLInventoryIcon::ICONNAME_TEXTURE, new IconEntry("Inv_Texture"));
- addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Texture"));
+ addEntry(LLInventoryIcon::ICONNAME_SOUND, new IconEntry("Inv_Sound"));
addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_ONLINE, new IconEntry("Inv_CallingCard"));
addEntry(LLInventoryIcon::ICONNAME_CALLINGCARD_OFFLINE, new IconEntry("Inv_CallingCard"));
addEntry(LLInventoryIcon::ICONNAME_LANDMARK, new IconEntry("Inv_Landmark"));
@@ -83,7 +83,7 @@ LLIconDictionary::LLIconDictionary()
addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture"));
addEntry(LLInventoryIcon::ICONNAME_LINKITEM, new IconEntry("Inv_LinkItem"));
- addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkItem"));
+ addEntry(LLInventoryIcon::ICONNAME_LINKFOLDER, new IconEntry("Inv_LinkFolder"));
addEntry(LLInventoryIcon::ICONNAME_INVALID, new IconEntry("Inv_Invalid"));
diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp
index 225d0288a9..3e0849a795 100644
--- a/indra/newview/llinventorylistitem.cpp
+++ b/indra/newview/llinventorylistitem.cpp
@@ -97,7 +97,8 @@ void LLPanelInventoryListItemBase::draw()
LLRect separator_rect = getLocalRect();
separator_rect.mTop = separator_rect.mBottom;
separator_rect.mBottom -= mSeparatorImage->getHeight();
- mSeparatorImage->draw(separator_rect);
+ F32 alpha = getCurrentTransparency();
+ mSeparatorImage->draw(separator_rect, UI_VERTEX_COLOR % alpha);
}
LLPanel::draw();
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 50adae09c0..0870b5b8dd 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -290,7 +290,10 @@ void LLInventoryPanel::modelChanged(U32 mask)
const LLUUID& item_id = (*items_iter);
const LLInventoryObject* model_item = model->getObject(item_id);
LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id);
- LLFolderViewFolder* view_folder = mFolderRoot->getFolderByID(item_id);
+
+ // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item
+ // to folder is the fast way to get a folder without searching through folders tree.
+ LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item);
//////////////////////////////
// LABEL Operation
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 8c70b1e973..0121bbb1ed 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -89,6 +89,16 @@ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+
*/
const static boost::regex NAME_AND_TEXT("([^:]+[:]{1})?(\\s*)(.*)");
+/**
+ * These are recognizers for matching the names of ad-hoc conferences when generating the log file name
+ * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4"
+ * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>"
+ * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName()
+ * then these definition need to be adjusted as well.
+ */
+const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}");
+const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}");
+
//is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st"
const static std::string NAME_TEXT_DIVIDER(": ");
@@ -182,15 +192,43 @@ private:
//static
std::string LLLogChat::makeLogFileName(std::string filename)
{
+ /**
+ * Testing for in bound and out bound ad-hoc file names
+ * if it is then skip date stamping.
+ **/
+ //LL_INFOS("") << "Befor:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
+ boost::match_results<std::string::const_iterator> matches;
+ bool inboundConf = boost::regex_match(filename, matches, INBOUND_CONFERENCE);
+ bool outboundConf = boost::regex_match(filename, matches, OUTBOUND_CONFERENCE);
+ if (!(inboundConf || outboundConf))
+ {
+ if( gSavedPerAccountSettings.getBOOL("LogFileNamewithDate") )
+ {
+ time_t now;
+ time(&now);
+ char dbuffer[20]; /* Flawfinder: ignore */
+ if (filename == "chat")
+ {
+ strftime(dbuffer, 20, "-%Y-%m-%d", localtime(&now));
+ }
+ else
+ {
+ strftime(dbuffer, 20, "-%Y-%m", localtime(&now));
+ }
+ filename += dbuffer;
+ }
+ }
+ //LL_INFOS("") << "After:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
filename = cleanFileName(filename);
filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS,filename);
filename += ".txt";
+ //LL_INFOS("") << "Full:" << filename << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
return filename;
}
std::string LLLogChat::cleanFileName(std::string filename)
{
- std::string invalidChars = "\"\'\\/?*:<>|";
+ std::string invalidChars = "\"\'\\/?*:.<>|";
std::string::size_type position = filename.find_first_of(invalidChars);
while (position != filename.npos)
{
@@ -354,10 +392,19 @@ void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& me
llwarns << "Session name is Empty!" << llendl;
return ;
}
-
- LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r"); /*Flawfinder: ignore*/
- if (!fptr) return; //No previous conversation with this name.
-
+ //LL_INFOS("") << "Loading:" << file_name << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
+ //LL_INFOS("") << "Current:" << makeLogFileName(file_name) << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
+ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/
+ if (!fptr)
+ {
+ if (!fptr) return; //No previous conversation with this name.
+ }
+ }
+
+ //LL_INFOS("") << "Reading:" << file_name << LL_ENDL;
char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
char *bptr;
S32 len;
@@ -544,3 +591,32 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im)
im[IM_TEXT] = name_and_text[IDX_TEXT];
return true; //parsed name and message text, maybe have a timestamp too
}
+std::string LLLogChat::oldLogFileName(std::string filename)
+{
+ std::string scanResult;
+ std::string directory = gDirUtilp->getPerAccountChatLogsDir();/* get Users log directory */
+ directory += gDirUtilp->getDirDelimiter();/* add final OS dependent delimiter */
+ filename=cleanFileName(filename);/* lest make shure the file name has no invalad charecters befor making the pattern */
+ std::string pattern = (filename+(( filename == "chat" ) ? "-???\?-?\?-??.txt" : "-???\?-??.txt"));/* create search pattern*/
+ //LL_INFOS("") << "Checking:" << directory << " for " << pattern << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
+ std::vector<std::string> allfiles;
+
+ while (gDirUtilp->getNextFileInDir(directory, pattern, scanResult))
+ {
+ //LL_INFOS("") << "Found :" << scanResult << LL_ENDL;
+ allfiles.push_back(scanResult);
+ }
+
+ if (allfiles.size() == 0) // if no result from date search, return generic filename
+ {
+ scanResult = directory + filename + ".txt";
+ }
+ else
+ {
+ std::sort(allfiles.begin(), allfiles.end());
+ scanResult = directory + allfiles.back();
+ // thisfile is now the most recent version of the file.
+ }
+ //LL_INFOS("") << "Reading:" << scanResult << LL_ENDL;/* uncomment if you want to verify step, delete on commit */
+ return scanResult;
+}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index 6958d56311..27752452c9 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -41,6 +41,10 @@ public:
};
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
+ /**
+ *Add functions to get old and non date stamped file names when needed
+ */
+ static std::string oldLogFileName(std::string(filename));
static void saveHistory(const std::string& filename,
const std::string& from,
const LLUUID& from_id,
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 029e700c4c..52ce932241 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -42,6 +42,7 @@
// newview
#include "llviewernetwork.h"
#include "llviewercontrol.h"
+#include "llversioninfo.h"
#include "llslurl.h"
#include "llstartup.h"
#include "llfloaterreg.h"
@@ -149,6 +150,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
requested_options.append("newuser-config");
requested_options.append("ui-config");
#endif
+ requested_options.append("max-agent-groups");
requested_options.append("map-server-url");
requested_options.append("voice-config");
requested_options.append("tutorial_setting");
@@ -181,8 +183,8 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
request_params["read_critical"] = false; // handleTOSResponse
request_params["last_exec_event"] = mLastExecEvent;
request_params["mac"] = hashed_unique_id_string;
- request_params["version"] = gCurrentVersion; // Includes channel name
- request_params["channel"] = gSavedSettings.getString("VersionChannelName");
+ request_params["version"] = LLVersionInfo::getChannelAndVersion(); // Includes channel name
+ request_params["channel"] = LLVersionInfo::getChannel();
request_params["id0"] = mSerialNumber;
mRequestData.clear();
diff --git a/indra/newview/llmainlooprepeater.cpp b/indra/newview/llmainlooprepeater.cpp
new file mode 100644
index 0000000000..5c020e6d98
--- /dev/null
+++ b/indra/newview/llmainlooprepeater.cpp
@@ -0,0 +1,88 @@
+/**
+ * @file llmachineid.cpp
+ * @brief retrieves unique machine ids
+ *
+ * $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 "llapr.h"
+#include "llevents.h"
+#include "llmainlooprepeater.h"
+
+
+
+// LLMainLoopRepeater
+//-----------------------------------------------------------------------------
+
+
+LLMainLoopRepeater::LLMainLoopRepeater(void):
+ mQueue(0)
+{
+ ; // No op.
+}
+
+
+void LLMainLoopRepeater::start(void)
+{
+ if(mQueue != 0) return;
+
+ mQueue = new LLThreadSafeQueue<LLSD>(gAPRPoolp, 1024);
+ mMainLoopConnection = LLEventPumps::instance().
+ obtain("mainloop").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1));
+ mRepeaterConnection = LLEventPumps::instance().
+ obtain("mainlooprepeater").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMessage, this, _1));
+}
+
+
+void LLMainLoopRepeater::stop(void)
+{
+ mMainLoopConnection.release();
+ mRepeaterConnection.release();
+
+ delete mQueue;
+ mQueue = 0;
+}
+
+
+bool LLMainLoopRepeater::onMainLoop(LLSD const &)
+{
+ LLSD message;
+ while(mQueue->tryPopBack(message)) {
+ std::string pump = message["pump"].asString();
+ if(pump.length() == 0 ) continue; // No pump.
+ LLEventPumps::instance().obtain(pump).post(message["payload"]);
+ }
+ return false;
+}
+
+
+bool LLMainLoopRepeater::onMessage(LLSD const & event)
+{
+ try {
+ mQueue->pushFront(event);
+ } catch(LLThreadSafeQueueError & e) {
+ llwarns << "could not repeat message (" << e.what() << ")" <<
+ event.asString() << LL_ENDL;
+ }
+ return false;
+}
diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h
new file mode 100644
index 0000000000..f84c0ca94c
--- /dev/null
+++ b/indra/newview/llmainlooprepeater.h
@@ -0,0 +1,65 @@
+/**
+ * @file llmainlooprepeater.h
+ * @brief a service for repeating messages on the main loop.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMAINLOOPREPEATER_H
+#define LL_LLMAINLOOPREPEATER_H
+
+
+#include "llsd.h"
+#include "llthreadsafequeue.h"
+
+
+//
+// A service which creates the pump 'mainlooprepeater' to which any thread can
+// post a message that will be re-posted on the main loop.
+//
+// The posted message should contain two map elements: pump and payload. The
+// pump value is a string naming the pump to which the message should be
+// re-posted. The payload value is what will be posted to the designated pump.
+//
+class LLMainLoopRepeater:
+ public LLSingleton<LLMainLoopRepeater>
+{
+public:
+ LLMainLoopRepeater(void);
+
+ // Start the repeater service.
+ void start(void);
+
+ // Stop the repeater service.
+ void stop(void);
+
+private:
+ LLTempBoundListener mMainLoopConnection;
+ LLTempBoundListener mRepeaterConnection;
+ LLThreadSafeQueue<LLSD> * mQueue;
+
+ bool onMainLoop(LLSD const &);
+ bool onMessage(LLSD const & event);
+};
+
+
+#endif
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 5eb3b789f2..f871df0c36 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -726,7 +726,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move;
// Don't let object centers go too far underground
- F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object);
+ F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal());
if (new_position_global.mdV[VZ] < min_height)
{
new_position_global.mdV[VZ] = min_height;
diff --git a/indra/newview/llmetricperformancetester.cpp b/indra/newview/llmetricperformancetester.cpp
deleted file mode 100644
index 903c97378e..0000000000
--- a/indra/newview/llmetricperformancetester.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/**
- * @file llmetricperformancetester.cpp
- * @brief LLMetricPerformanceTester class implementation
- *
- * $LicenseInfo:firstyear=2004&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 "indra_constants.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "llfontgl.h"
-#include "llsdserialize.h"
-#include "llstat.h"
-#include "lltreeiterators.h"
-#include "llmetricperformancetester.h"
-
-LLMetricPerformanceTester::name_tester_map_t LLMetricPerformanceTester::sTesterMap ;
-
-//static
-void LLMetricPerformanceTester::initClass()
-{
-}
-//static
-void LLMetricPerformanceTester::cleanClass()
-{
- for(name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
- {
- delete iter->second ;
- }
- sTesterMap.clear() ;
-}
-
-//static
-void LLMetricPerformanceTester::addTester(LLMetricPerformanceTester* tester)
-{
- if(!tester)
- {
- llerrs << "invalid tester!" << llendl ;
- return ;
- }
-
- std::string name = tester->getName() ;
- if(getTester(name))
- {
- llerrs << "Tester name is used by some other tester: " << name << llendl ;
- return ;
- }
-
- sTesterMap.insert(std::make_pair(name, tester));
-
- return ;
-}
-
-//static
-LLMetricPerformanceTester* LLMetricPerformanceTester::getTester(std::string label)
-{
- name_tester_map_t::iterator found_it = sTesterMap.find(label) ;
- if(found_it != sTesterMap.end())
- {
- return found_it->second ;
- }
-
- return NULL ;
-}
-
-LLMetricPerformanceTester::LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis)
- : mName(name),
- mBaseSessionp(NULL),
- mCurrentSessionp(NULL),
- mCount(0),
- mUseDefaultPerformanceAnalysis(use_default_performance_analysis)
-{
- if(mName == std::string())
- {
- llerrs << "invalid name." << llendl ;
- }
-
- LLMetricPerformanceTester::addTester(this) ;
-}
-
-/*virtual*/
-LLMetricPerformanceTester::~LLMetricPerformanceTester()
-{
- if(mBaseSessionp)
- {
- delete mBaseSessionp ;
- mBaseSessionp = NULL ;
- }
- if(mCurrentSessionp)
- {
- delete mCurrentSessionp ;
- mCurrentSessionp = NULL ;
- }
-}
-
-void LLMetricPerformanceTester::incLabel()
-{
- mCurLabel = llformat("%s-%d", mName.c_str(), mCount++) ;
-}
-void LLMetricPerformanceTester::preOutputTestResults(LLSD* sd)
-{
- incLabel() ;
- (*sd)[mCurLabel]["Name"] = mName ;
-}
-void LLMetricPerformanceTester::postOutputTestResults(LLSD* sd)
-{
- LLMutexLock lock(LLFastTimer::sLogLock);
- LLFastTimer::sLogQueue.push((*sd));
-}
-
-void LLMetricPerformanceTester::outputTestResults()
-{
- LLSD sd ;
- preOutputTestResults(&sd) ;
-
- outputTestRecord(&sd) ;
-
- postOutputTestResults(&sd) ;
-}
-
-void LLMetricPerformanceTester::addMetricString(std::string str)
-{
- mMetricStrings.push_back(str) ;
-}
-
-const std::string& LLMetricPerformanceTester::getMetricString(U32 index) const
-{
- return mMetricStrings[index] ;
-}
-
-void LLMetricPerformanceTester::prePerformanceAnalysis()
-{
- mCount = 0 ;
- incLabel() ;
-}
-
-//
-//default analyzing the performance
-//
-/*virtual*/
-void LLMetricPerformanceTester::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
-{
- if(mUseDefaultPerformanceAnalysis)//use default performance analysis
- {
- prePerformanceAnalysis() ;
-
- BOOL in_base = (*base).has(mCurLabel) ;
- BOOL in_current = (*current).has(mCurLabel) ;
-
- while(in_base || in_current)
- {
- LLSD::String label = mCurLabel ;
-
- if(in_base && in_current)
- {
- *os << llformat("%s\n", label.c_str()) ;
-
- for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
- {
- switch((*current)[label][ mMetricStrings[index] ].type())
- {
- case LLSD::TypeInteger:
- compareTestResults(os, mMetricStrings[index],
- (S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
- break ;
- case LLSD::TypeReal:
- compareTestResults(os, mMetricStrings[index],
- (F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
- break;
- default:
- llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
- }
- }
- }
-
- incLabel() ;
- in_base = (*base).has(mCurLabel) ;
- in_current = (*current).has(mCurLabel) ;
- }
- }//end of default
- else
- {
- //load the base session
- prePerformanceAnalysis() ;
- mBaseSessionp = loadTestSession(base) ;
-
- //load the current session
- prePerformanceAnalysis() ;
- mCurrentSessionp = loadTestSession(current) ;
-
- if(!mBaseSessionp || !mCurrentSessionp)
- {
- llerrs << "memory error during loading test sessions." << llendl ;
- }
-
- //compare
- compareTestSessions(os) ;
-
- //release memory
- if(mBaseSessionp)
- {
- delete mBaseSessionp ;
- mBaseSessionp = NULL ;
- }
- if(mCurrentSessionp)
- {
- delete mCurrentSessionp ;
- mCurrentSessionp = NULL ;
- }
- }
-}
-
-//virtual
-void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current)
-{
- *os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
- v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
-}
-
-//virtual
-void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current)
-{
- *os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
- v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
-}
-
-//virtual
-LLMetricPerformanceTester::LLTestSession::~LLTestSession()
-{
-}
-
diff --git a/indra/newview/llmetricperformancetester.h b/indra/newview/llmetricperformancetester.h
deleted file mode 100644
index 6f5dc03564..0000000000
--- a/indra/newview/llmetricperformancetester.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/**
- * @file LLMetricPerformanceTester.h
- * @brief LLMetricPerformanceTester class definition
- *
- * $LicenseInfo:firstyear=2004&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_METRICPERFORMANCETESTER_H
-#define LL_METRICPERFORMANCETESTER_H
-
-class LLMetricPerformanceTester
-{
-public:
- //
- //name passed to the constructor is a unique string for each tester.
- //an error is reported if the name is already used by some other tester.
- //
- LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis) ;
- virtual ~LLMetricPerformanceTester();
-
- //
- //return the name of the tester
- //
- std::string getName() const { return mName ;}
- //
- //return the number of the test metrics in this tester
- //
- S32 getNumOfMetricStrings() const { return mMetricStrings.size() ;}
- //
- //return the metric string at the index
- //
- const std::string& getMetricString(U32 index) const ;
-
- //
- //this function to compare the test results.
- //by default, it compares the test results against the baseline one by one, item by item,
- //in the increasing order of the LLSD label counter, starting from the first one.
- //you can define your own way to analyze performance by passing FALSE to "use_default_performance_analysis",
- //and implement two abstract virtual functions below: loadTestSession(...) and compareTestSessions(...).
- //
- void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
-
-protected:
- //
- //insert metric strings used in the tester.
- //
- void addMetricString(std::string str) ;
-
- //
- //increase LLSD label by 1
- //
- void incLabel() ;
-
- //
- //the function to write a set of test results to the log LLSD.
- //
- void outputTestResults() ;
-
- //
- //compare the test results.
- //you can write your own to overwrite the default one.
- //
- virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
- virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
-
- //
- //for performance analysis use
- //it defines an interface for the two abstract virtual functions loadTestSession(...) and compareTestSessions(...).
- //please make your own test session class derived from it.
- //
- class LLTestSession
- {
- public:
- virtual ~LLTestSession() ;
- };
-
- //
- //load a test session for log LLSD
- //you need to implement it only when you define your own way to analyze performance.
- //otherwise leave it empty.
- //
- virtual LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) = 0 ;
- //
- //compare the base session and the target session
- //you need to implement it only when you define your own way to analyze performance.
- //otherwise leave it empty.
- //
- virtual void compareTestSessions(std::ofstream* os) = 0 ;
- //
- //the function to write a set of test results to the log LLSD.
- //you have to write you own version of this function.
- //
- virtual void outputTestRecord(LLSD* sd) = 0 ;
-
-private:
- void preOutputTestResults(LLSD* sd) ;
- void postOutputTestResults(LLSD* sd) ;
- void prePerformanceAnalysis() ;
-
-protected:
- //
- //the unique name string of the tester
- //
- std::string mName ;
- //
- //the current label counter for the log LLSD
- //
- std::string mCurLabel ;
- S32 mCount ;
-
- BOOL mUseDefaultPerformanceAnalysis ;
- LLTestSession* mBaseSessionp ;
- LLTestSession* mCurrentSessionp ;
-
- //metrics strings
- std::vector< std::string > mMetricStrings ;
-
-//static members
-private:
- static void addTester(LLMetricPerformanceTester* tester) ;
-
-public:
- typedef std::map< std::string, LLMetricPerformanceTester* > name_tester_map_t;
- static name_tester_map_t sTesterMap ;
-
- static LLMetricPerformanceTester* getTester(std::string label) ;
- static BOOL hasMetricPerformanceTesters() {return !sTesterMap.empty() ;}
-
- static void initClass() ;
- static void cleanClass() ;
-};
-
-#endif
-
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 6658e1d7e8..89d551f129 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -94,6 +94,7 @@ BOOL LLFloaterMove::postBuild()
{
setIsChrome(TRUE);
setTitleVisible(TRUE); // restore title visibility after chrome applying
+ updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
LLDockableFloater::postBuild();
@@ -552,7 +553,7 @@ LLPanelStandStopFlying::LLPanelStandStopFlying() :
}
// static
-inline LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
+LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
{
static LLPanelStandStopFlying* panel = getStandStopFlyingPanel();
return panel;
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 180695e40b..572eeb8fc7 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -365,3 +365,16 @@ BOOL LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)
mChatHistory->setFocus(TRUE);
return LLDockableFloater::handleMouseDown(x, y, mask);
}
+
+void LLNearbyChat::draw()
+{
+ // *HACK: Update transparency type depending on whether our children have focus.
+ // This is needed because this floater is chrome and thus cannot accept focus, so
+ // the transparency type setting code from LLFloater::setFocus() isn't reached.
+ if (getTransparencyType() != TT_DEFAULT)
+ {
+ setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);
+ }
+
+ LLDockableFloater::draw();
+}
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index 1e62910385..2ea79797f8 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -48,6 +48,7 @@ public:
bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual void draw();
// focus overrides
/*virtual*/ void onFocusLost();
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 47d32e57fb..dfbbaa0941 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -64,6 +64,18 @@ public:
LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id)
{
mStopProcessing = false;
+
+ LLControlVariable* ctrl = gSavedSettings.getControl("NearbyToastLifeTime").get();
+ if (ctrl)
+ {
+ ctrl->getSignal()->connect(boost::bind(&LLNearbyChatScreenChannel::updateToastsLifetime, this));
+ }
+
+ ctrl = gSavedSettings.getControl("NearbyToastFadingTime").get();
+ if (ctrl)
+ {
+ ctrl->getSignal()->connect(boost::bind(&LLNearbyChatScreenChannel::updateToastFadingTime, this));
+ }
}
void addNotification (LLSD& notification);
@@ -109,13 +121,26 @@ protected:
if (!toast) return;
LL_DEBUGS("NearbyChat") << "Pooling toast" << llendl;
toast->setVisible(FALSE);
- toast->stopTimer();
+ toast->stopFading();
toast->setIsHidden(true);
+
+ // Nearby chat toasts that are hidden, not destroyed. They are collected to the toast pool, so that
+ // they can be used next time, this is done for performance. But if the toast lifetime was changed
+ // (from preferences floater (STORY-36)) while it was shown (at this moment toast isn't in the pool yet)
+ // changes don't take affect.
+ // So toast's lifetime should be updated each time it's added to the pool. Otherwise viewer would have
+ // to be restarted so that changes take effect.
+ toast->setLifetime(gSavedSettings.getS32("NearbyToastLifeTime"));
+ toast->setFadingTime(gSavedSettings.getS32("NearbyToastFadingTime"));
m_toast_pool.push_back(toast->getHandle());
}
void createOverflowToast(S32 bottom, F32 timer);
+ void updateToastsLifetime();
+
+ void updateToastFadingTime();
+
create_toast_panel_callback_t m_create_toast_panel_callback_t;
bool createPoolToast();
@@ -140,11 +165,20 @@ public:
: LLToast(p),
mNearbyChatScreenChannelp(nc_channelp)
{
+ updateTransparency();
+ setMouseEnterCallback(boost::bind(&LLNearbyChatToast::updateTransparency, this));
+ setMouseLeaveCallback(boost::bind(&LLNearbyChatToast::updateTransparency, this));
}
/*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void setBackgroundOpaque(BOOL b);
+
+protected:
+ /*virtual*/ void setTransparentState(bool transparent);
private:
+ void updateTransparency();
+
LLNearbyChatScreenChannel* mNearbyChatScreenChannelp;
};
@@ -205,6 +239,27 @@ void LLNearbyChatScreenChannel::onToastFade(LLToast* toast)
arrangeToasts();
}
+void LLNearbyChatScreenChannel::updateToastsLifetime()
+{
+ S32 seconds = gSavedSettings.getS32("NearbyToastLifeTime");
+ toast_list_t::iterator it;
+
+ for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it)
+ {
+ (*it).get()->setLifetime(seconds);
+ }
+}
+
+void LLNearbyChatScreenChannel::updateToastFadingTime()
+{
+ S32 seconds = gSavedSettings.getS32("NearbyToastFadingTime");
+ toast_list_t::iterator it;
+
+ for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it)
+ {
+ (*it).get()->setFadingTime(seconds);
+ }
+}
bool LLNearbyChatScreenChannel::createPoolToast()
{
@@ -250,7 +305,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
{
panel->addMessage(notification);
toast->reshapeToPanel();
- toast->resetTimer();
+ toast->startFading();
arrangeToasts();
return;
@@ -295,7 +350,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
panel->init(notification);
toast->reshapeToPanel();
- toast->resetTimer();
+ toast->startFading();
m_active_toasts.push_back(toast->getHandle());
@@ -325,9 +380,9 @@ void LLNearbyChatScreenChannel::arrangeToasts()
int sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second)
{
- F32 v1 = first.get()->getTimer()->getEventTimer().getElapsedTimeF32();
- F32 v2 = second.get()->getTimer()->getEventTimer().getElapsedTimeF32();
- return v1 < v2;
+ F32 v1 = first.get()->getTimeLeftToLive();
+ F32 v2 = second.get()->getTimeLeftToLive();
+ return v1 > v2;
}
void LLNearbyChatScreenChannel::showToastsBottom()
@@ -551,4 +606,34 @@ void LLNearbyChatToast::onClose(bool app_quitting)
mNearbyChatScreenChannelp->onToastDestroyed(this, app_quitting);
}
+// virtual
+void LLNearbyChatToast::setBackgroundOpaque(BOOL b)
+{
+ // We don't want background changes: transparency is handled differently.
+ LLToast::setBackgroundOpaque(TRUE);
+}
+
+// virtual
+void LLNearbyChatToast::setTransparentState(bool transparent)
+{
+ LLToast::setTransparentState(transparent);
+ updateTransparency();
+}
+
+void LLNearbyChatToast::updateTransparency()
+{
+ ETypeTransparency transparency_type;
+
+ if (isHovered())
+ {
+ transparency_type = TT_ACTIVE;
+ }
+ else
+ {
+ transparency_type = getTransparentState() ? TT_FADING : TT_INACTIVE;
+ }
+
+ LLFloater::updateTransparency(transparency_type);
+}
+
// EOF
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index 650bce0da4..e053b1c177 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -38,6 +38,7 @@ class LLColor4U;
class LLCoordGL;
class LLImageRaw;
class LLViewerTexture;
+class LLFloaterMap;
class LLNetMap : public LLUICtrl
{
@@ -55,6 +56,7 @@ public:
protected:
LLNetMap (const Params & p);
friend class LLUICtrlFactory;
+ friend class LLFloaterMap;
public:
virtual ~LLNetMap();
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index db9d386b6b..6435126fc0 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -38,9 +38,11 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "lllistcontextmenu.h"
+#include "llmenubutton.h"
#include "llnotificationsutil.h"
#include "lloutfitobserver.h"
#include "llsidetray.h"
+#include "lltoggleablemenu.h"
#include "lltransutil.h"
#include "llviewermenu.h"
#include "llvoavatar.h"
@@ -113,7 +115,7 @@ public:
registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this));
registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this));
registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this));
- registrar.add("Gear.Delete", boost::bind(&LLOutfitListGearMenu::onDelete, this));
+ registrar.add("Gear.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList));
registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2));
registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this));
@@ -121,23 +123,11 @@ public:
enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2));
enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2));
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
- void show(LLView* spawning_view)
- {
- if (!mMenu) return;
-
- updateItemsVisibility();
- mMenu->buildDrawLabels();
- mMenu->updateParent(LLMenuGL::sMenuContainer);
- S32 menu_x = 0;
- S32 menu_y = spawning_view->getRect().getHeight() + mMenu->getRect().getHeight();
- LLMenuGL::showPopup(spawning_view, mMenu, menu_x, menu_y);
- }
-
void updateItemsVisibility()
{
if (!mMenu) return;
@@ -148,6 +138,8 @@ public:
mMenu->arrangeAndClear(); // update menu height
}
+ LLToggleableMenu* getMenu() { return mMenu; }
+
private:
const LLUUID& getSelectedOutfitID()
{
@@ -205,15 +197,6 @@ private:
}
}
- void onDelete()
- {
- const LLUUID& selected_outfit_id = getSelectedOutfitID();
- if (selected_outfit_id.notNull())
- {
- remove_category(&gInventory, selected_outfit_id);
- }
- }
-
void onCreate(const LLSD& data)
{
LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
@@ -260,14 +243,20 @@ private:
return true;
}
- LLOutfitsList* mOutfitList;
- LLMenuGL* mMenu;
+ LLOutfitsList* mOutfitList;
+ LLToggleableMenu* mMenu;
};
//////////////////////////////////////////////////////////////////////////
class LLOutfitContextMenu : public LLListContextMenu
{
+public:
+
+ LLOutfitContextMenu(LLOutfitsList* outfit_list)
+ : LLListContextMenu(),
+ mOutfitList(outfit_list)
+ {}
protected:
/* virtual */ LLContextMenu* createMenu()
{
@@ -283,7 +272,7 @@ protected:
boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id));
registrar.add("Outfit.Edit", boost::bind(editOutfit));
registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
- registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id));
+ registrar.add("Outfit.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList));
enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2));
@@ -346,10 +335,8 @@ protected:
LLAppearanceMgr::instance().renameOutfit(outfit_cat_id);
}
- static void deleteOutfit(const LLUUID& outfit_cat_id)
- {
- remove_category(&gInventory, outfit_cat_id);
- }
+private:
+ LLOutfitsList* mOutfitList;
};
//////////////////////////////////////////////////////////////////////////
@@ -366,7 +353,7 @@ LLOutfitsList::LLOutfitsList()
mCategoriesObserver = new LLInventoryCategoriesObserver();
mGearMenu = new LLOutfitListGearMenu(this);
- mOutfitMenu = new LLOutfitContextMenu();
+ mOutfitMenu = new LLOutfitContextMenu(this);
}
LLOutfitsList::~LLOutfitsList()
@@ -386,6 +373,11 @@ BOOL LLOutfitsList::postBuild()
mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");
mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
+ LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
+
+ menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenu::updateItemsVisibility, mGearMenu));
+ menu_gear_btn->setMenu(mGearMenu->getMenu());
+
return TRUE;
}
@@ -638,6 +630,14 @@ void LLOutfitsList::performAction(std::string action)
void LLOutfitsList::removeSelected()
{
+ LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitsList::onOutfitsRemovalConfirmation, this, _1, _2));
+}
+
+void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return; // canceled
+
if (mSelectedOutfitUUID.notNull())
{
remove_category(&gInventory, mSelectedOutfitUUID);
@@ -727,13 +727,6 @@ bool LLOutfitsList::isActionEnabled(const LLSD& userdata)
return false;
}
-// virtual
-void LLOutfitsList::showGearMenu(LLView* spawning_view)
-{
- if (!mGearMenu) return;
- mGearMenu->show(spawning_view);
-}
-
void LLOutfitsList::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const
{
// Collect selected items from all selected lists.
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index f73ae5bef2..a0598737f1 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -94,8 +94,6 @@ public:
/*virtual*/ bool isActionEnabled(const LLSD& userdata);
- /*virtual*/ void showGearMenu(LLView* spawning_view);
-
const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; }
/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const;
@@ -112,6 +110,8 @@ public:
private:
+ void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
+
/**
* Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference
*/
diff --git a/indra/newview/llpanelappearancetab.h b/indra/newview/llpanelappearancetab.h
index 81366c5db4..2ed6b00497 100644
--- a/indra/newview/llpanelappearancetab.h
+++ b/indra/newview/llpanelappearancetab.h
@@ -39,8 +39,6 @@ public:
virtual bool isActionEnabled(const LLSD& userdata) = 0;
- virtual void showGearMenu(LLView* spawning_view) = 0;
-
virtual void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const {}
static const std::string& getFilterSubString() { return sFilterSubString; }
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 80df420a4e..ec340dc258 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -692,7 +692,8 @@ void LLPanelGroupGeneral::updateMembers()
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
if (!mListVisibleMembers || !gdatap
- || !gdatap->isMemberDataComplete())
+ || !gdatap->isMemberDataComplete()
+ || gdatap->mMembers.empty())
{
return;
}
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 35f898bfa6..d1362d7922 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -49,6 +49,7 @@
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
+#include "llviewercontrol.h"
#include "roles_constants.h"
@@ -742,10 +743,12 @@ LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
mHasMatch(FALSE),
mNumOwnerAdditions(0)
{
+ mUdpateSessionID = LLUUID::null;
}
LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
{
+ gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName());
}
BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
@@ -772,6 +775,17 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
// Show the member's profile on double click.
mMembersList->setDoubleClickCallback(onMemberDoubleClick, this);
mMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+
+ LLSD row;
+ row["columns"][0]["column"] = "name";
+ row["columns"][1]["column"] = "donated";
+ row["columns"][2]["column"] = "online";
+ mMembersList->addElement(row);
+ std::string order_by = gSavedSettings.getString("GroupMembersSortOrder");
+ if(!order_by.empty())
+ {
+ mMembersList->sortByColumn(order_by, TRUE);
+ }
LLButton* button = parent->getChild<LLButton>("member_invite", recurse);
if ( button )
@@ -1529,6 +1543,10 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
mMemberProgress = gdatap->mMembers.begin();
mPendingMemberUpdate = TRUE;
mHasMatch = FALSE;
+ // Generate unique ID for current updateMembers()- see onNameCache for details.
+ // Using unique UUID is perhaps an overkill but this way we are perfectly safe
+ // from coincidences.
+ mUdpateSessionID.generate();
}
else
{
@@ -1556,6 +1574,63 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
}
}
+void LLPanelGroupMembersSubTab::addMemberToList(LLUUID id, LLGroupMemberData* data)
+{
+ if (!data) return;
+ LLUIString donated = getString("donation_area");
+ donated.setArg("[AREA]", llformat("%d", data->getContribution()));
+
+ LLSD row;
+ row["id"] = id;
+
+ row["columns"][0]["column"] = "name";
+ // value is filled in by name list control
+
+ row["columns"][1]["column"] = "donated";
+ row["columns"][1]["value"] = donated.getString();
+
+ row["columns"][2]["column"] = "online";
+ row["columns"][2]["value"] = data->getOnlineStatus();
+ row["columns"][2]["font"] = "SANSSERIF_SMALL";
+
+ mMembersList->addElement(row);
+
+ mHasMatch = TRUE;
+}
+
+void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, const LLUUID& id)
+{
+ // Update ID is used to determine whether member whose id is passed
+ // into onNameCache() was passed after current or previous user-initiated update.
+ // This is needed to avoid probable duplication of members in list after changing filter
+ // or adding of members of another group if gets for their names were called on
+ // previous update. If this id is from get() called from older update,
+ // we do nothing.
+ if (mUdpateSessionID != update_id) return;
+
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if (!gdatap)
+ {
+ llwarns << "LLPanelGroupMembersSubTab::updateMembers() -- No group data!" << llendl;
+ return;
+ }
+
+ std::string fullname;
+ gCacheName->getFullName(id, fullname);
+
+ LLGroupMemberData* data;
+ // trying to avoid unnecessary hash lookups
+ if (matchesSearchFilter(fullname) && ((data = gdatap->mMembers[id]) != NULL))
+ {
+ addMemberToList(id, data);
+ if(!mMembersList->getEnabled())
+ {
+ mMembersList->setEnabled(TRUE);
+ }
+ }
+
+}
+
void LLPanelGroupMembersSubTab::updateMembers()
{
mPendingMemberUpdate = FALSE;
@@ -1580,12 +1655,13 @@ void LLPanelGroupMembersSubTab::updateMembers()
//cleanup list only for first iretation
if(mMemberProgress == gdatap->mMembers.begin())
+ {
mMembersList->deleteAllItems();
+ }
LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
- LLUIString donated = getString("donation_area");
-
+
S32 i = 0;
for( ; mMemberProgress != end && i<UPDATE_MEMBERS_PER_FRAME;
++mMemberProgress, ++i)
@@ -1593,38 +1669,19 @@ void LLPanelGroupMembersSubTab::updateMembers()
if (!mMemberProgress->second)
continue;
// Do filtering on name if it is already in the cache.
- bool add_member = true;
-
std::string fullname;
if (gCacheName->getFullName(mMemberProgress->first, fullname))
{
- if ( !matchesSearchFilter(fullname) )
+ if (matchesSearchFilter(fullname))
{
- add_member = false;
+ addMemberToList(mMemberProgress->first, mMemberProgress->second);
}
}
-
- if (add_member)
+ else
{
- donated.setArg("[AREA]", llformat("%d", mMemberProgress->second->getContribution()));
-
- LLSD row;
- row["id"] = (*mMemberProgress).first;
-
- row["columns"][0]["column"] = "name";
- // value is filled in by name list control
-
- row["columns"][1]["column"] = "donated";
- row["columns"][1]["value"] = donated.getString();
-
- row["columns"][2]["column"] = "online";
- row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
- row["columns"][2]["font"] = "SANSSERIF_SMALL";
-
- LLScrollListItem* member = mMembersList->addElement(row);
-
- LLUUID id = member->getUUID();
- mHasMatch = TRUE;
+ // If name is not cached, onNameCache() should be called when it is cached and add this member to list.
+ gCacheName->get(mMemberProgress->first, FALSE, boost::bind(&LLPanelGroupMembersSubTab::onNameCache,
+ this, mUdpateSessionID, _1));
}
}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 6a773f1ebb..270259c16f 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -187,6 +187,9 @@ public:
virtual void setGroupID(const LLUUID& id);
+ void addMemberToList(LLUUID id, LLGroupMemberData* data);
+ void onNameCache(const LLUUID& update_id, const LLUUID& id);
+
protected:
typedef std::map<LLUUID, LLRoleMemberChangeType> role_change_data_map_t;
typedef std::map<LLUUID, role_change_data_map_t*> member_role_changes_map_t;
@@ -207,6 +210,9 @@ protected:
BOOL mPendingMemberUpdate;
BOOL mHasMatch;
+ // This id is generated after each user initiated member list update(opening Roles or changing filter)
+ LLUUID mUdpateSessionID;
+
member_role_changes_map_t mMemberRoleChangeData;
U32 mNumOwnerAdditions;
diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
index 87acd83b23..c57746ec00 100644
--- a/indra/newview/llpanellandmarkinfo.cpp
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -180,6 +180,9 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
populateFoldersList();
+ // Prevent the floater from losing focus (if the sidepanel is undocked).
+ setFocus(TRUE);
+
LLPanelPlaceInfo::setInfoType(type);
}
@@ -330,6 +333,9 @@ void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled)
// when it was enabled/disabled we set the text once again.
mNotesEditor->setText(mNotesEditor->getText());
}
+
+ // Prevent the floater from losing focus (if the sidepanel is undocked).
+ setFocus(TRUE);
}
const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index c4a484d368..e8c8273a9d 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -47,9 +47,11 @@
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
#include "lllandmarkactions.h"
+#include "llmenubutton.h"
#include "llplacesinventorybridge.h"
#include "llplacesinventorypanel.h"
#include "llsidetray.h"
+#include "lltoggleablemenu.h"
#include "llviewermenu.h"
#include "llviewerregion.h"
@@ -191,6 +193,7 @@ LLLandmarksPanel::LLLandmarksPanel()
, mLibraryInventoryPanel(NULL)
, mCurrentSelectedList(NULL)
, mListCommands(NULL)
+ , mGearButton(NULL)
, mGearFolderMenu(NULL)
, mGearLandmarkMenu(NULL)
{
@@ -517,9 +520,6 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
{
if (!parcel_id.isNull())
{
- //ext-4655, defensive. remove now incase this gets called twice without a remove
- LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_id, this);
-
LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
}
@@ -685,7 +685,9 @@ void LLLandmarksPanel::initListCommandsHandlers()
{
mListCommands = getChild<LLPanel>("bottom_panel");
- mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
+ mGearButton = getChild<LLMenuButton>(OPTIONS_BUTTON_NAME);
+ mGearButton->setMouseDownCallback(boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
+
mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
@@ -702,8 +704,8 @@ void LLLandmarksPanel::initListCommandsHandlers()
mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
- mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME));
@@ -722,7 +724,7 @@ void LLLandmarksPanel::updateListCommands()
void LLLandmarksPanel::onActionsButtonClick()
{
- LLMenuGL* menu = mGearFolderMenu;
+ LLToggleableMenu* menu = mGearFolderMenu;
LLFolderViewItem* cur_item = NULL;
if(mCurrentSelectedList)
@@ -741,7 +743,7 @@ void LLLandmarksPanel::onActionsButtonClick()
}
}
- showActionMenu(menu,OPTIONS_BUTTON_NAME);
+ mGearButton->setMenu(menu);
}
void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
@@ -750,7 +752,10 @@ void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_
{
menu->buildDrawLabels();
menu->updateParent(LLMenuGL::sMenuContainer);
- LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ menu->arrangeAndClear();
+
+ LLView* spawning_view = getChild<LLView>(spawning_view_name);
+
S32 menu_x, menu_y;
//show menu in co-ordinates of panel
spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 0d4402d8cb..8dcbca0440 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -39,7 +39,9 @@
class LLAccordionCtrlTab;
class LLFolderViewItem;
+class LLMenuButton;
class LLMenuGL;
+class LLToggleableMenu;
class LLInventoryPanel;
class LLPlacesInventoryPanel;
@@ -155,8 +157,9 @@ private:
LLPlacesInventoryPanel* mLandmarksInventoryPanel;
LLPlacesInventoryPanel* mMyInventoryPanel;
LLPlacesInventoryPanel* mLibraryInventoryPanel;
- LLMenuGL* mGearLandmarkMenu;
- LLMenuGL* mGearFolderMenu;
+ LLMenuButton* mGearButton;
+ LLToggleableMenu* mGearLandmarkMenu;
+ LLToggleableMenu* mGearFolderMenu;
LLMenuGL* mMenuAdd;
LLPlacesInventoryPanel* mCurrentSelectedList;
LLInventoryObserver* mInventoryObserver;
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 467aefc60f..cf567fb208 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -230,7 +230,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
getChild<LLPanel>("login")->setDefaultBtn("connect_btn");
- std::string channel = gSavedSettings.getString("VersionChannelName");
+ std::string channel = LLVersionInfo::getChannel();
std::string version = llformat("%s (%d)",
LLVersionInfo::getShortVersion().c_str(),
LLVersionInfo::getBuild());
@@ -817,7 +817,7 @@ void LLPanelLogin::loadLoginPage()
LLVersionInfo::getShortVersion().c_str(),
LLVersionInfo::getBuild());
- char* curl_channel = curl_escape(gSavedSettings.getString("VersionChannelName").c_str(), 0);
+ char* curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);
char* curl_version = curl_escape(version.c_str(), 0);
oStr << "&channel=" << curl_channel;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 5b07e4863b..17433a557b 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -39,12 +39,14 @@
#include "llinventorypanel.h"
#include "llfiltereditor.h"
#include "llfloaterreg.h"
+#include "llmenubutton.h"
#include "lloutfitobserver.h"
#include "llpreviewtexture.h"
#include "llresmgr.h"
#include "llscrollcontainer.h"
#include "llsdserialize.h"
#include "llspinctrl.h"
+#include "lltoggleablemenu.h"
#include "lltooldraganddrop.h"
#include "llviewermenu.h"
#include "llviewertexturelist.h"
@@ -192,6 +194,8 @@ BOOL LLPanelMainInventory::postBuild()
mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2));
}
+ mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
+
initListCommandsHandlers();
// *TODO:Get the cost info from the server
@@ -325,15 +329,23 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
if (sort_field == "name")
{
U32 order = getActivePanel()->getSortOrder();
- getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
-
+ order &= ~LLInventoryFilter::SO_DATE;
+
+ getActivePanel()->setSortOrder( order );
+
+ gSavedSettings.setU32("InventorySortOrder", order);
+
gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
}
else if (sort_field == "date")
{
U32 order = getActivePanel()->getSortOrder();
- getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
+ order |= LLInventoryFilter::SO_DATE;
+
+ getActivePanel()->setSortOrder( order );
+
+ gSavedSettings.setU32("InventorySortOrder", order);
gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
@@ -371,6 +383,8 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
}
getActivePanel()->setSortOrder( order );
+
+ gSavedSettings.setU32("InventorySortOrder", order);
}
}
@@ -900,7 +914,6 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
void LLPanelMainInventory::initListCommandsHandlers()
{
- childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
@@ -912,8 +925,10 @@ void LLPanelMainInventory::initListCommandsHandlers()
));
mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
- mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearMenuButton->setMenu(mMenuGearDefault);
mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
// Update the trash button when selected item(s) get worn or taken off.
@@ -927,11 +942,6 @@ void LLPanelMainInventory::updateListCommands()
mTrashButton->setEnabled(trash_enabled);
}
-void LLPanelMainInventory::onGearButtonClick()
-{
- showActionMenu(mMenuGearDefault,"options_gear_btn");
-}
-
void LLPanelMainInventory::onAddButtonClick()
{
setUploadCostIfNeeded();
@@ -1001,6 +1011,11 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
const LLSD arg = "date";
setSortBy(arg);
}
+ if (command_name == "sort_system_folders_to_top")
+ {
+ const LLSD arg = "systemfolderstotop";
+ setSortBy(arg);
+ }
if (command_name == "show_filters")
{
toggleFindOptions();
@@ -1174,6 +1189,31 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
return TRUE;
}
+BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+
+ if (command_name == "sort_by_name")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ return ~order & LLInventoryFilter::SO_DATE;
+ }
+
+ if (command_name == "sort_by_recent")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ return order & LLInventoryFilter::SO_DATE;
+ }
+
+ if (command_name == "sort_system_folders_to_top")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ return order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+ }
+
+ return FALSE;
+}
+
bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
{
*accept = ACCEPT_NO;
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index cf2cc14531..c2b78ff9ea 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -40,7 +40,9 @@ class LLSaveFolderState;
class LLFilterEditor;
class LLTabContainer;
class LLFloaterInventoryFinder;
+class LLMenuButton;
class LLMenuGL;
+class LLToggleableMenu;
class LLFloater;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -129,12 +131,12 @@ private:
protected:
void initListCommandsHandlers();
void updateListCommands();
- void onGearButtonClick();
void onAddButtonClick();
void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
void onTrashButtonClick();
void onClipboardAction(const LLSD& userdata);
BOOL isActionEnabled(const LLSD& command_name);
+ BOOL isActionChecked(const LLSD& userdata);
void onCustomAction(const LLSD& command_name);
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
/**
@@ -143,8 +145,9 @@ protected:
void setUploadCostIfNeeded();
private:
LLDragAndDropButton* mTrashButton;
- LLMenuGL* mMenuGearDefault;
+ LLToggleableMenu* mMenuGearDefault;
LLMenuGL* mMenuAdd;
+ LLMenuButton* mGearMenuButton;
bool mNeedUploadCost;
// List Commands //
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index d756a1b931..a0c320ba19 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -1695,10 +1695,10 @@ void LLPanelObject::sendPosition(BOOL btn_down)
LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
LLViewerRegion* regionp = mObject->getRegion();
-
+
// Clamp the Z height
const F32 height = newpos.mV[VZ];
- const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject);
+ const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal());
const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight();
if (!mObject->isAttachment())
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 408d4f29b7..ce9b1c66d7 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -56,11 +56,13 @@
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llloadingindicator.h"
+#include "llmenubutton.h"
#include "llpaneloutfitsinventory.h"
#include "lluiconstants.h"
#include "llsaveoutfitcombobtn.h"
#include "llscrolllistctrl.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llsdutil.h"
@@ -151,13 +153,13 @@ std::string LLShopURLDispatcher::resolveURL(LLAssetType::EType asset_type, ESex
class LLPanelOutfitEditGearMenu
{
public:
- static LLMenuGL* create()
+ static LLToggleableMenu* create()
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("Wearable.Create", boost::bind(onCreate, _2));
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_cof_gear.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(menu);
if (menu)
@@ -218,7 +220,7 @@ private:
class LLAddWearablesGearMenu : public LLInitClass<LLAddWearablesGearMenu>
{
public:
- static LLMenuGL* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel)
+ static LLToggleableMenu* create(LLWearableItemsList* flat_list, LLInventoryPanel* inventory_panel)
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
@@ -233,7 +235,7 @@ public:
enable_registrar.add("AddWearable.Gear.Check", boost::bind(onCheck, flat_list_handle, inventory_panel_handle, _2));
enable_registrar.add("AddWearable.Gear.Visible", boost::bind(onVisible, inventory_panel_handle, _2));
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_add_wearable_gear.xml",
LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
@@ -404,7 +406,9 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
mFolderViewFilterCmbBox(NULL),
mListViewFilterCmbBox(NULL),
mWearableListManager(NULL),
- mPlusBtn(NULL)
+ mPlusBtn(NULL),
+ mWearablesGearMenuBtn(NULL),
+ mGearMenuBtn(NULL)
{
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
@@ -480,13 +484,14 @@ BOOL LLPanelOutfitEdit::postBuild()
childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);
childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);
childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::saveListSelection, this), NULL);
- childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
- childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);
childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);
childSetCommitCallback("shop_btn_2", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL);
setVisibleCallback(boost::bind(&LLPanelOutfitEdit::onVisibilityChange, this, _2));
+ mWearablesGearMenuBtn = getChild<LLMenuButton>("wearables_gear_menu_btn");
+ mGearMenuBtn = getChild<LLMenuButton>("gear_menu_btn");
+
mCOFWearables = findChild<LLCOFWearables>("cof_wearables_list");
mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, this));
@@ -559,6 +564,13 @@ BOOL LLPanelOutfitEdit::postBuild()
mWearableItemsList->setComparator(mWearableListViewItemsComparator);
+ // Creating "Add Wearables" panel gear menu after initialization of mWearableItemsList and mInventoryItemsPanel.
+ mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel);
+ mWearablesGearMenuBtn->setMenu(mAddWearablesGearMenu);
+
+ mGearMenu = LLPanelOutfitEditGearMenu::create();
+ mGearMenuBtn->setMenu(mGearMenu);
+
mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this));
return TRUE;
}
@@ -1258,37 +1270,6 @@ void LLPanelOutfitEdit::resetAccordionState()
}
}
-void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)
-{
- LLMenuGL* menu = NULL;
-
- if (mAddWearablesPanel->getVisible())
- {
- if (!mAddWearablesGearMenu)
- {
- mAddWearablesGearMenu = LLAddWearablesGearMenu::create(mWearableItemsList, mInventoryItemsPanel);
- }
-
- menu = mAddWearablesGearMenu;
- }
- else
- {
- if (!mGearMenu)
- {
- mGearMenu = LLPanelOutfitEditGearMenu::create();
- }
-
- menu = mGearMenu;
- }
-
- if (!menu) return;
-
- menu->arrangeAndClear(); // update menu height
- S32 menu_y = menu->getRect().getHeight() + clicked_button->getRect().getHeight();
- menu->buildDrawLabels();
- LLMenuGL::showPopup(clicked_button, menu, 0, menu_y);
-}
-
void LLPanelOutfitEdit::onAddMoreButtonClicked()
{
toggleAddWearablesPanel();
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 2dca986e33..fd366e9cbc 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -54,6 +54,7 @@ class LLScrollListCtrl;
class LLToggleableMenu;
class LLFilterEditor;
class LLFilteredWearableListManager;
+class LLMenuButton;
class LLMenuGL;
class LLFindNonLinksByMask;
class LLFindWearablesOfType;
@@ -186,8 +187,6 @@ public:
std::string& tooltip_msg);
private:
-
- void onGearButtonClick(LLUICtrl* clicked_button);
void onAddMoreButtonClicked();
void showFilteredWearablesListView(LLWearableType::EType type);
void onOutfitChanging(bool started);
@@ -234,12 +233,12 @@ private:
std::vector<LLFilterItem*> mListViewItemTypes;
LLCOFWearables* mCOFWearables;
- LLMenuGL* mGearMenu;
- LLMenuGL* mAddWearablesGearMenu;
+ LLToggleableMenu* mGearMenu;
+ LLToggleableMenu* mAddWearablesGearMenu;
bool mInitialized;
std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn;
-
-
+ LLMenuButton* mWearablesGearMenuBtn;
+ LLMenuButton* mGearMenuBtn;
};
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index d6d8a38ebe..a90f864ae2 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -232,9 +232,7 @@ void LLPanelOutfitsInventory::initListCommandsHandlers()
{
mListCommands = getChild<LLPanel>("bottom_panel");
mListCommands->childSetAction("wear_btn", boost::bind(&LLPanelOutfitsInventory::onWearButtonClick, this));
- mMyOutfitsPanel->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::showGearMenu, this));
mMyOutfitsPanel->childSetAction("trash_btn", boost::bind(&LLPanelOutfitsInventory::onTrashButtonClick, this));
- mCurrentOutfitPanel->childSetAction("options_gear_btn", boost::bind(&LLPanelOutfitsInventory::showGearMenu, this));
}
void LLPanelOutfitsInventory::updateListCommands()
@@ -258,27 +256,9 @@ void LLPanelOutfitsInventory::updateListCommands()
}
}
-void LLPanelOutfitsInventory::showGearMenu()
-{
- if (!mActivePanel) return;
-
- LLView* spawning_view = getChild<LLView>("options_gear_btn");
- mActivePanel->showGearMenu(spawning_view);
-}
-
void LLPanelOutfitsInventory::onTrashButtonClick()
{
- LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLPanelOutfitsInventory::onOutfitsRemovalConfirmation, this, _1, _2));
-}
-
-void LLPanelOutfitsInventory::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (option != 0) return; // canceled
-
mMyOutfitsPanel->removeSelected();
- updateListCommands();
- updateVerbs();
}
bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h
index f1ca1dbfeb..a7917b457c 100644
--- a/indra/newview/llpaneloutfitsinventory.h
+++ b/indra/newview/llpaneloutfitsinventory.h
@@ -89,7 +89,6 @@ protected:
void onWearButtonClick();
void showGearMenu();
void onTrashButtonClick();
- void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
bool isActionEnabled(const LLSD& userdata);
void setWearablesLoading(bool val);
void onWearablesLoaded();
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 040b5319b9..9e9bc5fc1a 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -29,11 +29,13 @@
// libs
#include "llavatarname.h"
#include "llfloaterreg.h"
+#include "llmenubutton.h"
#include "llmenugl.h"
#include "llnotificationsutil.h"
#include "lleventtimer.h"
#include "llfiltereditor.h"
#include "lltabcontainer.h"
+#include "lltoggleablemenu.h"
#include "lluictrlfactory.h"
#include "llpanelpeople.h"
@@ -464,7 +466,11 @@ LLPanelPeople::LLPanelPeople()
mAllFriendList(NULL),
mNearbyList(NULL),
mRecentList(NULL),
- mGroupList(NULL)
+ mGroupList(NULL),
+ mNearbyGearButton(NULL),
+ mFriendsGearButton(NULL),
+ mGroupsGearButton(NULL),
+ mRecentGearButton(NULL)
{
mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this));
mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this));
@@ -600,11 +606,6 @@ BOOL LLPanelPeople::postBuild()
buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this));
buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this));
- getChild<LLPanel>(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this));
- getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this));
- getChild<LLPanel>(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this));
- getChild<LLPanel>(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this));
-
// Must go after setting commit callback and initializing all pointers to children.
mTabContainer->selectTabByName(NEARBY_TAB_NAME);
@@ -624,24 +625,41 @@ BOOL LLPanelPeople::postBuild()
enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2));
enable_registrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2));
+ mNearbyGearButton = getChild<LLMenuButton>("nearby_view_sort_btn");
+ mFriendsGearButton = getChild<LLMenuButton>("friends_viewsort_btn");
+ mGroupsGearButton = getChild<LLMenuButton>("groups_viewsort_btn");
+ mRecentGearButton = getChild<LLMenuButton>("recent_viewsort_btn");
+
LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGroupPlusMenuHandle = plus_menu->getHandle();
- LLMenuGL* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* nearby_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_nearby_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(nearby_view_sort)
+ {
mNearbyViewSortMenuHandle = nearby_view_sort->getHandle();
+ mNearbyGearButton->setMenu(nearby_view_sort);
+ }
- LLMenuGL* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* friend_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_friends_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(friend_view_sort)
+ {
mFriendsViewSortMenuHandle = friend_view_sort->getHandle();
+ mFriendsGearButton->setMenu(friend_view_sort);
+ }
- LLMenuGL* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(group_view_sort)
+ {
mGroupsViewSortMenuHandle = group_view_sort->getHandle();
+ mGroupsGearButton->setMenu(group_view_sort);
+ }
- LLMenuGL* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(recent_view_sort)
+ {
mRecentViewSortMenuHandle = recent_view_sort->getHandle();
+ mRecentGearButton->setMenu(recent_view_sort);
+ }
LLVoiceClient::getInstance()->addObserver(this);
@@ -911,7 +929,7 @@ void LLPanelPeople::showGroupMenu(LLMenuGL* menu)
// Calculate its coordinates.
// (assumes that groups panel is the current tab)
- LLPanel* bottom_panel = mTabContainer->getCurrentPanel()->getChild<LLPanel>("bottom_panel");
+ LLPanel* bottom_panel = mTabContainer->getCurrentPanel()->getChild<LLPanel>("bottom_panel");
LLPanel* parent_panel = mTabContainer->getCurrentPanel();
menu->arrangeAndClear();
S32 menu_height = menu->getRect().getHeight();
@@ -1346,44 +1364,9 @@ void LLPanelPeople::onMoreButtonClicked()
// *TODO: not implemented yet
}
-void LLPanelPeople::onFriendsViewSortButtonClicked()
-{
- LLMenuGL* menu = (LLMenuGL*)mFriendsViewSortMenuHandle.get();
- if (!menu)
- return;
- showGroupMenu(menu);
-}
-
-void LLPanelPeople::onGroupsViewSortButtonClicked()
-{
- LLMenuGL* menu = (LLMenuGL*)mGroupsViewSortMenuHandle.get();
- if (!menu)
- return;
- showGroupMenu(menu);
-}
-
-void LLPanelPeople::onRecentViewSortButtonClicked()
-{
- LLMenuGL* menu = (LLMenuGL*)mRecentViewSortMenuHandle.get();
- if (!menu)
- return;
- showGroupMenu(menu);
-}
-
-void LLPanelPeople::onNearbyViewSortButtonClicked()
-{
- LLMenuGL* menu = (LLMenuGL*)mNearbyViewSortMenuHandle.get();
- if (!menu)
- return;
- showGroupMenu(menu);
-}
-
void LLPanelPeople::onOpen(const LLSD& key)
{
std::string tab_name = key["people_panel_tab_name"];
- mFilterEditor -> clear();
- onFilterEdit("");
-
if (!tab_name.empty())
mTabContainer->selectTabByName(tab_name);
}
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index f5ff09b038..4412aed062 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -36,6 +36,7 @@ class LLAvatarList;
class LLAvatarName;
class LLFilterEditor;
class LLGroupList;
+class LLMenuButton;
class LLTabContainer;
class LLPanelPeople
@@ -101,10 +102,6 @@ private:
void onShareButtonClicked();
void onMoreButtonClicked();
void onActivateButtonClicked();
- void onRecentViewSortButtonClicked();
- void onNearbyViewSortButtonClicked();
- void onFriendsViewSortButtonClicked();
- void onGroupsViewSortButtonClicked();
void onAvatarListDoubleClicked(LLUICtrl* ctrl);
void onAvatarListCommitted(LLAvatarList* list);
void onGroupPlusButtonClicked();
@@ -156,6 +153,11 @@ private:
Updater* mNearbyListUpdater;
Updater* mRecentListUpdater;
+ LLMenuButton* mNearbyGearButton;
+ LLMenuButton* mFriendsGearButton;
+ LLMenuButton* mGroupsGearButton;
+ LLMenuButton* mRecentGearButton;
+
std::string mFilterSubString;
std::string mFilterSubStringOrig;
};
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index 271728220c..44cca21a76 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -204,9 +204,6 @@ void LLPanelPickInfo::sendParcelInfoRequest()
{
if (mParcelId != mRequestedId)
{
- //ext-4655, remove now incase this gets called twice without a remove
- LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedId, this);
-
LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this);
LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId);
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index ccef563544..15e826ac2c 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -212,7 +212,8 @@ void LLPanelPicks::updateData()
mNoPicks = false;
mNoClassifieds = false;
- getChild<LLUICtrl>("picks_panel_text")->setValue(LLTrans::getString("PicksClassifiedsLoadingText"));
+ mNoItemsLabel->setValue(LLTrans::getString("PicksClassifiedsLoadingText"));
+ mNoItemsLabel->setVisible(TRUE);
mPicksList->clear();
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
@@ -314,15 +315,17 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
mNoClassifieds = !mClassifiedsList->size();
}
- if (mNoPicks && mNoClassifieds)
+ bool no_data = mNoPicks && mNoClassifieds;
+ mNoItemsLabel->setVisible(no_data);
+ if (no_data)
{
if(getAvatarId() == gAgentID)
{
- getChild<LLUICtrl>("picks_panel_text")->setValue(LLTrans::getString("NoPicksClassifiedsText"));
+ mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText"));
}
else
{
- getChild<LLUICtrl>("picks_panel_text")->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText"));
+ mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText"));
}
}
}
@@ -359,6 +362,8 @@ BOOL LLPanelPicks::postBuild()
mPicksList->setNoItemsCommentText(getString("no_picks"));
mClassifiedsList->setNoItemsCommentText(getString("no_classifieds"));
+ mNoItemsLabel = getChild<LLUICtrl>("picks_panel_text");
+
childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickPlusBtn, this));
childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this));
childSetAction(XML_BTN_TELEPORT, boost::bind(&LLPanelPicks::onClickTeleport, this));
@@ -781,7 +786,7 @@ void LLPanelPicks::showAccordion(const std::string& name, bool show)
void LLPanelPicks::onPanelPickClose(LLPanel* panel)
{
- panel->setVisible(FALSE);
+ getProfilePanel()->closePanel(panel);
}
void LLPanelPicks::onPanelPickSave(LLPanel* panel)
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 526ba48dcb..a02ed81bb0 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -149,6 +149,7 @@ private:
LLPanelClassifiedInfo* mPanelClassifiedInfo;
LLPanelPickEdit* mPanelPickEdit;
LLToggleableMenu* mPlusMenu;
+ LLUICtrl* mNoItemsLabel;
// <classified_id, edit_panel>
typedef std::map<LLUUID, LLPanelClassifiedEdit*> panel_classified_edit_map_t;
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 9cbb512e70..4ae0c0eb12 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -128,10 +128,6 @@ void LLPanelPlaceInfo::sendParcelInfoRequest()
{
if (mParcelID != mRequestedID)
{
- //ext-4655, defensive. remove now incase this gets called twice without a remove
- //as panel never closes its ok atm (but wrong :)
- LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mRequestedID, this);
-
LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 4e63563979..6038ab20d8 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -217,6 +217,10 @@ void LLPanelProfile::setAllChildrenVisible(BOOL visible)
void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params)
{
+ // Hide currently visible panel (STORM-690).
+ setAllChildrenVisible(FALSE);
+
+ // Add the panel or bring it to front.
if (panel->getParent() != this)
{
addChild(panel);
@@ -243,6 +247,18 @@ void LLPanelProfile::closePanel(LLPanel* panel)
if (panel->getParent() == this)
{
removeChild(panel);
+
+ // Make the underlying panel visible.
+ const child_list_t* child_list = getChildList();
+ if (child_list->size() > 0)
+ {
+ child_list->front()->setVisible(TRUE);
+ child_list->front()->setFocus(TRUE); // prevent losing focus by the floater
+ }
+ else
+ {
+ llwarns << "No underlying panel to make visible." << llendl;
+ }
}
}
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 9b8167b15a..fff8ccb912 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "llfloaterreg.h"
+#include "llmenubutton.h"
#include "llfloaterworldmap.h"
#include "llpanelteleporthistory.h"
@@ -40,6 +41,7 @@
#include "llflatlistview.h"
#include "llnotificationsutil.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "llviewermenu.h"
#include "lllandmarkactions.h"
#include "llclipboard.h"
@@ -375,7 +377,8 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
mHistoryAccordion(NULL),
mAccordionTabMenu(NULL),
mLastSelectedFlatlList(NULL),
- mLastSelectedItemIndex(-1)
+ mLastSelectedItemIndex(-1),
+ mMenuGearButton(NULL)
{
buildFromFile( "panel_teleport_history.xml");
}
@@ -439,8 +442,6 @@ BOOL LLTeleportHistoryPanel::postBuild()
}
}
- getChild<LLPanel>("bottom_panel")->childSetAction("gear_btn",boost::bind(&LLTeleportHistoryPanel::onGearButtonClicked, this));
-
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("TeleportHistory.ExpandAllFolders", boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders, this));
@@ -448,9 +449,14 @@ BOOL LLTeleportHistoryPanel::postBuild()
registrar.add("TeleportHistory.ClearTeleportHistory", boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory, this));
mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
- LLMenuGL* gear_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuGearButton = getChild<LLMenuButton>("gear_btn");
+
+ LLToggleableMenu* gear_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());;
if(gear_menu)
+ {
mGearMenuHandle = gear_menu->getHandle();
+ mMenuGearButton->setMenu(gear_menu);
+ }
return TRUE;
}
@@ -985,27 +991,6 @@ LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTa
return NULL;
}
-void LLTeleportHistoryPanel::onGearButtonClicked()
-{
- LLMenuGL* menu = (LLMenuGL*)mGearMenuHandle.get();
- if (!menu)
- return;
-
- // Shows the menu at the top of the button bar.
-
- // Calculate its coordinates.
- LLPanel* bottom_panel = getChild<LLPanel>("bottom_panel");
- menu->arrangeAndClear();
- S32 menu_height = menu->getRect().getHeight();
- S32 menu_x = -2; // *HACK: compensates HPAD in showPopup()
- S32 menu_y = bottom_panel->getRect().mTop + menu_height;
-
- // Actually show the menu.
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
- LLMenuGL::showPopup(this, menu, menu_x, menu_y);
-}
-
bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
{
S32 tabs_cnt = mItemContainers.size();
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index b5a025b39b..3d29454d15 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -38,6 +38,7 @@ class LLTeleportHistoryStorage;
class LLAccordionCtrl;
class LLAccordionCtrlTab;
class LLFlatListView;
+class LLMenuButton;
class LLTeleportHistoryPanel : public LLPanelPlacesTab
{
@@ -94,7 +95,6 @@ private:
void showTeleportHistory();
void handleItemSelect(LLFlatListView* );
LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);
- void onGearButtonClicked();
bool isActionEnabled(const LLSD& userdata) const;
void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
@@ -118,6 +118,7 @@ private:
ContextMenu mContextMenu;
LLContextMenu* mAccordionTabMenu;
LLHandle<LLView> mGearMenuHandle;
+ LLMenuButton* mMenuGearButton;
};
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index 860470cd73..911a9e5dda 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -28,10 +28,13 @@
#include "llpanelwearing.h"
+#include "lltoggleablemenu.h"
+
#include "llappearancemgr.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
+#include "llmenubutton.h"
#include "llsidetray.h"
#include "llviewermenu.h"
#include "llwearableitemslist.h"
@@ -58,21 +61,12 @@ public:
enable_registrar.add("Gear.OnEnable", boost::bind(&LLPanelWearing::isActionEnabled, mPanelWearing, _2));
- mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(
+ mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_wearing_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
- void show(LLView* spawning_view)
- {
- if (!mMenu) return;
-
- mMenu->buildDrawLabels();
- mMenu->updateParent(LLMenuGL::sMenuContainer);
- S32 menu_x = 0;
- S32 menu_y = spawning_view->getRect().getHeight() + mMenu->getRect().getHeight();
- LLMenuGL::showPopup(spawning_view, mMenu, menu_x, menu_y);
- }
+ LLToggleableMenu* getMenu() { return mMenu; }
private:
@@ -87,8 +81,8 @@ private:
}
}
- LLMenuGL* mMenu;
- LLPanelWearing* mPanelWearing;
+ LLToggleableMenu* mMenu;
+ LLPanelWearing* mPanelWearing;
};
//////////////////////////////////////////////////////////////////////////
@@ -189,6 +183,10 @@ BOOL LLPanelWearing::postBuild()
mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list");
mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3));
+ LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
+
+ menu_gear_btn->setMenu(mGearMenu->getMenu());
+
return TRUE;
}
@@ -253,13 +251,6 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata)
return false;
}
-// virtual
-void LLPanelWearing::showGearMenu(LLView* spawning_view)
-{
- if (!mGearMenu) return;
- mGearMenu->show(spawning_view);
-}
-
boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb)
{
if (!mCOFItemsList) return boost::signals2::connection();
diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h
index 1fa97735b1..157b2c4c5f 100644
--- a/indra/newview/llpanelwearing.h
+++ b/indra/newview/llpanelwearing.h
@@ -58,8 +58,6 @@ public:
/*virtual*/ bool isActionEnabled(const LLSD& userdata);
- /*virtual*/ void showGearMenu(LLView* spawning_view);
-
/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const;
boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb);
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 01b3b5572e..54053cf89f 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -197,17 +197,20 @@ private:
uuid_set_t mAvalineCallers;
};
-LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/,
- bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/):
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
+ LLAvatarList* avatar_list,
+ bool use_context_menu/* = true*/,
+ bool exclude_agent /*= true*/,
+ bool can_toggle_icons /*= true*/) :
mSpeakerMgr(data_source),
mAvatarList(avatar_list),
- mSortOrder(E_SORT_BY_NAME)
-, mParticipantListMenu(NULL)
-, mExcludeAgent(exclude_agent)
-, mValidateSpeakerCallback(NULL)
+ mParticipantListMenu(NULL),
+ mExcludeAgent(exclude_agent),
+ mValidateSpeakerCallback(NULL)
{
+
mAvalineUpdater = new LLAvalineUpdater(boost::bind(&LLParticipantList::onAvalineCallerFound, this, _1),
- boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1));
+ boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1));
mSpeakerAddListener = new SpeakerAddListener(*this);
mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
@@ -393,15 +396,15 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
}
/*
-Seems this method is not necessary after onAvalineCallerRemoved was implemented;
+ Seems this method is not necessary after onAvalineCallerRemoved was implemented;
-It does nothing because list item is always created with correct class type for Avaline caller.
-For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client
-session.
-This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call.
+ It does nothing because list item is always created with correct class type for Avaline caller.
+ For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client
+ session.
+ This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call.
-Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself.
-Asked in EXT-4301.
+ Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself.
+ Asked in EXT-4301.
*/
void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id)
{
@@ -443,16 +446,19 @@ void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id)
void LLParticipantList::setSortOrder(EParticipantSortOrder order)
{
- if ( mSortOrder != order )
+ const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
+
+ if ( speaker_sort_order != order )
{
- mSortOrder = order;
+ gSavedSettings.setU32("SpeakerParticipantDefaultOrder", (U32)order);
sort();
}
}
-LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
+const LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() const
{
- return mSortOrder;
+ const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
+ return EParticipantSortOrder(speaker_sort_order);
}
void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb)
@@ -551,28 +557,29 @@ void LLParticipantList::sort()
if ( !mAvatarList )
return;
- switch ( mSortOrder ) {
- case E_SORT_BY_NAME :
- // if mExcludeAgent == true , then no need to keep agent on top of the list
- if(mExcludeAgent)
- {
- mAvatarList->sortByName();
- }
- else
- {
- mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR);
+ switch ( getSortOrder() )
+ {
+ case E_SORT_BY_NAME :
+ // if mExcludeAgent == true , then no need to keep agent on top of the list
+ if(mExcludeAgent)
+ {
+ mAvatarList->sortByName();
+ }
+ else
+ {
+ mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR);
+ mAvatarList->sort();
+ }
+ break;
+ case E_SORT_BY_RECENT_SPEAKERS:
+ if (mSortByRecentSpeakers.isNull())
+ mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this);
+ mAvatarList->setComparator(mSortByRecentSpeakers.get());
mAvatarList->sort();
- }
- break;
- case E_SORT_BY_RECENT_SPEAKERS:
- if (mSortByRecentSpeakers.isNull())
- mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this);
- mAvatarList->setComparator(mSortByRecentSpeakers.get());
- mAvatarList->sort();
- break;
- default :
- llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
- return;
+ break;
+ default :
+ llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
+ return;
}
}
@@ -645,7 +652,7 @@ bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents:
//
bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
- return mParent.onModeratorUpdateEvent(event, userdata);
+ return mParent.onModeratorUpdateEvent(event, userdata);
}
bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
@@ -867,7 +874,7 @@ void LLParticipantList::LLParticipantListMenu::confirmMuteAllCallback(const LLSD
const LLUUID& session_id = payload["session_id"];
LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> (
- LLIMModel::getInstance()->getSpeakerManager(session_id));
+ LLIMModel::getInstance()->getSpeakerManager(session_id));
if (speaker_manager)
{
speaker_manager->moderateVoiceAllParticipants(false);
@@ -925,9 +932,9 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD&
}
/*
-Processed menu items with such parameters:
- can_allow_text_chat
- can_moderate_voice
+ Processed menu items with such parameters:
+ can_allow_text_chat
+ can_moderate_voice
*/
bool LLParticipantList::LLParticipantListMenu::enableModerateContextMenuItem(const LLSD& userdata)
{
@@ -978,11 +985,11 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD&
}
else if(item == "is_sorted_by_name")
{
- return E_SORT_BY_NAME == mParent.mSortOrder;
+ return E_SORT_BY_NAME == mParent.getSortOrder();
}
else if(item == "is_sorted_by_recent_speakers")
{
- return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder;
+ return E_SORT_BY_RECENT_SPEAKERS == mParent.getSortOrder();
}
return false;
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index 722a749d19..e0b3d42c25 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -24,6 +24,9 @@
* $/LicenseInfo$
*/
+#ifndef LL_PARTICIPANTLIST_H
+#define LL_PARTICIPANTLIST_H
+
#include "llviewerprecompiledheaders.h"
#include "llevent.h"
#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator
@@ -37,239 +40,247 @@ class LLAvalineUpdater;
class LLParticipantList
{
LOG_CLASS(LLParticipantList);
+public:
+
+ typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
+
+ LLParticipantList(LLSpeakerMgr* data_source,
+ LLAvatarList* avatar_list,
+ bool use_context_menu = true,
+ bool exclude_agent = true,
+ bool can_toggle_icons = true);
+ ~LLParticipantList();
+ void setSpeakingIndicatorsVisible(BOOL visible);
+
+ enum EParticipantSortOrder
+ {
+ E_SORT_BY_NAME = 0,
+ E_SORT_BY_RECENT_SPEAKERS = 1,
+ };
+
+ /**
+ * Adds specified avatar ID to the existing list if it is not Agent's ID
+ *
+ * @param[in] avatar_id - Avatar UUID to be added into the list
+ */
+ void addAvatarIDExceptAgent(const LLUUID& avatar_id);
+
+ /**
+ * Set and sort Avatarlist by given order
+ */
+ void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
+ const EParticipantSortOrder getSortOrder() const;
+
+ /**
+ * Refreshes the participant list if it's in sort by recent speaker order.
+ */
+ void updateRecentSpeakersOrder();
+
+ /**
+ * Set a callback to be called before adding a speaker. Invalid speakers will not be added.
+ *
+ * If the callback is unset all speakers are considered as valid.
+ *
+ * @see onAddItemEvent()
+ */
+ void setValidateSpeakerCallback(validate_speaker_callback_t cb);
+
+protected:
+ /**
+ * LLSpeakerMgr event handlers
+ */
+ bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+
+ /**
+ * Sorts the Avatarlist by stored order
+ */
+ void sort();
+
+ /**
+ * List of listeners implementing LLOldEvents::LLSimpleListener.
+ * There is no way to handle all the events in one listener as LLSpeakerMgr registers
+ * listeners in such a way that one listener can handle only one type of event
+ **/
+ class BaseSpeakerListener : public LLOldEvents::LLSimpleListener
+ {
public:
+ BaseSpeakerListener(LLParticipantList& parent) : mParent(parent) {}
+ protected:
+ LLParticipantList& mParent;
+ };
- typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t;
-
- LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true, bool can_toggle_icons = true);
- ~LLParticipantList();
- void setSpeakingIndicatorsVisible(BOOL visible);
-
- typedef enum e_participant_sort_oder {
- E_SORT_BY_NAME = 0,
- E_SORT_BY_RECENT_SPEAKERS = 1,
- } EParticipantSortOrder;
+ class SpeakerAddListener : public BaseSpeakerListener
+ {
+ public:
+ SpeakerAddListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
- /**
- * Adds specified avatar ID to the existing list if it is not Agent's ID
- *
- * @param[in] avatar_id - Avatar UUID to be added into the list
- */
- void addAvatarIDExceptAgent(const LLUUID& avatar_id);
+ class SpeakerRemoveListener : public BaseSpeakerListener
+ {
+ public:
+ SpeakerRemoveListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
- /**
- * Set and sort Avatarlist by given order
- */
- void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
- EParticipantSortOrder getSortOrder();
+ class SpeakerClearListener : public BaseSpeakerListener
+ {
+ public:
+ SpeakerClearListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
- /**
- * Refreshes the participant list if it's in sort by recent speaker order.
- */
- void updateRecentSpeakersOrder();
+ class SpeakerModeratorUpdateListener : public BaseSpeakerListener
+ {
+ public:
+ SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+
+ class SpeakerMuteListener : public BaseSpeakerListener
+ {
+ public:
+ SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
- /**
- * Set a callback to be called before adding a speaker. Invalid speakers will not be added.
- *
- * If the callback is unset all speakers are considered as valid.
- *
- * @see onAddItemEvent()
- */
- void setValidateSpeakerCallback(validate_speaker_callback_t cb);
+ /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ };
+ /**
+ * Menu used in the participant list.
+ */
+ class LLParticipantListMenu : public LLListContextMenu
+ {
+ public:
+ LLParticipantListMenu(LLParticipantList& parent):mParent(parent){};
+ /*virtual*/ LLContextMenu* createMenu();
+ /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);
protected:
+ LLParticipantList& mParent;
+ private:
+ bool enableContextMenuItem(const LLSD& userdata);
+ bool enableModerateContextMenuItem(const LLSD& userdata);
+ bool checkContextMenuItem(const LLSD& userdata);
+
+ void sortParticipantList(const LLSD& userdata);
+ void toggleAllowTextChat(const LLSD& userdata);
+ void toggleMute(const LLSD& userdata, U32 flags);
+ void toggleMuteText(const LLSD& userdata);
+ void toggleMuteVoice(const LLSD& userdata);
+
/**
- * LLSpeakerMgr event handlers
+ * Return true if Agent is group moderator(and moderator of group call).
*/
- bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ bool isGroupModerator();
+ // Voice moderation support
/**
- * Sorts the Avatarlist by stored order
+ * Check whether specified by argument avatar is muted for group chat or not.
*/
- void sort();
-
- //List of listeners implementing LLOldEvents::LLSimpleListener.
- //There is no way to handle all the events in one listener as LLSpeakerMgr registers listeners in such a way
- //that one listener can handle only one type of event
- class BaseSpeakerListner : public LLOldEvents::LLSimpleListener
- {
- public:
- BaseSpeakerListner(LLParticipantList& parent) : mParent(parent) {}
- protected:
- LLParticipantList& mParent;
- };
-
- class SpeakerAddListener : public BaseSpeakerListner
- {
- public:
- SpeakerAddListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
- /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- };
-
- class SpeakerRemoveListener : public BaseSpeakerListner
- {
- public:
- SpeakerRemoveListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
- /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- };
-
- class SpeakerClearListener : public BaseSpeakerListner
- {
- public:
- SpeakerClearListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
- /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- };
-
- class SpeakerModeratorUpdateListener : public BaseSpeakerListner
- {
- public:
- SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
- /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- };
-
- class SpeakerMuteListener : public BaseSpeakerListner
- {
- public:
- SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {}
-
- /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
- };
+ bool isMuted(const LLUUID& avatar_id);
/**
- * Menu used in the participant list.
+ * Processes Voice moderation menu items.
+ *
+ * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on
+ * passed parameter.
+ *
+ * @param userdata can be "selected" or "others".
+ *
+ * @see moderateVoiceParticipant()
+ * @see moderateVoiceAllParticipants()
*/
- class LLParticipantListMenu : public LLListContextMenu
- {
- public:
- LLParticipantListMenu(LLParticipantList& parent):mParent(parent){};
- /*virtual*/ LLContextMenu* createMenu();
- /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);
- protected:
- LLParticipantList& mParent;
- private:
- bool enableContextMenuItem(const LLSD& userdata);
- bool enableModerateContextMenuItem(const LLSD& userdata);
- bool checkContextMenuItem(const LLSD& userdata);
-
- void sortParticipantList(const LLSD& userdata);
- void toggleAllowTextChat(const LLSD& userdata);
- void toggleMute(const LLSD& userdata, U32 flags);
- void toggleMuteText(const LLSD& userdata);
- void toggleMuteVoice(const LLSD& userdata);
-
- /**
- * Return true if Agent is group moderator(and moderator of group call).
- */
- bool isGroupModerator();
-
- // Voice moderation support
- /**
- * Check whether specified by argument avatar is muted for group chat or not.
- */
- bool isMuted(const LLUUID& avatar_id);
-
- /**
- * Processes Voice moderation menu items.
- *
- * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on
- * passed parameter.
- *
- * @param userdata can be "selected" or "others".
- *
- * @see moderateVoiceParticipant()
- * @see moderateVoiceAllParticipants()
- */
- void moderateVoice(const LLSD& userdata);
-
- /**
- * Mutes/Unmutes avatar for current group voice chat.
- *
- * It only marks avatar as muted for session and does not use local Agent's Block list.
- * It does not mute Agent itself.
- *
- * @param[in] avatar_id UUID of avatar to be processed
- * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted.
- *
- * @see moderateVoiceAllParticipants()
- */
- void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute);
-
- /**
- * Mutes/Unmutes all avatars for current group voice chat.
- *
- * It only marks avatars as muted for session and does not use local Agent's Block list.
- *
- * @param[in] unmute if true - avatars will be muted, otherwise - unmuted.
- *
- * @see moderateVoiceParticipant()
- */
- void moderateVoiceAllParticipants(bool unmute);
-
- static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response);
- };
+ void moderateVoice(const LLSD& userdata);
/**
- * Comparator for comparing avatar items by last spoken time
+ * Mutes/Unmutes avatar for current group voice chat.
+ *
+ * It only marks avatar as muted for session and does not use local Agent's Block list.
+ * It does not mute Agent itself.
+ *
+ * @param[in] avatar_id UUID of avatar to be processed
+ * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted.
+ *
+ * @see moderateVoiceAllParticipants()
*/
- class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount
- {
- LOG_CLASS(LLAvatarItemRecentSpeakerComparator);
- public:
- LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){};
- virtual ~LLAvatarItemRecentSpeakerComparator() {};
- protected:
- virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
- private:
- LLParticipantList& mParent;
- };
-
- private:
- void onAvatarListDoubleClicked(LLUICtrl* ctrl);
- void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
-
- void onAvalineCallerFound(const LLUUID& participant_id);
- void onAvalineCallerRemoved(const LLUUID& participant_id);
+ void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute);
/**
- * Adjusts passed participant to work properly.
+ * Mutes/Unmutes all avatars for current group voice chat.
*
- * Adds SpeakerMuteListener to process moderation actions.
- */
- void adjustParticipant(const LLUUID& speaker_id);
-
- LLSpeakerMgr* mSpeakerMgr;
- LLAvatarList* mAvatarList;
-
- std::set<LLUUID> mModeratorList;
- std::set<LLUUID> mModeratorToRemoveList;
-
- LLPointer<SpeakerAddListener> mSpeakerAddListener;
- LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
- LLPointer<SpeakerClearListener> mSpeakerClearListener;
- LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
- LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
-
- LLParticipantListMenu* mParticipantListMenu;
-
- EParticipantSortOrder mSortOrder;
- /*
- * This field manages an adding a new avatar_id in the mAvatarList
- * If true, then agent_id wont be added into mAvatarList
- * Also by default this field is controlling a sort procedure, @c sort()
+ * It only marks avatars as muted for session and does not use local Agent's Block list.
+ *
+ * @param[in] unmute if true - avatars will be muted, otherwise - unmuted.
+ *
+ * @see moderateVoiceParticipant()
*/
- bool mExcludeAgent;
+ void moderateVoiceAllParticipants(bool unmute);
- // boost::connections
- boost::signals2::connection mAvatarListDoubleClickConnection;
- boost::signals2::connection mAvatarListRefreshConnection;
- boost::signals2::connection mAvatarListReturnConnection;
- boost::signals2::connection mAvatarListToggleIconsConnection;
+ static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response);
+ };
- LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
- validate_speaker_callback_t mValidateSpeakerCallback;
- LLAvalineUpdater* mAvalineUpdater;
+ /**
+ * Comparator for comparing avatar items by last spoken time
+ */
+ class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount
+ {
+ LOG_CLASS(LLAvatarItemRecentSpeakerComparator);
+ public:
+ LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){};
+ virtual ~LLAvatarItemRecentSpeakerComparator() {};
+ protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
+ private:
+ LLParticipantList& mParent;
+ };
+
+private:
+ void onAvatarListDoubleClicked(LLUICtrl* ctrl);
+ void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
+
+ void onAvalineCallerFound(const LLUUID& participant_id);
+ void onAvalineCallerRemoved(const LLUUID& participant_id);
+
+ /**
+ * Adjusts passed participant to work properly.
+ *
+ * Adds SpeakerMuteListener to process moderation actions.
+ */
+ void adjustParticipant(const LLUUID& speaker_id);
+
+ LLSpeakerMgr* mSpeakerMgr;
+ LLAvatarList* mAvatarList;
+
+ std::set<LLUUID> mModeratorList;
+ std::set<LLUUID> mModeratorToRemoveList;
+
+ LLPointer<SpeakerAddListener> mSpeakerAddListener;
+ LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
+ LLPointer<SpeakerClearListener> mSpeakerClearListener;
+ LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
+ LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
+
+ LLParticipantListMenu* mParticipantListMenu;
+
+ /**
+ * This field manages an adding a new avatar_id in the mAvatarList
+ * If true, then agent_id wont be added into mAvatarList
+ * Also by default this field is controlling a sort procedure, @c sort()
+ */
+ bool mExcludeAgent;
+
+ // boost::connections
+ boost::signals2::connection mAvatarListDoubleClickConnection;
+ boost::signals2::connection mAvatarListRefreshConnection;
+ boost::signals2::connection mAvatarListReturnConnection;
+ boost::signals2::connection mAvatarListToggleIconsConnection;
+
+ LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
+ validate_speaker_callback_t mValidateSpeakerCallback;
+ LLAvalineUpdater* mAvalineUpdater;
};
+
+#endif // LL_PARTICIPANTLIST_H
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
index 408270a1a0..29e262199e 100644
--- a/indra/newview/llplacesinventorypanel.cpp
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -205,24 +205,6 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask)
return LLFolderView::handleRightMouseDown(x, y, mask);
}
-BOOL LLPlacesFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- // Don't accept anything except landmarks and folders to be dropped
- // in places folder view. See STORM-296.
- if (cargo_type != DAD_LANDMARK && cargo_type != DAD_CATEGORY)
- {
- *accept = ACCEPT_NO;
- return FALSE;
- }
-
- return LLFolderView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data,
- accept, tooltip_msg);
-}
-
void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle)
{
mMenuHandlesByInventoryType[asset_type] = menu_handle;
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
index a44776d18b..6641871a0b 100644
--- a/indra/newview/llplacesinventorypanel.h
+++ b/indra/newview/llplacesinventorypanel.h
@@ -70,12 +70,6 @@ public:
*/
/*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
-
void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle);
void setParentLandmarksPanel(LLLandmarksPanel* panel)
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index cf2ea38288..330e809c53 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -34,11 +34,13 @@
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldir.h"
+#include "llexternaleditor.h"
#include "llfloaterreg.h"
#include "llinventorydefines.h"
#include "llinventorymodel.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
+#include "lllivefile.h"
#include "llhelp.h"
#include "llnotificationsutil.h"
#include "llresmgr.h"
@@ -116,6 +118,54 @@ static bool have_script_upload_cap(LLUUID& object_id)
}
/// ---------------------------------------------------------------------------
+/// LLLiveLSLFile
+/// ---------------------------------------------------------------------------
+class LLLiveLSLFile : public LLLiveFile
+{
+public:
+ LLLiveLSLFile(std::string file_path, LLLiveLSLEditor* parent);
+ ~LLLiveLSLFile();
+
+ void ignoreNextUpdate() { mIgnoreNextUpdate = true; }
+
+protected:
+ /*virtual*/ bool loadFile();
+
+ LLLiveLSLEditor* mParent;
+ bool mIgnoreNextUpdate;
+};
+
+LLLiveLSLFile::LLLiveLSLFile(std::string file_path, LLLiveLSLEditor* parent)
+: mParent(parent)
+, mIgnoreNextUpdate(false)
+, LLLiveFile(file_path, 1.0)
+{
+}
+
+LLLiveLSLFile::~LLLiveLSLFile()
+{
+ LLFile::remove(filename());
+}
+
+bool LLLiveLSLFile::loadFile()
+{
+ if (mIgnoreNextUpdate)
+ {
+ mIgnoreNextUpdate = false;
+ return true;
+ }
+
+ if (!mParent->loadScriptText(filename()))
+ {
+ return false;
+ }
+
+ // Disable sync to avoid recursive load->save->load calls.
+ mParent->saveIfNeeded(false);
+ return true;
+}
+
+/// ---------------------------------------------------------------------------
/// LLFloaterScriptSearch
/// ---------------------------------------------------------------------------
class LLFloaterScriptSearch : public LLFloater
@@ -281,6 +331,7 @@ LLScriptEdCore::LLScriptEdCore(
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void*),
void (*save_callback)(void*, BOOL),
+ void (*edit_callback)(void*),
void (*search_replace_callback) (void* userdata),
void* userdata,
S32 bottom_pad)
@@ -290,6 +341,7 @@ LLScriptEdCore::LLScriptEdCore(
mEditor( NULL ),
mLoadCallback( load_callback ),
mSaveCallback( save_callback ),
+ mEditCallback( edit_callback ),
mSearchReplaceCallback( search_replace_callback ),
mUserdata( userdata ),
mForceClose( FALSE ),
@@ -329,6 +381,7 @@ BOOL LLScriptEdCore::postBuild()
childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE));
+ childSetAction("Edit_btn", boost::bind(&LLScriptEdCore::onEditButtonClick, this));
initMenu();
@@ -809,6 +862,13 @@ void LLScriptEdCore::doSave( BOOL close_after_save )
}
}
+void LLScriptEdCore::onEditButtonClick()
+{
+ if (mEditCallback)
+ {
+ mEditCallback(mUserdata);
+ }
+}
void LLScriptEdCore::onBtnUndoChanges()
{
@@ -949,6 +1009,7 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
self->getHandle(),
LLPreviewLSL::onLoad,
LLPreviewLSL::onSave,
+ NULL, // no edit callback
LLPreviewLSL::onSearchReplace,
self,
0);
@@ -1417,6 +1478,7 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
self->getHandle(),
&LLLiveLSLEditor::onLoad,
&LLLiveLSLEditor::onSave,
+ &LLLiveLSLEditor::onEdit,
&LLLiveLSLEditor::onSearchReplace,
self,
0);
@@ -1433,6 +1495,7 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
mCloseAfterSave(FALSE),
mPendingUploads(0),
mIsModifiable(FALSE),
+ mLiveFile(NULL),
mIsNew(false)
{
mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
@@ -1458,6 +1521,7 @@ BOOL LLLiveLSLEditor::postBuild()
LLLiveLSLEditor::~LLLiveLSLEditor()
{
+ delete mLiveFile;
}
// virtual
@@ -1639,38 +1703,39 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
delete xored_id;
}
-// unused
-// void LLLiveLSLEditor::loadScriptText(const std::string& filename)
-// {
-// if(!filename)
-// {
-// llerrs << "Filename is Empty!" << llendl;
-// return;
-// }
-// LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
-// if(file)
-// {
-// // read in the whole file
-// fseek(file, 0L, SEEK_END);
-// long file_length = ftell(file);
-// fseek(file, 0L, SEEK_SET);
-// char* buffer = new char[file_length+1];
-// size_t nread = fread(buffer, 1, file_length, file);
-// if (nread < (size_t) file_length)
-// {
-// llwarns << "Short read" << llendl;
-// }
-// buffer[nread] = '\0';
-// fclose(file);
-// mScriptEd->mEditor->setText(LLStringExplicit(buffer));
-// mScriptEd->mEditor->makePristine();
-// delete[] buffer;
-// }
-// else
-// {
-// llwarns << "Error opening " << filename << llendl;
-// }
-// }
+ bool LLLiveLSLEditor::loadScriptText(const std::string& filename)
+ {
+ if (filename.empty())
+ {
+ llwarns << "Empty file name" << llendl;
+ return false;
+ }
+
+ LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ if (!file)
+ {
+ llwarns << "Error opening " << filename << llendl;
+ return false;
+ }
+
+ // read in the whole file
+ fseek(file, 0L, SEEK_END);
+ size_t file_length = (size_t) ftell(file);
+ fseek(file, 0L, SEEK_SET);
+ char* buffer = new char[file_length+1];
+ size_t nread = fread(buffer, 1, file_length, file);
+ if (nread < file_length)
+ {
+ llwarns << "Short read" << llendl;
+ }
+ buffer[nread] = '\0';
+ fclose(file);
+ mScriptEd->mEditor->setText(LLStringExplicit(buffer));
+ //mScriptEd->mEditor->makePristine();
+ delete[] buffer;
+
+ return true;
+ }
void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
{
@@ -1825,9 +1890,8 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
mItem = new LLViewerInventoryItem(item);
}
-void LLLiveLSLEditor::saveIfNeeded()
+void LLLiveLSLEditor::saveIfNeeded(bool sync)
{
- llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(!object)
{
@@ -1877,9 +1941,74 @@ void LLLiveLSLEditor::saveIfNeeded()
mItem->setAssetUUID(asset_id);
mItem->setTransactionID(tid);
- // write out the data, and store it in the asset database
+ writeToFile(filename);
+
+ if (sync)
+ {
+ // Sync with external ed2itor.
+ std::string tmp_file = getTmpFileName();
+ llstat s;
+ if (LLFile::stat(tmp_file, &s) == 0) // file exists
+ {
+ if (mLiveFile) mLiveFile->ignoreNextUpdate();
+ writeToFile(tmp_file);
+ }
+ }
+
+ // save it out to asset server
+ std::string url = object->getRegion()->getCapability("UpdateScriptTask");
+ getWindow()->incBusyCount();
+ mPendingUploads++;
+ BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
+ if (!url.empty())
+ {
+ uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running);
+ }
+ else if (gAssetStorage)
+ {
+ uploadAssetLegacy(filename, object, tid, is_running);
+ }
+}
+
+void LLLiveLSLEditor::openExternalEditor()
+{
+ LLViewerObject* object = gObjectList.findObject(mObjectUUID);
+ if(!object)
+ {
+ LLNotificationsUtil::add("SaveScriptFailObjectNotFound");
+ return;
+ }
+
+ delete mLiveFile; // deletes file
+
+ // Save the script to a temporary file.
+ std::string filename = getTmpFileName();
+ writeToFile(filename);
+
+ // Start watching file changes.
+ mLiveFile = new LLLiveLSLFile(filename, this);
+ mLiveFile->addToEventTimer();
+
+ // Open it in external editor.
+ {
+ LLExternalEditor ed;
+
+ if (!ed.setCommand("LL_SCRIPT_EDITOR"))
+ {
+ std::string msg = "Select an editor by setting the environment variable LL_SCRIPT_EDITOR "
+ "or the ExternalEditor setting"; // *TODO: localize
+ LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
+ return;
+ }
+
+ ed.run(filename);
+ }
+}
+
+bool LLLiveLSLEditor::writeToFile(const std::string& filename)
+{
LLFILE* fp = LLFile::fopen(filename, "wb");
- if(!fp)
+ if (!fp)
{
llwarns << "Unable to write to " << filename << llendl;
@@ -1887,33 +2016,25 @@ void LLLiveLSLEditor::saveIfNeeded()
row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
row["columns"][0]["font"] = "SANSSERIF_SMALL";
mScriptEd->mErrorList->addElement(row);
- return;
+ return false;
}
+
std::string utf8text = mScriptEd->mEditor->getText();
// Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889
- if ( utf8text.size() == 0 )
+ if (utf8text.size() == 0)
{
utf8text = " ";
}
fputs(utf8text.c_str(), fp);
fclose(fp);
- fp = NULL;
-
- // save it out to asset server
- std::string url = object->getRegion()->getCapability("UpdateScriptTask");
- getWindow()->incBusyCount();
- mPendingUploads++;
- BOOL is_running = getChild<LLCheckBoxCtrl>( "running")->get();
- if (!url.empty())
- {
- uploadAssetViaCaps(url, filename, mObjectUUID, mItemUUID, is_running);
- }
- else if (gAssetStorage)
- {
- uploadAssetLegacy(filename, object, tid, is_running);
- }
+ return true;
+}
+
+std::string LLLiveLSLEditor::getTmpFileName()
+{
+ return std::string(LLFile::tmpdir()) + "sl_script_" + mObjectUUID.asString() + ".lsl";
}
void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
@@ -2138,6 +2259,14 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
self->saveIfNeeded();
}
+
+// static
+void LLLiveLSLEditor::onEdit(void* userdata)
+{
+ LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
+ self->openExternalEditor();
+}
+
// static
void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
{
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index f4b31e5962..d35c6b8528 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -35,6 +35,7 @@
#include "lliconctrl.h"
#include "llframetimer.h"
+class LLLiveLSLFile;
class LLMessageSystem;
class LLTextEditor;
class LLButton;
@@ -62,6 +63,7 @@ public:
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void* userdata),
void (*save_callback)(void* userdata, BOOL close_after_save),
+ void (*edit_callback)(void*),
void (*search_replace_callback)(void* userdata),
void* userdata,
S32 bottom_pad = 0); // pad below bottom row of buttons
@@ -80,6 +82,8 @@ public:
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response);
+ void onEditButtonClick();
+
static void onCheckLock(LLUICtrl*, void*);
static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
static void onClickBack(void* userdata);
@@ -114,6 +118,7 @@ private:
LLTextEditor* mEditor;
void (*mLoadCallback)(void* userdata);
void (*mSaveCallback)(void* userdata, BOOL close_after_save);
+ void (*mEditCallback)(void* userdata);
void (*mSearchReplaceCallback) (void* userdata);
void* mUserdata;
LLComboBox *mFunctions;
@@ -179,6 +184,7 @@ protected:
// Used to view and edit an LSL that is attached to an object.
class LLLiveLSLEditor : public LLPreview
{
+ friend class LLLiveLSLFile;
public:
LLLiveLSLEditor(const LLSD& key);
~LLLiveLSLEditor();
@@ -202,7 +208,10 @@ private:
virtual void loadAsset();
void loadAsset(BOOL is_new);
- void saveIfNeeded();
+ void saveIfNeeded(bool sync = true);
+ void openExternalEditor();
+ std::string getTmpFileName();
+ bool writeToFile(const std::string& filename);
void uploadAssetViaCaps(const std::string& url,
const std::string& filename,
const LLUUID& task_id,
@@ -218,6 +227,7 @@ private:
static void onSearchReplace(void* userdata);
static void onLoad(void* userdata);
static void onSave(void* userdata, BOOL close_after_save);
+ static void onEdit(void* userdata);
static void onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid,
LLAssetType::EType type,
@@ -227,7 +237,7 @@ private:
static void onRunningCheckboxClicked(LLUICtrl*, void* userdata);
static void onReset(void* userdata);
-// void loadScriptText(const std::string& filename); // unused
+ bool loadScriptText(const std::string& filename);
void loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type);
static void onErrorList(LLUICtrl*, void* user_data);
@@ -253,6 +263,7 @@ private:
LLCheckBoxCtrl* mMonoCheckbox;
BOOL mIsModifiable;
+ LLLiveLSLFile* mLiveFile;
};
#endif // LL_LLPREVIEWSCRIPT_H
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index d63a48647d..0dff087553 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -77,23 +77,20 @@ void LLRemoteParcelRequestResponder::error(U32 status, const std::string& reason
void LLRemoteParcelInfoProcessor::addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
{
- // Check if the observer is already in observers list for this UUID
observer_multimap_t::iterator it;
+ observer_multimap_t::iterator start = mObservers.lower_bound(parcel_id);
+ observer_multimap_t::iterator end = mObservers.upper_bound(parcel_id);
- it = mObservers.find(parcel_id);
- while (it != mObservers.end())
+ // Check if the observer is already in observers list for this UUID
+ for(it = start; it != end; ++it)
{
- if (it->second == observer)
+ if (it->second.get() == observer)
{
return;
}
- else
- {
- ++it;
- }
}
- mObservers.insert(std::pair<LLUUID, LLRemoteParcelInfoObserver*>(parcel_id, observer));
+ mObservers.insert(std::make_pair(parcel_id, observer->getObserverHandle()));
}
void LLRemoteParcelInfoProcessor::removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer)
@@ -104,19 +101,16 @@ void LLRemoteParcelInfoProcessor::removeObserver(const LLUUID& parcel_id, LLRemo
}
observer_multimap_t::iterator it;
+ observer_multimap_t::iterator start = mObservers.lower_bound(parcel_id);
+ observer_multimap_t::iterator end = mObservers.upper_bound(parcel_id);
- it = mObservers.find(parcel_id);
- while (it != mObservers.end())
+ for(it = start; it != end; ++it)
{
- if (it->second == observer)
+ if (it->second.get() == observer)
{
mObservers.erase(it);
break;
}
- else
- {
- ++it;
- }
}
}
@@ -141,13 +135,35 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v
msg->getS32 ("Data", "SalePrice", parcel_data.sale_price);
msg->getS32 ("Data", "AuctionID", parcel_data.auction_id);
- LLRemoteParcelInfoProcessor::observer_multimap_t observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers;
+ LLRemoteParcelInfoProcessor::observer_multimap_t & observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers;
+
+ typedef std::vector<observer_multimap_t::iterator> deadlist_t;
+ deadlist_t dead_iters;
- observer_multimap_t::iterator oi = observers.find(parcel_data.parcel_id);
+ observer_multimap_t::iterator oi;
+ observer_multimap_t::iterator start = observers.lower_bound(parcel_data.parcel_id);
observer_multimap_t::iterator end = observers.upper_bound(parcel_data.parcel_id);
- for (; oi != end; ++oi)
+
+ for (oi = start; oi != end; ++oi)
+ {
+ LLRemoteParcelInfoObserver * observer = oi->second.get();
+ if(observer)
+ {
+ observer->processParcelInfo(parcel_data);
+ }
+ else
+ {
+ // the handle points to an expired observer, so don't keep it
+ // around anymore
+ dead_iters.push_back(oi);
+ }
+ }
+
+ deadlist_t::iterator i;
+ deadlist_t::iterator end_dead = dead_iters.end();
+ for(i = dead_iters.begin(); i != end_dead; ++i)
{
- oi->second->processParcelInfo(parcel_data);
+ observers.erase(*i);
}
}
diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h
index a6c62995a9..74cf1616df 100644
--- a/indra/newview/llremoteparcelrequest.h
+++ b/indra/newview/llremoteparcelrequest.h
@@ -98,7 +98,7 @@ public:
static void processParcelInfoReply(LLMessageSystem* msg, void**);
private:
- typedef std::multimap<LLUUID, LLRemoteParcelInfoObserver*> observer_multimap_t;
+ typedef std::multimap<LLUUID, LLHandle<LLRemoteParcelInfoObserver> > observer_multimap_t;
observer_multimap_t mObservers;
};
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 18c9ac28c1..61f4897ed0 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -369,7 +369,7 @@ void LLScreenChannel::loadStoredToastsToChannel()
for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
{
(*it).toast->setIsHidden(false);
- (*it).toast->resetTimer();
+ (*it).toast->startFading();
mToastList.push_back((*it));
}
@@ -394,7 +394,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
}
toast->setIsHidden(false);
- toast->resetTimer();
+ toast->startFading();
mToastList.push_back((*it));
redrawToasts();
@@ -477,7 +477,7 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
toast->removeChild(old_panel);
delete old_panel;
toast->insertPanel(panel);
- toast->resetTimer();
+ toast->startFading();
redrawToasts();
}
}
@@ -588,7 +588,7 @@ void LLScreenChannel::showToastsBottom()
mHiddenToastsNum = 0;
for(; it != mToastList.rend(); it++)
{
- (*it).toast->stopTimer();
+ (*it).toast->stopFading();
(*it).toast->setVisible(FALSE);
mHiddenToastsNum++;
}
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 2334f0cde5..170e23e4c5 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -32,11 +32,13 @@
#include "llchannelmanager.h"
#include "llchiclet.h"
#include "llfloaterreg.h"
+#include "lllslconstants.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llscreenchannel.h"
#include "llsyswellwindow.h"
#include "lltoastnotifypanel.h"
+#include "lltoastscripttextbox.h"
#include "lltrans.h"
#include "llviewerwindow.h"
#include "llimfloater.h"
@@ -151,10 +153,18 @@ void LLScriptFloater::createForm(const LLUUID& notification_id)
// create new form
LLRect toast_rect = getRect();
- // LLToastNotifyPanel will fit own content in vertical direction,
- // but it needs an initial rect to properly calculate its width
- // Use an initial rect of the script floater to make the floater window more configurable.
- mScriptForm = new LLToastNotifyPanel(notification, toast_rect);
+ if (isScriptTextbox(notification))
+ {
+ mScriptForm = new LLToastScriptTextbox(notification);
+ }
+ else
+ {
+ // LLToastNotifyPanel will fit own content in vertical direction,
+ // but it needs an initial rect to properly calculate its width
+ // Use an initial rect of the script floater to make the floater
+ // window more configurable.
+ mScriptForm = new LLToastNotifyPanel(notification, toast_rect);
+ }
addChild(mScriptForm);
// position form on floater
@@ -564,4 +574,32 @@ void LLScriptFloaterManager::setFloaterVisible(const LLUUID& notification_id, bo
}
}
+//////////////////////////////////////////////////////////////////
+
+bool LLScriptFloater::isScriptTextbox(LLNotificationPtr notification)
+{
+ // get a form for the notification
+ LLNotificationFormPtr form(notification->getForm());
+
+ if (form)
+ {
+ // get number of elements in the form
+ int num_options = form->getNumElements();
+
+ // if ANY of the buttons have the magic lltextbox string as
+ // name, then treat the whole dialog as a simple text entry
+ // box (i.e. mixed button and textbox forms are not supported)
+ for (int i=0; i<num_options; ++i)
+ {
+ LLSD form_element = form->getElement(i);
+ if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
// EOF
diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h
index da70bb4334..dc52baa115 100644
--- a/indra/newview/llscriptfloater.h
+++ b/indra/newview/llscriptfloater.h
@@ -28,6 +28,7 @@
#define LL_SCRIPTFLOATER_H
#include "lltransientdockablefloater.h"
+#include "llnotificationptr.h"
class LLToastNotifyPanel;
@@ -203,6 +204,8 @@ protected:
void dockToChiclet(bool dock);
private:
+ bool isScriptTextbox(LLNotificationPtr notification);
+
LLToastNotifyPanel* mScriptForm;
LLUUID mNotificationId;
LLUUID mObjectId;
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index f9c0fd398e..be797ea937 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -68,10 +68,22 @@ private:
void LLItemPropertiesObserver::changed(U32 mask)
{
- // if there's a change we're interested in.
- if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
+ const std::set<LLUUID>& mChangedItemIDs = gInventory.getChangedIDs();
+ std::set<LLUUID>::const_iterator it;
+
+ const LLUUID& object_id = mFloater->getObjectID();
+
+ for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++)
{
- mFloater->dirty();
+ // set dirty for 'item profile panel' only if changed item is the item for which 'item profile panel' is shown (STORM-288)
+ if (*it == object_id)
+ {
+ // if there's a change we're interested in.
+ if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
+ {
+ mFloater->dirty();
+ }
+ }
}
}
@@ -179,6 +191,11 @@ void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
mItemID = item_id;
}
+const LLUUID& LLSidepanelItemInfo::getObjectID() const
+{
+ return mObjectID;
+}
+
void LLSidepanelItemInfo::reset()
{
LLSidepanelInventorySubpanel::reset();
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 10e93dd7de..6416e2cfe4 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -54,6 +54,8 @@ public:
void setItemID(const LLUUID& item_id);
void setEditMode(BOOL edit);
+ const LLUUID& getObjectID() const;
+
protected:
/*virtual*/ void refresh();
/*virtual*/ void save();
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 81b2fc0ae0..3f8aeaf400 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -118,7 +118,7 @@ public:
protected:
LLSideTrayTab(const Params& params);
- void dock();
+ void dock(LLFloater* floater_tab);
void undock(LLFloater* floater_tab);
LLSideTray* getSideTray();
@@ -259,7 +259,7 @@ void LLSideTrayTab::toggleTabDocked()
if (docking)
{
- dock();
+ dock(floater_tab);
}
else
{
@@ -271,11 +271,14 @@ void LLSideTrayTab::toggleTabDocked()
LLFloaterReg::toggleInstance("side_bar_tab", tab_name);
}
-void LLSideTrayTab::dock()
+void LLSideTrayTab::dock(LLFloater* floater_tab)
{
LLSideTray* side_tray = getSideTray();
if (!side_tray) return;
+ // Before docking the tab, reset its (and its children's) transparency to default (STORM-688).
+ floater_tab->updateTransparency(TT_DEFAULT);
+
if (!side_tray->addTab(this))
{
llwarns << "Failed to add tab " << getName() << " to side tray" << llendl;
@@ -1028,7 +1031,8 @@ void LLSideTray::arrange()
}
// The tab buttons should be shown only if there is at least one non-detached tab.
- mButtonsPanel->setVisible(hasTabs());
+ // Also hide them in mouse-look mode.
+ mButtonsPanel->setVisible(hasTabs() && !gAgentCamera.cameraMouselook());
}
// Detach those tabs that were detached when the viewer exited last time.
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 4c23a1920b..3c572dde95 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -40,6 +40,8 @@ class LLSideTray : public LLPanel, private LLDestroyClass<LLSideTray>
{
friend class LLUICtrlFactory;
friend class LLDestroyClass<LLSideTray>;
+ friend class LLSideTrayTab;
+ friend class LLSideTrayButton;
public:
LOG_CLASS(LLSideTray);
@@ -126,11 +128,6 @@ public:
}
/*
- * get currently active tab
- */
- const LLSideTrayTab* getActiveTab() const { return mActiveTab; }
-
- /*
* collapse SideBar, hiding visible tab and moving tab buttons
* to the right corner of the screen
*/
@@ -163,32 +160,28 @@ public:
virtual BOOL postBuild();
- void onTabButtonClick(std::string name);
- void onToggleCollapse();
-
- bool addChild (LLView* view, S32 tab_group);
- bool removeTab (LLSideTrayTab* tab); // Used to detach tabs temporarily
- bool addTab (LLSideTrayTab* tab); // Used to re-attach tabs
-
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
- void processTriState ();
-
+
void updateSidetrayVisibility();
commit_signal_t& getCollapseSignal() { return mCollapseSignal; }
void handleLoginComplete();
- LLSideTrayTab* getTab (const std::string& name);
-
bool isTabAttached (const std::string& name);
protected:
+ bool addChild (LLView* view, S32 tab_group);
+ bool removeTab (LLSideTrayTab* tab); // Used to detach tabs temporarily
+ bool addTab (LLSideTrayTab* tab); // Used to re-attach tabs
bool hasTabs ();
+ const LLSideTrayTab* getActiveTab() const { return mActiveTab; }
+ LLSideTrayTab* getTab(const std::string& name);
+
void createButtons ();
LLButton* createButton (const std::string& name,const std::string& image,const std::string& tooltip,
@@ -196,11 +189,15 @@ protected:
void arrange ();
void detachTabs ();
void reflectCollapseChange();
+ void processTriState ();
void toggleTabButton (LLSideTrayTab* tab);
LLPanel* openChildPanel (LLSideTrayTab* tab, const std::string& panel_name, const LLSD& params);
+ void onTabButtonClick(std::string name);
+ void onToggleCollapse();
+
private:
// Implementation of LLDestroyClass<LLSideTray>
static void destroyClass()
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index fb984a7c62..960e72ee42 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1555,7 +1555,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
{
- if (earlyFail(camera, this))
+ // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
+ if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) ||
+ earlyFail(camera, this))
{
setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
assert_states_valid(this);
@@ -1576,7 +1578,18 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
buildOcclusion();
}
-
+
+ // Depth clamp all water to avoid it being culled as a result of being
+ // behind the far clip plane, and in the case of edge water to avoid
+ // it being culled while still visible.
+ bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
+ (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
+ mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
+ if (use_depth_clamp)
+ {
+ glEnable(GL_DEPTH_CLAMP);
+ }
+
glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
if (camera->getOrigin().isExactlyZero())
@@ -1592,6 +1605,11 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
}
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
+
+ if (use_depth_clamp)
+ {
+ glDisable(GL_DEPTH_CLAMP);
+ }
}
setOcclusionState(LLSpatialGroup::QUERY_PENDING);
@@ -2591,9 +2609,10 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
gGL.color4f(0.5f,0.5f,0.5f,1.0f);
break;
case LLViewerObject::LL_VO_PART_GROUP:
- case LLViewerObject::LL_VO_HUD_PART_GROUP:
+ case LLViewerObject::LL_VO_HUD_PART_GROUP:
gGL.color4f(0,0,1,1);
break;
+ case LLViewerObject::LL_VO_VOID_WATER:
case LLViewerObject::LL_VO_WATER:
gGL.color4f(0,0.5f,1,1);
break;
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 1a25f3f85d..2b9cf6c630 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -551,6 +551,13 @@ public:
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
};
+//spatial partition for hole and edge water (implemented in LLVOWater.cpp)
+class LLVoidWaterPartition : public LLWaterPartition
+{
+public:
+ LLVoidWaterPartition();
+};
+
//spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp)
class LLTerrainPartition : public LLSpatialPartition
{
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index 3dce66f394..c76ecae4a2 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -134,8 +134,11 @@ LLSpeakButton::LLSpeakButton(const Params& p)
LLSpeakButton::~LLSpeakButton()
{
- LLTransientFloaterMgr::getInstance()->removeControlView(mSpeakBtn);
- LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn);
+ if(LLTransientFloaterMgr::instanceExists())
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(mSpeakBtn);
+ LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn);
+ }
}
void LLSpeakButton::setSpeakToolTip(const std::string& msg)
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index ede1d6bebe..9b38bf22ff 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -308,7 +308,10 @@ void LLSpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker
void LLSpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator)
{
- SpeakingIndicatorManager::instance().unregisterSpeakingIndicator(speaker_id, speaking_indicator);
+ if(SpeakingIndicatorManager::instanceExists())
+ {
+ SpeakingIndicatorManager::instance().unregisterSpeakingIndicator(speaker_id, speaking_indicator);
+ }
}
// EOF
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 5ee4599200..80cf7e3cd0 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -198,6 +198,7 @@
// exported globals
//
bool gAgentMovementCompleted = false;
+S32 gMaxAgentGroups;
std::string SCREEN_HOME_FILENAME = "screen_home.bmp";
std::string SCREEN_LAST_FILENAME = "screen_last.bmp";
@@ -3151,6 +3152,18 @@ bool process_login_success_response()
LLViewerMedia::openIDSetup(openid_url, openid_token);
}
+ if(response.has("max-agent-groups")) {
+ std::string max_agent_groups(response["max-agent-groups"]);
+ gMaxAgentGroups = atoi(max_agent_groups.c_str());
+ LL_INFOS("LLStartup") << "gMaxAgentGroups read from login.cgi: "
+ << gMaxAgentGroups << LL_ENDL;
+ }
+ else {
+ gMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS;
+ LL_INFOS("LLStartup") << "using gMaxAgentGroups default: "
+ << gMaxAgentGroups << LL_ENDL;
+ }
+
bool success = false;
// JC: gesture loading done below, when we have an asset system
// in place. Don't delete/clear gUserCredentials until then.
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index be1043cf91..b3d9ef1dcc 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -70,6 +70,7 @@ typedef enum {
// exported symbols
extern bool gAgentMovementCompleted;
+extern S32 gMaxAgentGroups;
extern LLPointer<LLViewerTexture> gStartTexture;
class LLStartUp
diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index af4d9fa7b9..6fc8153b77 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -1162,8 +1162,13 @@ void LLSurface::setWaterHeight(F32 height)
if (!mWaterObjp.isNull())
{
LLVector3 water_pos_region = mWaterObjp->getPositionRegion();
+ bool changed = water_pos_region.mV[VZ] != height;
water_pos_region.mV[VZ] = height;
mWaterObjp->setPositionRegion(water_pos_region);
+ if (changed)
+ {
+ LLWorld::getInstance()->updateWaterObjects();
+ }
}
else
{
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 328298bda4..56e9739350 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -564,25 +564,27 @@ void LLFloaterTexturePicker::draw()
LLRect interior = border;
interior.stretch( -1 );
+ // If the floater is focused, don't apply its alpha to the texture (STORM-677).
+ const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
if( mTexturep )
{
if( mTexturep->getComponents() == 4 )
{
- gl_rect_2d_checkerboard( interior );
+ gl_rect_2d_checkerboard( interior, alpha );
}
- gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep );
+ gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha );
// Pump the priority
mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
}
else if (!mFallbackImage.isNull())
{
- mFallbackImage->draw(interior);
+ mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
}
else
{
- gl_rect_2d( interior, LLColor4::grey, TRUE );
+ gl_rect_2d( interior, LLColor4::grey % alpha, TRUE );
// Draw X
gl_draw_x(interior, LLColor4::black );
@@ -1263,23 +1265,25 @@ void LLTextureCtrl::draw()
LLRect interior = border;
interior.stretch( -1 );
+ // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677).
+ const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
if( mTexturep )
{
if( mTexturep->getComponents() == 4 )
{
- gl_rect_2d_checkerboard( interior );
+ gl_rect_2d_checkerboard( interior, alpha );
}
- gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep);
+ gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
}
else if (!mFallbackImage.isNull())
{
- mFallbackImage->draw(interior);
+ mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha);
}
else
{
- gl_rect_2d( interior, LLColor4::grey, TRUE );
+ gl_rect_2d( interior, LLColor4::grey % alpha, TRUE );
// Draw X
gl_draw_x( interior, LLColor4::black );
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index fafef84aa2..13fd51f473 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -299,6 +299,7 @@ public:
{
static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog");
static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator");
+ static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
if (log_to_viewer_log || log_to_sim)
{
@@ -332,6 +333,16 @@ public:
}
S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success);
+
+ if(log_texture_traffic && data_size > 0)
+ {
+ LLViewerTexture* tex = LLViewerTextureManager::findTexture(mID) ;
+ if(tex)
+ {
+ gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ;
+ }
+ }
+
mFetcher->removeFromHTTPQueue(mID, data_size);
}
else
@@ -1563,7 +1574,6 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
{
// Only do partial requests for J2C at the moment
- //llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;
desired_size = MAX_IMAGE_DATA_SIZE;
desired_discard = 0;
}
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index c87aff022f..b9a15fd1f4 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -514,7 +514,8 @@ void LLGLTexMemBar::draw()
F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
- S32 total_downloaded = BYTES_TO_MEGA_BYTES(gTotalTextureBytes);
+ F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
+ F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
@@ -525,13 +526,13 @@ void LLGLTexMemBar::draw()
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
- text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot: %d MB",
+ text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB",
total_mem,
max_total_mem,
bound_mem,
max_bound_mem,
LLImageRaw::sGlobalRawMemory >> 20, discard_bias,
- cache_usage, cache_max_usage, total_downloaded);
+ cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded);
//, cache_entries, cache_max_entries
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index c3090cb1fc..8916469e67 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -35,6 +35,13 @@
using namespace LLNotificationsUI;
+//--------------------------------------------------------------------------
+LLToastLifeTimer::LLToastLifeTimer(LLToast* toast, F32 period)
+ : mToast(toast),
+ LLEventTimer(period)
+{
+}
+
/*virtual*/
BOOL LLToastLifeTimer::tick()
{
@@ -45,6 +52,38 @@ BOOL LLToastLifeTimer::tick()
return FALSE;
}
+void LLToastLifeTimer::stop()
+{
+ mEventTimer.stop();
+}
+
+void LLToastLifeTimer::start()
+{
+ mEventTimer.start();
+}
+
+void LLToastLifeTimer::restart()
+{
+ mEventTimer.reset();
+}
+
+BOOL LLToastLifeTimer::getStarted()
+{
+ return mEventTimer.getStarted();
+}
+
+void LLToastLifeTimer::setPeriod(F32 period)
+{
+ mPeriod = period;
+}
+
+F32 LLToastLifeTimer::getRemainingTimeF32()
+{
+ F32 et = mEventTimer.getElapsedTimeF32();
+ if (!getStarted() || et > mPeriod) return 0.0f;
+ return mPeriod - et;
+}
+
//--------------------------------------------------------------------------
LLToast::Params::Params()
: can_fade("can_fade", true),
@@ -73,7 +112,8 @@ LLToast::LLToast(const LLToast::Params& p)
mIsHidden(false),
mHideBtnPressed(false),
mIsTip(p.is_tip),
- mWrapperPanel(NULL)
+ mWrapperPanel(NULL),
+ mIsTransparent(false)
{
mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs));
@@ -101,10 +141,6 @@ LLToast::LLToast(const LLToast::Params& p)
// init callbacks if present
if(!p.on_delete_toast().empty())
mOnDeleteToastSignal.connect(p.on_delete_toast());
-
- // *TODO: This signal doesn't seem to be used at all.
- if(!p.on_mouse_enter().empty())
- mOnMouseEnterSignal.connect(p.on_mouse_enter());
}
void LLToast::reshape(S32 width, S32 height, BOOL called_from_parent)
@@ -143,6 +179,7 @@ LLToast::~LLToast()
void LLToast::hide()
{
setVisible(FALSE);
+ setTransparentState(false);
mTimer->stop();
mIsHidden = true;
mOnFadeSignal(this);
@@ -166,6 +203,16 @@ void LLToast::onFocusReceived()
}
}
+void LLToast::setLifetime(S32 seconds)
+{
+ mToastLifetime = seconds;
+}
+
+void LLToast::setFadingTime(S32 seconds)
+{
+ mToastFadingTime = seconds;
+}
+
S32 LLToast::getTopPad()
{
if(mWrapperPanel)
@@ -195,13 +242,46 @@ void LLToast::setCanFade(bool can_fade)
//--------------------------------------------------------------------------
void LLToast::expire()
{
- // if toast has fade property - hide it
- if(mCanFade)
+ if (mCanFade)
{
- hide();
+ if (mIsTransparent)
+ {
+ hide();
+ }
+ else
+ {
+ setTransparentState(true);
+ mTimer->restart();
+ }
}
}
+void LLToast::setTransparentState(bool transparent)
+{
+ setBackgroundOpaque(!transparent);
+ mIsTransparent = transparent;
+
+ if (transparent)
+ {
+ mTimer->setPeriod(mToastFadingTime);
+ }
+ else
+ {
+ mTimer->setPeriod(mToastLifetime);
+ }
+}
+
+F32 LLToast::getTimeLeftToLive()
+{
+ F32 time_to_live = mTimer->getRemainingTimeF32();
+
+ if (!mIsTransparent)
+ {
+ time_to_live += mToastFadingTime;
+ }
+
+ return time_to_live;
+}
//--------------------------------------------------------------------------
void LLToast::reshapeToPanel()
@@ -245,13 +325,6 @@ void LLToast::draw()
drawChild(mHideBtn);
}
}
-
- // if timer started and remaining time <= fading time
- if (mTimer->getStarted() && (mToastLifetime
- - mTimer->getEventTimer().getElapsedTimeF32()) <= mToastFadingTime)
- {
- setBackgroundOpaque(FALSE);
- }
}
//--------------------------------------------------------------------------
@@ -267,6 +340,11 @@ void LLToast::setVisible(BOOL show)
return;
}
+ if (show && getVisible())
+ {
+ return;
+ }
+
if(show)
{
setBackgroundOpaque(TRUE);
@@ -320,7 +398,6 @@ void LLToast::onToastMouseEnter()
{
mHideBtn->setVisible(TRUE);
}
- mOnMouseEnterSignal(this);
mToastMouseEnterSignal(this, getValue());
}
}
@@ -372,7 +449,8 @@ void LLNotificationsUI::LLToast::stopFading()
{
if(mCanFade)
{
- stopTimer();
+ setTransparentState(false);
+ mTimer->stop();
}
}
@@ -380,7 +458,8 @@ void LLNotificationsUI::LLToast::startFading()
{
if(mCanFade)
{
- resetTimer();
+ setTransparentState(false);
+ mTimer->start();
}
}
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 0a96c092a0..d23e858c5c 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -49,14 +49,16 @@ class LLToast;
class LLToastLifeTimer: public LLEventTimer
{
public:
- LLToastLifeTimer(LLToast* toast, F32 period) : mToast(toast), LLEventTimer(period){}
+ LLToastLifeTimer(LLToast* toast, F32 period);
/*virtual*/
BOOL tick();
- void stop() { mEventTimer.stop(); }
- void start() { mEventTimer.start(); }
- void restart() {mEventTimer.reset(); }
- BOOL getStarted() { return mEventTimer.getStarted(); }
+ void stop();
+ void start();
+ void restart();
+ BOOL getStarted();
+ void setPeriod(F32 period);
+ F32 getRemainingTimeF32();
LLTimer& getEventTimer() { return mEventTimer;}
private :
@@ -80,10 +82,15 @@ public:
Optional<LLUUID> notif_id, //notification ID
session_id; //im session ID
Optional<LLNotificationPtr> notification;
- Optional<F32> lifetime_secs,
- fading_time_secs; // Number of seconds while a toast is fading
- Optional<toast_callback_t> on_delete_toast,
- on_mouse_enter;
+
+ //NOTE: Life time of a toast (i.e. period of time from the moment toast was shown
+ //till the moment when toast was hidden) is the sum of lifetime_secs and fading_time_secs.
+
+ Optional<F32> lifetime_secs, // Number of seconds while a toast is non-transparent
+ fading_time_secs; // Number of seconds while a toast is transparent
+
+
+ Optional<toast_callback_t> on_delete_toast;
Optional<bool> can_fade,
can_be_stored,
enable_hide_btn,
@@ -125,10 +132,8 @@ public:
LLPanel* getPanel() { return mPanel; }
// enable/disable Toast's Hide button
void setHideButtonEnabled(bool enabled);
- //
- void resetTimer() { mTimer->start(); }
//
- void stopTimer() { mTimer->stop(); }
+ F32 getTimeLeftToLive();
//
LLToastLifeTimer* getTimer() { return mTimer.get();}
//
@@ -136,7 +141,7 @@ public:
//
virtual void setVisible(BOOL show);
- /*virtual*/ void setBackgroundOpaque(BOOL b);
+ virtual void setBackgroundOpaque(BOOL b);
//
virtual void hide();
@@ -144,6 +149,10 @@ public:
/*virtual*/ void onFocusReceived();
+ void setLifetime(S32 seconds);
+
+ void setFadingTime(S32 seconds);
+
/**
* Returns padding between floater top and wrapper_panel top.
* This padding should be taken into account when positioning or reshaping toasts
@@ -172,7 +181,6 @@ public:
// Registers signals/callbacks for events
toast_signal_t mOnFadeSignal;
- toast_signal_t mOnMouseEnterSignal;
toast_signal_t mOnDeleteToastSignal;
toast_signal_t mOnToastDestroyedSignal;
boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFadeSignal.connect(cb); }
@@ -190,13 +198,17 @@ public:
LLHandle<LLToast> getHandle() { mHandle.bind(this); return mHandle; }
+ bool getTransparentState() const { return mIsTransparent; }
+ virtual void setTransparentState(bool transparent);
+
+
private:
void onToastMouseEnter();
void onToastMouseLeave();
- void expire();
+ void expire();
LLUUID mNotificationID;
LLUUID mSessionID;
@@ -222,6 +234,7 @@ private:
bool mHideBtnPressed;
bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
bool mIsTip;
+ bool mIsTransparent;
commit_signal_t mToastMouseEnterSignal;
commit_signal_t mToastMouseLeaveSignal;
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 371aad64bb..563c27c4d7 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -60,7 +60,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLGroupData groupData;
if (!gAgent.getGroupData(payload["group_id"].asUUID(),groupData))
{
- llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
+ llwarns << "Group notice for unknown group: " << payload["group_id"].asUUID() << llendl;
}
//group icon
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 9017f5ec55..3f7dc24ade 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -33,6 +33,7 @@
// library includes
#include "lldbstrings.h"
+#include "lllslconstants.h"
#include "llnotifications.h"
#include "lluiconstants.h"
#include "llrect.h"
@@ -70,11 +71,11 @@ mCloseNotificationOnDestroy(true)
mControlPanel = getChild<LLPanel>("control_panel");
BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth");
// customize panel's attributes
- // is it intended for displaying a tip
+ // is it intended for displaying a tip?
mIsTip = notification->getType() == "notifytip";
- // is it a script dialog
+ // is it a script dialog?
mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup");
- // is it a caution
+ // is it a caution?
//
// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
// notify xml template specifies that it is a caution
@@ -139,6 +140,12 @@ mCloseNotificationOnDestroy(true)
LLSD form_element = form->getElement(i);
if (form_element["type"].asString() != "button")
{
+ // not a button.
+ continue;
+ }
+ if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
+ {
+ // a textbox pretending to be a button.
continue;
}
LLButton* new_button = createButton(form_element, TRUE);
@@ -159,7 +166,7 @@ mCloseNotificationOnDestroy(true)
if(h_pad < 2*HPAD)
{
/*
- * Probably it is a scriptdialog toast
+ * Probably it is a scriptdialog toast
* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons.
* In last case set default h_pad to avoid heaping of buttons
*/
@@ -261,7 +268,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
}
else if (mIsScriptDialog && is_ignore_btn)
{
- // this is ignore button,make it smaller
+ // this is ignore button, make it smaller
p.rect.height = BTN_HEIGHT_SMALL;
p.rect.width = 1;
p.auto_resize = true;
diff --git a/indra/newview/lltoastscripttextbox.cpp b/indra/newview/lltoastscripttextbox.cpp
new file mode 100644
index 0000000000..c013f521cc
--- /dev/null
+++ b/indra/newview/lltoastscripttextbox.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file lltoastscripttextbox.cpp
+ * @brief Panel for script llTextBox dialogs
+ *
+ * $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 "lltoastscripttextbox.h"
+
+#include "llfocusmgr.h"
+
+#include "llbutton.h"
+#include "llnotifications.h"
+#include "llviewertexteditor.h"
+
+#include "llavatarnamecache.h"
+#include "lluiconstants.h"
+#include "llui.h"
+#include "llviewercontrol.h"
+#include "lltrans.h"
+#include "llstyle.h"
+
+#include "llglheaders.h"
+#include "llagent.h"
+
+const S32 LLToastScriptTextbox::DEFAULT_MESSAGE_MAX_LINE_COUNT= 7;
+
+LLToastScriptTextbox::LLToastScriptTextbox(LLNotificationPtr& notification)
+: LLToastNotifyPanel(notification)
+{
+ buildFromFile( "panel_notify_textbox.xml");
+
+ const LLSD& payload = notification->getPayload();
+
+ //message body
+ const std::string& message = payload["message"].asString();
+
+ LLViewerTextEditor* pMessageText = getChild<LLViewerTextEditor>("message");
+ pMessageText->clear();
+
+ LLStyle::Params style;
+ style.font = pMessageText->getDefaultFont();
+ pMessageText->appendText(message, TRUE, style);
+
+ //submit button
+ LLButton* pSubmitBtn = getChild<LLButton>("btn_submit");
+ pSubmitBtn->setClickedCallback((boost::bind(&LLToastScriptTextbox::onClickSubmit, this)));
+ setDefaultBtn(pSubmitBtn);
+
+ S32 maxLinesCount;
+ std::istringstream ss( getString("message_max_lines_count") );
+ if (!(ss >> maxLinesCount))
+ {
+ maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
+ }
+ //snapToMessageHeight(pMessageText, maxLinesCount);
+}
+
+// virtual
+LLToastScriptTextbox::~LLToastScriptTextbox()
+{
+}
+
+void LLToastScriptTextbox::close()
+{
+ die();
+}
+
+#include "lllslconstants.h"
+void LLToastScriptTextbox::onClickSubmit()
+{
+ LLViewerTextEditor* pMessageText = getChild<LLViewerTextEditor>("message");
+
+ if (pMessageText)
+ {
+ LLSD response = mNotification->getResponseTemplate();
+ response[TEXTBOX_MAGIC_TOKEN] = pMessageText->getText();
+ if (response[TEXTBOX_MAGIC_TOKEN].asString().empty())
+ {
+ // so we can distinguish between a successfully
+ // submitted blank textbox, and an ignored toast
+ response[TEXTBOX_MAGIC_TOKEN] = true;
+ }
+ mNotification->respond(response);
+ close();
+ llwarns << response << llendl;
+ }
+}
diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h
new file mode 100644
index 0000000000..ae3b545e0a
--- /dev/null
+++ b/indra/newview/lltoastscripttextbox.h
@@ -0,0 +1,58 @@
+/**
+ * @file lltoastscripttextbox.h
+ * @brief Panel for script llTextBox dialogs
+ *
+ * $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_LLTOASTSCRIPTTEXTBOX_H
+#define LL_LLTOASTSCRIPTTEXTBOX_H
+
+#include "lltoastnotifypanel.h"
+#include "llnotificationptr.h"
+
+class LLButton;
+
+/**
+ * Toast panel for scripted llTextbox notifications.
+ */
+class LLToastScriptTextbox
+: public LLToastNotifyPanel
+{
+public:
+ void close();
+
+ static bool onNewNotification(const LLSD& notification);
+
+ // Non-transient messages. You can specify non-default button
+ // layouts (like one for script dialogs) by passing various
+ // numbers in for "layout".
+ LLToastScriptTextbox(LLNotificationPtr& notification);
+
+ /*virtual*/ ~LLToastScriptTextbox();
+protected:
+ void onClickSubmit();
+private:
+ static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
+};
+
+#endif
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 78dd602f39..6deab96b45 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -36,8 +36,11 @@
LLTransientFloaterMgr::LLTransientFloaterMgr()
{
- gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
+ if(gViewerWindow)
+ {
+ gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+ }
mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(DOCKED, std::set<LLView*>()));
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 050e34ade9..8ccfdb071b 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -36,7 +36,7 @@
#include "llbufferstream.h"
#include "llui.h"
-#include "llversionviewer.h"
+#include "llversioninfo.h"
#include "llviewercontrol.h"
#include "jsoncpp/reader.h"
@@ -64,11 +64,11 @@ void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std
getTranslateUrl(url, from_lang, to_lang, mesg);
std::string user_agent = llformat("%s %d.%d.%d (%d)",
- LL_CHANNEL,
- LL_VERSION_MAJOR,
- LL_VERSION_MINOR,
- LL_VERSION_PATCH,
- LL_VERSION_BUILD );
+ LLVersionInfo::getChannel().c_str(),
+ LLVersionInfo::getMajor(),
+ LLVersionInfo::getMinor(),
+ LLVersionInfo::getPatch(),
+ LLVersionInfo::getBuild());
if (!m_Header.size())
{
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index 733d05834a..673d0c24cf 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -95,9 +95,42 @@ const std::string &LLVersionInfo::getShortVersion()
return version;
}
+namespace
+{
+ /// Storage of the channel name the viewer is using.
+ // The channel name is set by hardcoded constant,
+ // or by calling LLVersionInfo::resetChannel()
+ std::string sWorkingChannelName(LL_CHANNEL);
+
+ // Storage for the "version and channel" string.
+ // This will get reset too.
+ std::string sVersionChannel("");
+}
+
+//static
+const std::string &LLVersionInfo::getChannelAndVersion()
+{
+ if (sVersionChannel.empty())
+ {
+ // cache the version string
+ std::ostringstream stream;
+ stream << LLVersionInfo::getChannel()
+ << " "
+ << LLVersionInfo::getVersion();
+ sVersionChannel = stream.str();
+ }
+
+ return sVersionChannel;
+}
+
//static
const std::string &LLVersionInfo::getChannel()
{
- static std::string name(LL_CHANNEL);
- return name;
+ return sWorkingChannelName;
+}
+
+void LLVersionInfo::resetChannel(const std::string& channel)
+{
+ sWorkingChannelName = channel;
+ sVersionChannel.clear(); // Reset version and channel string til next use.
}
diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h
index e468b6ae4e..6f64544f3b 100644
--- a/indra/newview/llversioninfo.h
+++ b/indra/newview/llversioninfo.h
@@ -58,8 +58,15 @@ public:
/// return the viewer version as a string like "2.0.0"
static const std::string &getShortVersion();
+ /// return the viewer version and channel as a string
+ /// like "Second Life Release 2.0.0.200030"
+ static const std::string &getChannelAndVersion();
+
/// return the channel name, e.g. "Second Life"
static const std::string &getChannel();
+
+ /// reset the channel name used by the viewer.
+ static void resetChannel(const std::string& channel);
};
#endif
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index fbec2a7b9e..622d09c600 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -70,6 +70,7 @@
#include "llpaneloutfitsinventory.h"
#include "llpanellogin.h"
#include "llpaneltopinfobar.h"
+#include "llupdaterservice.h"
#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
BOOL gHackGodmode = FALSE;
@@ -82,7 +83,6 @@ LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session
LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings
std::string gLastRunVersion;
-std::string gCurrentVersion;
extern BOOL gResizeScreenTexture;
extern BOOL gDebugGL;
@@ -117,10 +117,23 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
gBumpImageList.destroyGL();
gBumpImageList.restoreGL();
+ // Changing shader also changes the terrain detail to high, reflect that change here
+ if (newvalue.asBoolean())
+ {
+ // shaders enabled, set terrain detail to high
+ gSavedSettings.setS32("RenderTerrainDetail", 1);
+ }
+ // else, leave terrain detail as is
LLViewerShaderMgr::instance()->setShaders();
return true;
}
+bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
+{
+ LLWorld::getInstance()->updateWaterObjects();
+ return true;
+}
+
static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
{
if (gPipeline.isInit())
@@ -489,6 +502,18 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)
return true;
}
+void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_value)
+{
+ if(new_value.asBoolean())
+ {
+ LLUpdaterService().startChecking();
+ }
+ else
+ {
+ LLUpdaterService().stopChecking();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////
void settings_setup_listeners()
@@ -636,7 +661,9 @@ void settings_setup_listeners()
gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2));
gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2));
gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2));
+ gSavedSettings.getControl("UpdaterServiceActive")->getSignal()->connect(&toggle_updater_service_active);
gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2));
+ gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2));
}
#if TEST_CACHED_CONTROL
diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h
index 22b48f8906..d7191f5c8d 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -57,7 +57,5 @@ extern LLControlGroup gCrashSettings;
// Set after settings loaded
extern std::string gLastRunVersion;
-extern std::string gCurrentVersion;
-
#endif // LL_LLVIEWERCONTROL_H
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 40583f05bf..ddb11829df 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -95,6 +95,7 @@ BOOL gForceRenderLandFence = FALSE;
BOOL gDisplaySwapBuffers = FALSE;
BOOL gDepthDirty = FALSE;
BOOL gResizeScreenTexture = FALSE;
+BOOL gWindowResized = FALSE;
BOOL gSnapshot = FALSE;
U32 gRecentFrameCount = 0; // number of 'recent' frames
@@ -218,22 +219,15 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLMemType mt_render(LLMemType::MTYPE_RENDER);
LLFastTimer t(FTM_RENDER);
- if (gResizeScreenTexture)
- { //skip render on frames where screen texture is resizing
+ if (gWindowResized)
+ { //skip render on frames where window has been resized
gGL.flush();
- if (!for_snapshot)
- {
- glClear(GL_COLOR_BUFFER_BIT);
- gViewerWindow->mWindow->swapBuffers();
- }
-
- gResizeScreenTexture = FALSE;
+ glClear(GL_COLOR_BUFFER_BIT);
+ gViewerWindow->mWindow->swapBuffers();
gPipeline.resizeScreenTexture();
-
- if (!for_snapshot)
- {
- return;
- }
+ gResizeScreenTexture = FALSE;
+ gWindowResized = FALSE;
+ return;
}
if (LLPipeline::sRenderDeferred)
@@ -597,7 +591,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
S32 water_clip = 0;
if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
- gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))
+ (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) ||
+ gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
{
if (LLViewerCamera::getInstance()->cameraUnderWater())
{
@@ -665,11 +660,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLVertexBuffer::clientCopy(0.016);
}
- //if (gResizeScreenTexture)
- //{
- // gResizeScreenTexture = FALSE;
- // gPipeline.resizeScreenTexture();
- //}
+ if (gResizeScreenTexture)
+ {
+ gResizeScreenTexture = FALSE;
+ gPipeline.resizeScreenTexture();
+ }
gGL.setColorMask(true, true);
glClearColor(0,0,0,0);
@@ -730,7 +725,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
//
// Doing this here gives hardware occlusion queries extra time to complete
LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
- LLError::LLCallStacks::clear() ;
{
LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
diff --git a/indra/newview/llviewerdisplay.h b/indra/newview/llviewerdisplay.h
index c6e86751e8..f6467d7f93 100644
--- a/indra/newview/llviewerdisplay.h
+++ b/indra/newview/llviewerdisplay.h
@@ -40,5 +40,6 @@ extern BOOL gTeleportDisplay;
extern LLFrameTimer gTeleportDisplayTimer;
extern BOOL gForceRenderLandFence;
extern BOOL gResizeScreenTexture;
+extern BOOL gWindowResized;
#endif // LL_LLVIEWERDISPLAY_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index b3f14b441d..f573f25efe 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -81,6 +81,7 @@
#include "llfloaterpostprocess.h"
#include "llfloaterpreference.h"
#include "llfloaterproperties.h"
+#include "llfloaterregiondebugconsole.h"
#include "llfloaterregioninfo.h"
#include "llfloaterreporter.h"
#include "llfloaterscriptdebug.h"
@@ -227,6 +228,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("reporter", "floater_report_abuse.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterReporter>);
LLFloaterReg::add("reset_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterResetQueue>);
+ LLFloaterReg::add("region_debug_console", "floater_region_debug_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionDebugConsole>);
LLFloaterReg::add("region_info", "floater_region_info.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRegionInfo>);
LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index 0cf5fe0ada..baf85d6884 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -257,7 +257,7 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy )
// if object is transparent, defer it, otherwise
// give the joint subclass a chance to draw itself
//----------------------------------------------------------------
- if ( gRenderForSelect || is_dummy )
+ if ( is_dummy )
{
triangle_count += drawShape( pixelArea, first_pass, is_dummy );
}
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index ae2aa41b3a..e59e685f53 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -61,7 +61,6 @@ extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
#endif
-extern BOOL gRenderForSelect;
static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;
static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
@@ -515,17 +514,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
//----------------------------------------------------------------
// setup current color
//----------------------------------------------------------------
- if (!gRenderForSelect)
- {
- if (is_dummy)
- glColor4fv(LLVOAvatar::getDummyColor().mV);
- else
- glColor4fv(mColor.mV);
- }
+ if (is_dummy)
+ glColor4fv(LLVOAvatar::getDummyColor().mV);
+ else
+ glColor4fv(mColor.mV);
stop_glerror();
- LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
+ LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
//----------------------------------------------------------------
// setup current texture
@@ -580,19 +576,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
- if (gRenderForSelect)
- {
- if (isTransparent())
- {
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
- gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA);
- }
- else
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- }
-
mFace->mVertexBuffer->setBuffer(sRenderMask);
U32 start = mMesh->mFaceVertexOffset;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 48ab122edf..fae4eb3c05 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -492,7 +492,7 @@ std::string LLViewerMedia::getCurrentUserAgent()
// Just in case we need to check browser differences in A/B test
// builds.
- std::string channel = gSavedSettings.getString("VersionChannelName");
+ std::string channel = LLVersionInfo::getChannel();
// append our magic version number string to the browser user agent id
// See the HTTP 1.0 and 1.1 specifications for allowed formats:
@@ -1083,7 +1083,7 @@ void LLViewerMedia::clearAllCookies()
}
// the hard part: iterate over all user directories and delete the cookie file from each one
- while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename, false))
+ while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename))
{
target = base_dir;
target += filename;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ccf3df827d..03490034d8 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -221,8 +221,6 @@ BOOL check_show_xui_names(void *);
// Debug UI
void handle_buy_currency_test(void*);
-void handle_save_to_xml(void*);
-void handle_load_from_xml(void*);
void handle_god_mode(void*);
@@ -1384,37 +1382,6 @@ class LLAdvancedCheckDebugWindowProc : public view_listener_t
// ------------------------------XUI MENU ---------------------------
-//////////////////////
-// LOAD UI FROM XML //
-//////////////////////
-
-
-class LLAdvancedLoadUIFromXML : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- handle_load_from_xml(NULL);
- return true;
-}
-};
-
-
-
-////////////////////
-// SAVE UI TO XML //
-////////////////////
-
-
-class LLAdvancedSaveUIToXML : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- handle_save_to_xml(NULL);
- return true;
-}
-};
-
-
class LLAdvancedSendTestIms : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -1994,6 +1961,16 @@ class LLAdvancedShowDebugSettings : public view_listener_t
// VIEW ADMIN OPTIONS //
////////////////////////
+class LLAdvancedEnableViewAdminOptions : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ // Don't enable in god mode since the admin menu is shown anyway.
+ // Only enable if the user has set the appropriate debug setting.
+ bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu");
+ return new_value;
+ }
+};
class LLAdvancedToggleViewAdminOptions : public view_listener_t
{
@@ -2008,7 +1985,7 @@ class LLAdvancedCheckViewAdminOptions : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- bool new_value = check_admin_override(NULL);
+ bool new_value = check_admin_override(NULL) || gAgent.isGodlike();
return new_value;
}
};
@@ -4160,6 +4137,11 @@ class LLObjectEnableReturn : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ // Do not enable if nothing selected
+ return false;
+ }
#ifdef HACKED_GODLIKE_VIEWER
bool new_value = true;
#else
@@ -6518,16 +6500,6 @@ class LLToggleControl : public view_listener_t
std::string control_name = userdata.asString();
BOOL checked = gSavedSettings.getBOOL( control_name );
gSavedSettings.setBOOL( control_name, !checked );
-
- // Doubleclick actions - there can be only one
- if ((control_name == "DoubleClickAutoPilot") && !checked)
- {
- gSavedSettings.setBOOL( "DoubleClickTeleport", FALSE );
- }
- else if ((control_name == "DoubleClickTeleport") && !checked)
- {
- gSavedSettings.setBOOL( "DoubleClickAutoPilot", FALSE );
- }
return true;
}
};
@@ -7183,44 +7155,6 @@ const LLRect LLViewerMenuHolderGL::getMenuRect() const
return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT);
}
-void handle_save_to_xml(void*)
-{
- LLFloater* frontmost = gFloaterView->getFrontmost();
- if (!frontmost)
- {
- LLNotificationsUtil::add("NoFrontmostFloater");
- return;
- }
-
- std::string default_name = "floater_";
- default_name += frontmost->getTitle();
- default_name += ".xml";
-
- LLStringUtil::toLower(default_name);
- LLStringUtil::replaceChar(default_name, ' ', '_');
- LLStringUtil::replaceChar(default_name, '/', '_');
- LLStringUtil::replaceChar(default_name, ':', '_');
- LLStringUtil::replaceChar(default_name, '"', '_');
-
- LLFilePicker& picker = LLFilePicker::instance();
- if (picker.getSaveFile(LLFilePicker::FFSAVE_XML, default_name))
- {
- std::string filename = picker.getFirstFile();
- LLUICtrlFactory::getInstance()->saveToXML(frontmost, filename);
- }
-}
-
-void handle_load_from_xml(void*)
-{
- LLFilePicker& picker = LLFilePicker::instance();
- if (picker.getOpenFile(LLFilePicker::FFLOAD_XML))
- {
- std::string filename = picker.getFirstFile();
- LLFloater* floater = new LLFloater(LLSD());
- floater->buildFromFile(filename);
- }
-}
-
void handle_web_browser_test(const LLSD& param)
{
std::string url = param.asString();
@@ -7861,6 +7795,9 @@ void initialize_menus()
view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
+ // Me > Movement
+ view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
+
// World menu
commit.add("World.Chat", boost::bind(&handle_chat, (void*)NULL));
view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
@@ -7934,9 +7871,6 @@ void initialize_menus()
// Advanced Other Settings
view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
-
- // Advanced > Shortcuts
- view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
// Advanced > Render > Types
view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
@@ -8006,8 +7940,6 @@ void initialize_menus()
// Advanced > XUI
commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance()));
- view_listener_t::addMenu(new LLAdvancedLoadUIFromXML(), "Advanced.LoadUIFromXML");
- view_listener_t::addMenu(new LLAdvancedSaveUIToXML(), "Advanced.SaveUIToXML");
view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
@@ -8068,6 +8000,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
+ view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");
view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions");
view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 237aa39e6e..048691696b 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -404,8 +404,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
gSavedSettings.getBOOL("RenderUIInSnapshot"),
FALSE))
{
- gViewerWindow->playSnapshotAnimAndSound();
-
LLPointer<LLImageFormatted> formatted;
switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat")))
{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9b1f2e67c6..5cbd5ffa0b 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -39,6 +39,7 @@
#include "llfloaterreg.h"
#include "llfollowcamparams.h"
#include "llinventorydefines.h"
+#include "lllslconstants.h"
#include "llregionhandle.h"
#include "llsdserialize.h"
#include "llteleportflags.h"
@@ -638,7 +639,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
if(option == 0 && !group_id.isNull())
{
// check for promotion or demotion.
- S32 max_groups = MAX_AGENT_GROUPS;
+ S32 max_groups = gMaxAgentGroups;
if(gAgent.isInGroup(group_id)) ++max_groups;
if(gAgent.mGroups.count() < max_groups)
@@ -1199,7 +1200,6 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
const BOOL auto_open =
gSavedSettings.getBOOL("ShowInInventory") && // don't open if showininventory is false
!(asset_type == LLAssetType::AT_CALLINGCARD) && // don't open if it's a calling card
- !(item && (item->getInventoryType() == LLInventoryType::IT_ATTACHMENT)) && // don't open if it's an item that's an attachment
!from_name.empty(); // don't open if it's not from anyone.
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open);
if(active_panel)
@@ -1511,7 +1511,12 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// MUTE falls through to decline
case IOR_DECLINE:
{
- log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +".";
+ {
+ LLStringUtil::format_map_t log_message_args;
+ log_message_args["DESC"] = mDesc;
+ log_message_args["NAME"] = mFromName;
+ log_message = LLTrans::getString("InvOfferDecline", log_message_args);
+ }
chat.mText = log_message;
if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
{
@@ -1710,8 +1715,12 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
// send the message
msg->sendReliable(mHost);
-
- log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +".";
+ {
+ LLStringUtil::format_map_t log_message_args;
+ log_message_args["DESC"] = mDesc;
+ log_message_args["NAME"] = mFromName;
+ log_message = LLTrans::getString("InvOfferDecline", log_message_args);
+ }
LLSD args;
args["MESSAGE"] = log_message;
LLNotificationsUtil::add("SystemMessage", args);
@@ -2501,15 +2510,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
S32 membership_fee = ntohl(invite_bucket->membership_fee);
- // IDEVO Clean up legacy name "Resident" in message constructed in
- // lldatagroups.cpp
- U32 pos = message.find(" has invited you to join a group.\n");
- if (pos != std::string::npos)
- {
- // use cleaned-up name from above
- message = name + message.substr(pos);
- }
-
LLSD payload;
payload["transaction_id"] = session_id;
payload["group_id"] = from_id;
@@ -3032,6 +3032,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
}
else
{
+ args["NAME"] = source_name;
LLNotificationsUtil::add("OfferCallingCard", args, payload);
}
}
@@ -3867,6 +3868,7 @@ void process_crossed_region(LLMessageSystem* msg, void**)
return;
}
LL_INFOS("Messaging") << "process_crossed_region()" << LL_ENDL;
+ gAgentAvatarp->resetRegionCrossingTimer();
U32 sim_ip;
msg->getIPAddrFast(_PREHASH_RegionData, _PREHASH_SimIP, sim_ip);
@@ -6435,8 +6437,22 @@ const char* SCRIPT_DIALOG_HEADER = "Script Dialog:\n";
bool callback_script_dialog(const LLSD& notification, const LLSD& response)
{
LLNotificationForm form(notification["form"]);
- std::string button = LLNotification::getSelectedOptionName(response);
- S32 button_idx = LLNotification::getSelectedOption(notification, response);
+
+ std::string rtn_text;
+ S32 button_idx;
+ button_idx = LLNotification::getSelectedOption(notification, response);
+ if (response[TEXTBOX_MAGIC_TOKEN].isDefined())
+ {
+ if (response[TEXTBOX_MAGIC_TOKEN].isString())
+ rtn_text = response[TEXTBOX_MAGIC_TOKEN].asString();
+ else
+ rtn_text.clear(); // bool marks empty string
+ }
+ else
+ {
+ rtn_text = LLNotification::getSelectedOptionName(response);
+ }
+
// Didn't click "Ignore"
if (button_idx != -1)
{
@@ -6449,7 +6465,7 @@ bool callback_script_dialog(const LLSD& notification, const LLSD& response)
msg->addUUID("ObjectID", notification["payload"]["object_id"].asUUID());
msg->addS32("ChatChannel", notification["payload"]["chat_channel"].asInteger());
msg->addS32("ButtonIndex", button_idx);
- msg->addString("ButtonLabel", button);
+ msg->addString("ButtonLabel", rtn_text);
msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index a58b0d68de..1804fac1b3 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -103,8 +103,8 @@
//#define DEBUG_UPDATE_TYPE
-BOOL gVelocityInterpolate = TRUE;
-BOOL gPingInterpolate = TRUE;
+BOOL LLViewerObject::sVelocityInterpolate = TRUE;
+BOOL LLViewerObject::sPingInterpolate = TRUE;
U32 LLViewerObject::sNumZombieObjects = 0;
S32 LLViewerObject::sNumObjects = 0;
@@ -115,6 +115,11 @@ S32 LLViewerObject::sAxisArrowLength(50);
BOOL LLViewerObject::sPulseEnabled(FALSE);
BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
+// sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime
+F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion
+F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction
+
+
static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
// static
@@ -168,8 +173,10 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
res = new LLVOSurfacePatch(id, pcode, regionp); break;
case LL_VO_SKY:
res = new LLVOSky(id, pcode, regionp); break;
+ case LL_VO_VOID_WATER:
+ res = new LLVOVoidWater(id, pcode, regionp); break;
case LL_VO_WATER:
- res = new LLVOWater(id, pcode, regionp); break;
+ res = new LLVOWater(id, pcode, regionp); break;
case LL_VO_GROUND:
res = new LLVOGround(id, pcode, regionp); break;
case LL_VO_PART_GROUP:
@@ -203,6 +210,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mLastInterpUpdateSecs(0.f),
mLastMessageUpdateSecs(0.f),
mLatestRecvPacketID(0),
+ mCircuitPacketCount(0),
mData(NULL),
mAudioSourcep(NULL),
mAudioGain(1.f),
@@ -1839,7 +1847,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.normQuat();
- if (gPingInterpolate)
+ if (sPingInterpolate)
{
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
if (cdp)
@@ -1860,6 +1868,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
//
//
+ // WTF? 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 &&
mLatestRecvPacketID - packet_id < 65536)
@@ -1869,6 +1879,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
mLatestRecvPacketID = packet_id;
+ mCircuitPacketCount = 0;
// Set the change flags for scale
if (new_scale != getScale())
@@ -2000,7 +2011,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay();
mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
- mLastMessageUpdateSecs = LLFrameTimer::getElapsedSeconds();
+ mLastMessageUpdateSecs = mLastInterpUpdateSecs;
if (mDrawable.notNull())
{
// Don't clear invisibility flag on update if still orphaned!
@@ -2027,6 +2038,8 @@ BOOL LLViewerObject::isActive() const
return TRUE;
}
+
+
BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
static LLFastTimer::DeclareTimer ftm("Viewer Object");
@@ -2040,7 +2053,7 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// CRO - don't velocity interp linked objects!
// Leviathan - but DO velocity interp joints
- if (!mStatic && gVelocityInterpolate && !isSelected())
+ if (!mStatic && sVelocityInterpolate && !isSelected())
{
// calculate dt from last update
F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
@@ -2130,33 +2143,8 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
return TRUE;
}
else
- {
- // linear motion
- // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
- // updates represents the average velocity of the last timestep, rather than the final velocity.
- // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically
- //
- // There is a problem here if dt is negative. . .
-
- // *TODO: should also wrap linear accel/velocity in check
- // to see if object is selected, instead of explicitly
- // zeroing it out
- LLVector3 accel = getAcceleration();
- LLVector3 vel = getVelocity();
-
- if (!(accel.isExactlyZero() && vel.isExactlyZero()))
- {
- LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
-
- // region local
- setPositionRegion(pos + getPositionRegion());
- setVelocity(vel + accel*dt);
-
- // for objects that are spinning but not translating, make sure to flag them as having moved
- setChanged(MOVED | SILHOUETTE);
- }
-
- mLastInterpUpdateSecs = time;
+ { // Move object based on it's velocity and rotation
+ interpolateLinearMotion(time, dt);
}
}
@@ -2172,6 +2160,158 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
}
+// Move an object due to idle-time viewer side updates by iterpolating motion
+void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt)
+{
+ // linear motion
+ // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
+ // updates represents the average velocity of the last timestep, rather than the final velocity.
+ // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically
+ //
+ // *TODO: should also wrap linear accel/velocity in check
+ // to see if object is selected, instead of explicitly
+ // zeroing it out
+
+ F64 time_since_last_update = time - mLastMessageUpdateSecs;
+ if (time_since_last_update <= 0.0 || dt <= 0.f)
+ {
+ return;
+ }
+
+ LLVector3 accel = getAcceleration();
+ LLVector3 vel = getVelocity();
+
+ if (sMaxUpdateInterpolationTime <= 0.0)
+ { // Old code path ... unbounded, simple interpolation
+ if (!(accel.isExactlyZero() && vel.isExactlyZero()))
+ {
+ LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
+
+ // region local
+ setPositionRegion(pos + getPositionRegion());
+ setVelocity(vel + accel*dt);
+
+ // for objects that are spinning but not translating, make sure to flag them as having moved
+ setChanged(MOVED | SILHOUETTE);
+ }
+ }
+ else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving
+ { // Object is moving, and hasn't been too long since we got an update from the server
+
+ // Calculate predicted position and velocity
+ LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
+ LLVector3 new_v = accel * dt;
+
+ if (time_since_last_update > sPhaseOutUpdateInterpolationTime)
+ { // Haven't seen a viewer update in a while, check to see if the ciruit is still active
+ if (mRegionp)
+ { // The simulator will NOT send updates if the object continues normally on the path
+ // predicted by the velocity and the acceleration (often gravity) sent to the viewer
+ // So check to see if the circuit is blocked, which means the sim is likely in a long lag
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() );
+ if (cdp)
+ {
+ if (!cdp->isAlive() || // Circuit is dead or blocked
+ cdp->isBlocked() || // or doesn't seem to be getting any packets
+ (mCircuitPacketCount > 0 && mCircuitPacketCount == cdp->getPacketsIn()))
+ {
+ // Start to reduce motion interpolation since we haven't seen a server update in a while
+ F64 time_since_last_interpolation = time - mLastInterpUpdateSecs;
+ F64 phase_out = 1.0;
+ if (time_since_last_update > sMaxUpdateInterpolationTime)
+ { // Past the time limit, so stop the object
+ phase_out = 0.0;
+ //llinfos << "Motion phase out to zero" << llendl;
+
+ // Kill angular motion as well. Note - not adding this due to paranoia
+ // about stopping rotation for llTargetOmega objects and not having it restart
+ // setAngularVelocity(LLVector3::zero);
+ }
+ else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime)
+ { // Last update was already phased out a bit
+ phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) /
+ (sMaxUpdateInterpolationTime - time_since_last_interpolation);
+ //llinfos << "Continuing motion phase out of " << (F32) phase_out << llendl;
+ }
+ else
+ { // Phase out from full value
+ phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) /
+ (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime);
+ //llinfos << "Starting motion phase out of " << (F32) phase_out << llendl;
+ }
+ phase_out = llclamp(phase_out, 0.0, 1.0);
+
+ new_pos = new_pos * ((F32) phase_out);
+ new_v = new_v * ((F32) phase_out);
+ }
+
+ // Save current circuit packet count to see if it changes
+ mCircuitPacketCount = cdp->getPacketsIn();
+ }
+ }
+ }
+
+ new_pos = new_pos + getPositionRegion();
+ new_v = new_v + vel;
+
+
+ // Clamp interpolated position to minimum underground and maximum region height
+ LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos);
+ F32 min_height;
+ if (isAvatar())
+ { // Make a better guess about AVs not going underground
+ min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global);
+ min_height += (0.5f * getScale().mV[VZ]);
+ }
+ else
+ { // This will put the object underground, but we can't tell if it will stop
+ // at ground level or not
+ min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global);
+ }
+
+ new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]);
+ new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]);
+
+ // Check to see if it's going off the region
+ LLVector3 temp(new_pos);
+ if (temp.clamp(0.f, mRegionp->getWidth()))
+ { // Going off this region, so see if we might end up on another region
+ LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());
+ new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above
+
+ // Clip the positions to known regions
+ LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global);
+ if (clip_pos_global != new_pos_global)
+ { // Was clipped, so this means we hit a edge where there is no region to enter
+
+ //llinfos << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global)
+ // << " from " << new_pos << llendl;
+ new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global);
+
+ // Stop motion and get server update for bouncing on the edge
+ new_v.clear();
+ setAcceleration(LLVector3::zero);
+ }
+ else
+ { // Let predicted movement cross into another region
+ //llinfos << "Predicting region crossing to " << new_pos << llendl;
+ }
+ }
+
+ // Set new position and velocity
+ setPositionRegion(new_pos);
+ setVelocity(new_v);
+
+ // for objects that are spinning but not translating, make sure to flag them as having moved
+ setChanged(MOVED | SILHOUETTE);
+ }
+
+ // Update the last time we did anything
+ mLastInterpUpdateSecs = time;
+}
+
+
+
BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
{
LLMemType mt(LLMemType::MTYPE_OBJECT);
@@ -4960,6 +5100,7 @@ void LLViewerObject::setRegion(LLViewerRegion *regionp)
}
mLatestRecvPacketID = 0;
+ mCircuitPacketCount = 0;
mRegionp = regionp;
for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
@@ -4972,6 +5113,20 @@ void LLViewerObject::setRegion(LLViewerRegion *regionp)
updateDrawable(FALSE);
}
+// virtual
+void LLViewerObject::updateRegion(LLViewerRegion *regionp)
+{
+// if (regionp)
+// {
+// F64 now = LLFrameTimer::getElapsedSeconds();
+// llinfos << "Updating to region " << regionp->getName()
+// << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0)
+// << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0)
+// << llendl;
+// }
+}
+
+
bool LLViewerObject::specialHoverCursor() const
{
return (mFlags & FLAGS_USE_PHYSICS)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 7d697a4a5f..fe670f8827 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -131,7 +131,7 @@ public:
typedef const child_list_t const_child_list_t;
- LLViewerObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp, BOOL is_global = FALSE);
+ LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE);
MEM_TYPE_NEW(LLMemType::MTYPE_OBJECT);
virtual void markDead(); // Mark this object as dead, and clean up its references
@@ -464,7 +464,7 @@ public:
bool specialHoverCursor() const; // does it have a special hover cursor?
void setRegion(LLViewerRegion *regionp);
- virtual void updateRegion(LLViewerRegion *regionp) {}
+ virtual void updateRegion(LLViewerRegion *regionp);
void updateFlags();
BOOL setFlags(U32 flag, BOOL state);
@@ -510,6 +510,9 @@ private:
// and the update wasn't due to this agent's last action.
U32 checkMediaURL(const std::string &media_url);
+ // Motion prediction between updates
+ void interpolateLinearMotion(const F64 & time, const F32 & dt);
+
public:
//
// Viewer-side only types - use the LL_PCODE_APP mask.
@@ -518,14 +521,14 @@ public:
{
LL_VO_CLOUDS = LL_PCODE_APP | 0x20,
LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30,
- //LL_VO_STARS = LL_PCODE_APP | 0x40,
+ LL_VO_WL_SKY = LL_PCODE_APP | 0x40,
LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50,
LL_VO_SKY = LL_PCODE_APP | 0x60,
- LL_VO_WATER = LL_PCODE_APP | 0x70,
- LL_VO_GROUND = LL_PCODE_APP | 0x80,
- LL_VO_PART_GROUP = LL_PCODE_APP | 0x90,
- LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xa0,
- LL_VO_WL_SKY = LL_PCODE_APP | 0xb0, // should this be moved to 0x40?
+ LL_VO_VOID_WATER = LL_PCODE_APP | 0x70,
+ LL_VO_WATER = LL_PCODE_APP | 0x80,
+ LL_VO_GROUND = LL_PCODE_APP | 0x90,
+ LL_VO_PART_GROUP = LL_PCODE_APP | 0xa0,
+ LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xb0,
LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0,
} EVOType;
@@ -612,6 +615,8 @@ protected:
F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation
F64 mLastMessageUpdateSecs; // Last update from a message from the simulator
TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator
+ U32 mCircuitPacketCount; // Packet tracking for early detection of a stopped simulator circuit
+
// extra data sent from the sim...currently only used for tree species info
U8* mData;
@@ -669,9 +674,21 @@ protected:
mutable LLVector3 mPositionRegion;
mutable LLVector3 mPositionAgent;
+ static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; }
+ static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; }
+
+ static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; }
+ static void setPingInterpolate(BOOL value) { sPingInterpolate = value; }
+
private:
static S32 sNumObjects;
+ static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation
+ static F64 sMaxUpdateInterpolationTime; // For motion interpolation
+
+ static BOOL sVelocityInterpolate;
+ static BOOL sPingInterpolate;
+
//--------------------------------------------------------------------
// For objects that are attachments
//--------------------------------------------------------------------
@@ -717,8 +734,8 @@ public:
class LLAlphaObject : public LLViewerObject
{
public:
- LLAlphaObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp)
- : LLViewerObject(id,type,regionp)
+ LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
+ : LLViewerObject(id,pcode,regionp)
{ mDepth = 0.f; }
virtual F32 getPartSize(S32 idx);
@@ -735,14 +752,12 @@ public:
class LLStaticViewerObject : public LLViewerObject
{
public:
- LLStaticViewerObject(const LLUUID& id, const LLPCode type, LLViewerRegion* regionp, BOOL is_global = FALSE)
- : LLViewerObject(id,type,regionp, is_global)
+ LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE)
+ : LLViewerObject(id,pcode,regionp, is_global)
{ }
virtual void updateDrawable(BOOL force_damped);
};
-extern BOOL gVelocityInterpolate;
-extern BOOL gPingInterpolate;
#endif
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index b597e6148e..f5a32438cf 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -165,6 +165,11 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
{
U32 local_id = object.mLocalID;
LLHost region_host = object.getRegion()->getHost();
+ if(!region_host.isOk())
+ {
+ return FALSE ;
+ }
+
U32 ip = region_host.getAddress();
U32 port = region_host.getPort();
U64 ipport = (((U64)ip) << 32) | (U64)port;
@@ -654,9 +659,24 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
{
LLMemType mt(LLMemType::MTYPE_OBJECT);
+
// Update globals
- gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate");
- gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate");
+ LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") );
+ LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") );
+
+ F32 interp_time = gSavedSettings.getF32("InterpolationTime");
+ F32 phase_out_time = gSavedSettings.getF32("InterpolationPhaseOut");
+ if (interp_time < 0.0 ||
+ phase_out_time < 0.0 ||
+ phase_out_time > interp_time)
+ {
+ llwarns << "Invalid values for InterpolationTime or InterpolationPhaseOut, resetting to defaults" << llendl;
+ interp_time = 3.0f;
+ phase_out_time = 1.0f;
+ }
+ LLViewerObject::setPhaseOutUpdateInterpolationTime( interp_time );
+ LLViewerObject::setMaxUpdateInterpolationTime( phase_out_time );
+
gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
// update global timer
@@ -1269,34 +1289,6 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
}
}
-void LLViewerObjectList::renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent)
-{
- gRenderForSelect = TRUE;
-
- gPipeline.renderForSelect(mSelectPickList, render_transparent, screen_rect);
-
- //
- // Render pass for selected objects
- //
- gGL.color4f(1,1,1,1);
- gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE );
-
- //fix for DEV-19335. Don't pick hud objects when customizing avatar (camera mode doesn't play nice with nametags).
- if (!gAgentCamera.cameraCustomizeAvatar())
- {
- // render pickable ui elements, like names, etc.
- LLHUDObject::renderAllForSelect();
- }
-
- gGL.flush();
- LLVertexBuffer::unbind();
-
- gRenderForSelect = FALSE;
-
- //llinfos << "Rendered " << count << " for select" << llendl;
- //llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl;
-}
-
LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
{
std::set<LLViewerObject*>::iterator pick_it;
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index eba5584b57..605bac8e89 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -104,7 +104,6 @@ public:
// Selection related stuff
void generatePickList(LLCamera &camera);
- void renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent);
LLViewerObject *getSelectedObject(const U32 object_id);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7fb259e012..ca07e7c4cf 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -266,6 +266,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
//MUST MATCH declaration of eObjectPartitions
mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD
mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN
+ mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER
mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
@@ -1399,6 +1400,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
capabilityNames.append("SetDisplayName");
+ capabilityNames.append("SimConsole");
+ capabilityNames.append("SimConsoleAsync");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TextureStats");
capabilityNames.append("UntrustedSimulatorMessage");
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 1ba025312b..8b71998f60 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -73,6 +73,7 @@ public:
{
PARTITION_HUD=0,
PARTITION_TERRAIN,
+ PARTITION_VOIDWATER,
PARTITION_WATER,
PARTITION_TREE,
PARTITION_PARTICLE,
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index d078c15316..c1abead36e 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -335,8 +335,8 @@ void LLViewerShaderMgr::setShaders()
}
else
{
- LLPipeline::sRenderGlow =
- LLPipeline::sWaterReflections = FALSE;
+ LLPipeline::sRenderGlow = FALSE;
+ LLPipeline::sWaterReflections = FALSE;
}
//hack to reset buffers that change behavior with shaders
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 42266ad233..546ee9a334 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -48,6 +48,7 @@
#include "llagent.h"
#include "llagentcamera.h"
#include "llviewercontrol.h"
+#include "llversioninfo.h"
#include "llfloatertools.h"
#include "lldebugview.h"
#include "llfasttimerview.h"
@@ -558,7 +559,7 @@ F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f;
U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0;
U32 gObjectBits = 0;
F32 gAvgSimPing = 0.f;
-
+U32 gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0};
extern U32 gVisCompared;
extern U32 gVisTested;
@@ -749,7 +750,7 @@ void send_stats()
// send fps only for time app spends in foreground
agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32();
- agent["version"] = gCurrentVersion;
+ agent["version"] = LLVersionInfo::getChannelAndVersion();
std::string language = LLUI::getLanguage();
agent["language"] = language;
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index ca977d4599..3f9cfb9d9b 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -264,4 +264,6 @@ void send_stats();
extern std::map<S32,LLFrameTimer> gDebugTimers;
extern std::map<S32,std::string> gDebugTimerLabel;
extern U32 gTotalTextureBytes;
+extern U32 gTotalObjectBytes;
+extern U32 gTotalTextureBytesPerBoostLevel[] ;
#endif // LL_LLVIEWERSTATS_H
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5c262838ae..6160510c0e 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -72,6 +72,7 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ;
LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ;
+const std::string sTesterName("TextureTester");
S32 LLViewerTexture::sImageCount = 0;
S32 LLViewerTexture::sRawCount = 0;
@@ -341,9 +342,14 @@ void LLViewerTextureManager::init()
LLViewerTexture::initClass() ;
- if(LLFastTimer::sMetricLog)
+ if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
{
- LLViewerTextureManager::sTesterp = new LLTexturePipelineTester() ;
+ sTesterp = new LLTexturePipelineTester() ;
+ if (!sTesterp->isValid())
+ {
+ delete sTesterp;
+ sTesterp = NULL;
+ }
}
}
@@ -408,9 +414,10 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
{
sCurrentTime = gFrameTimeSeconds ;
- if(LLViewerTextureManager::sTesterp)
+ LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
{
- LLViewerTextureManager::sTesterp->update() ;
+ tester->update() ;
}
LLViewerMediaTexture::updateClass() ;
@@ -603,9 +610,10 @@ bool LLViewerTexture::bindDefaultImage(S32 stage)
//check if there is cached raw image and switch to it if possible
switchToCachedImage() ;
- if(LLViewerTextureManager::sTesterp)
+ LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
{
- LLViewerTextureManager::sTesterp->updateGrayTextureBinding() ;
+ tester->updateGrayTextureBinding() ;
}
return res;
}
@@ -1066,9 +1074,10 @@ BOOL LLViewerTexture::isLargeImage()
//virtual
void LLViewerTexture::updateBindStatsForTester()
{
- if(LLViewerTextureManager::sTesterp)
+ LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
{
- LLViewerTextureManager::sTesterp->updateTextureBindingStats(this) ;
+ tester->updateTextureBindingStats(this) ;
}
}
@@ -1130,7 +1139,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
// does not contain this image.
mIsMissingAsset = FALSE;
- mLoadedCallbackDesiredDiscardLevel = 0;
+ mLoadedCallbackDesiredDiscardLevel = S8_MAX;
mPauseLoadedCallBacks = TRUE ;
mNeedsCreateTexture = FALSE;
@@ -1155,9 +1164,11 @@ void LLViewerFetchedTexture::init(bool firstinit)
mSavedRawImage = NULL ;
mForceToSaveRawImage = FALSE ;
+ mSaveRawImage = FALSE ;
mSavedRawDiscardLevel = -1 ;
mDesiredSavedRawDiscardLevel = -1 ;
mLastReferencedSavedRawImageTime = 0.0f ;
+ mLastCallBackActiveTime = 0.f;
}
LLViewerFetchedTexture::~LLViewerFetchedTexture()
@@ -1483,56 +1494,57 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
//virtual
void LLViewerFetchedTexture::processTextureStats()
{
+ static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
+
if(mFullyLoaded)
- {
- if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more
+ {
+ if(needsToSaveRawImage())//needs to reload
{
- mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ;
mFullyLoaded = FALSE ;
}
- }
- else
- {
- updateVirtualSize() ;
-
- static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes");
-
- if (textures_fullres)
+ else
{
- mDesiredDiscardLevel = 0;
+ return ;
}
- else if(!mFullWidth || !mFullHeight)
+ }
+
+ //updateVirtualSize() ;
+
+ if (textures_fullres)
+ {
+ mDesiredDiscardLevel = 0;
+ }
+ else if(!mFullWidth || !mFullHeight)
+ {
+ mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel) ;
+ }
+ else
+ {
+ if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
{
- mDesiredDiscardLevel = getMaxDiscardLevel() ;
- }
- else
- {
- if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
+ if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
{
- if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
- {
- mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
- }
- else
- {
- mDesiredDiscardLevel = 0;
- }
- }
- else if(mKnownDrawSizeChanged)//known draw size is set
- {
- mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2,
- log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
- mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
- mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ;
+ mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
}
- mKnownDrawSizeChanged = FALSE ;
-
- if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
+ else
{
- mFullyLoaded = TRUE ;
+ mDesiredDiscardLevel = 0;
}
}
- }
+ else if(mKnownDrawSizeChanged)//known draw size is set
+ {
+ mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2,
+ log((F32)mFullHeight / mKnownDrawHeight) / log_2) ;
+ mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ;
+ mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ;
+ }
+ mKnownDrawSizeChanged = FALSE ;
+
+ if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel))
+ {
+ mFullyLoaded = TRUE ;
+ }
+ }
if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture.
{
@@ -1846,10 +1858,11 @@ bool LLViewerFetchedTexture::updateFetch()
// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
if (mRawImage.notNull())
{
- if(LLViewerTextureManager::sTesterp)
+ LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
{
mIsFetched = TRUE ;
- LLViewerTextureManager::sTesterp->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
+ tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
}
mRawDiscardLevel = fetch_discard;
if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
@@ -2074,13 +2087,14 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
mNeedsAux |= needs_aux;
if(keep_imageraw)
{
- forceToSaveRawImage(discard_level, true) ;
+ mSaveRawImage = TRUE ;
}
if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
{
// We need aux data, but we've already loaded the image, and it didn't have any
llwarns << "No aux data available for callback for image:" << getID() << llendl;
}
+ mLastCallBackActiveTime = sCurrentTime ;
}
void LLViewerFetchedTexture::clearCallbackEntryList()
@@ -2103,9 +2117,8 @@ void LLViewerFetchedTexture::clearCallbackEntryList()
}
gTextureList.mCallbackList.erase(this);
- mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
mLoadedCallbackDesiredDiscardLevel = S8_MAX ;
- if(mForceToSaveRawImage)
+ if(needsToSaveRawImage())
{
destroySavedRawImage() ;
}
@@ -2151,14 +2164,13 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so
{
// If we have no callbacks, take us off of the image callback list.
gTextureList.mCallbackList.erase(this);
- mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
-
- if(mForceToSaveRawImage)
+
+ if(needsToSaveRawImage())
{
destroySavedRawImage() ;
}
}
- else if(mForceToSaveRawImage && mBoostLevel != LLViewerTexture::BOOST_PREVIEW)
+ else if(needsToSaveRawImage() && mBoostLevel != LLViewerTexture::BOOST_PREVIEW)
{
if(desired_raw_discard != INVALID_DISCARD_LEVEL)
{
@@ -2196,7 +2208,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
mPauseLoadedCallBacks = FALSE ;
if(need_raw)
{
- mForceToSaveRawImage = TRUE ;
+ mSaveRawImage = TRUE ;
}
}
@@ -2227,16 +2239,23 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s
{
mPauseLoadedCallBacks = TRUE ;//when set, loaded callback is paused.
resetTextureStats();
- mForceToSaveRawImage = FALSE ;
+ mSaveRawImage = FALSE ;
}
}
bool LLViewerFetchedTexture::doLoadedCallbacks()
{
+ static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds
+
if (mNeedsCreateTexture)
{
return false;
}
+ if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME)
+ {
+ clearCallbackEntryList() ; //remove all callbacks.
+ return false ;
+ }
bool res = false;
@@ -2302,13 +2321,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
bool run_raw_callbacks = false;
bool need_readback = false;
- mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
for(callback_list_t::iterator iter = mLoadedCallbackList.begin();
iter != mLoadedCallbackList.end(); )
{
LLLoadedCallbackEntry *entryp = *iter++;
- mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)entryp->mDesiredDiscard) ;
-
+
if (entryp->mNeedsImageRaw)
{
if (mNeedsAux)
@@ -2382,7 +2399,8 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
// to satisfy the interested party, then this is the last time that
// we're going to call them.
- llassert_always(mRawImage.notNull());
+ mLastCallBackActiveTime = sCurrentTime ;
+ //llassert_always(mRawImage.notNull());
if(mNeedsAux && mAuxRawImage.isNull())
{
llwarns << "Raw Image with no Aux Data for callback" << llendl;
@@ -2417,6 +2435,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
LLLoadedCallbackEntry *entryp = *curiter;
if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard))
{
+ mLastCallBackActiveTime = sCurrentTime ;
BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE;
entryp->mLastUsedDiscard = gl_discard;
entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData);
@@ -2436,7 +2455,6 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
if (mLoadedCallbackList.empty())
{
gTextureList.mCallbackList.erase(this);
- mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
}
// Done with any raw image data at this point (will be re-created if we still have callbacks)
@@ -2516,6 +2534,11 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
return mRawImage;
}
+bool LLViewerFetchedTexture::needsToSaveRawImage()
+{
+ return mForceToSaveRawImage || mSaveRawImage ;
+}
+
void LLViewerFetchedTexture::destroyRawImage()
{
if (mAuxRawImage.notNull()) sAuxCount--;
@@ -2526,7 +2549,7 @@ void LLViewerFetchedTexture::destroyRawImage()
if(mIsRawImageValid)
{
- if(mForceToSaveRawImage)
+ if(needsToSaveRawImage())
{
saveRawImage() ;
}
@@ -2658,7 +2681,7 @@ void LLViewerFetchedTexture::saveRawImage()
mSavedRawDiscardLevel = mRawDiscardLevel ;
mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ;
- if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
+ if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel)
{
mForceToSaveRawImage = FALSE ;
}
@@ -2691,13 +2714,10 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, bool from_
void LLViewerFetchedTexture::destroySavedRawImage()
{
clearCallbackEntryList() ;
- //if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0 && mDesiredSavedRawDiscardLevel < getDiscardLevel())
- //{
- // return ; //can not destroy the saved raw image before it is fully fetched, otherwise causing callbacks hanging there.
- //}
-
+
mSavedRawImage = NULL ;
mForceToSaveRawImage = FALSE ;
+ mSaveRawImage = FALSE ;
mSavedRawDiscardLevel = -1 ;
mDesiredSavedRawDiscardLevel = -1 ;
mLastReferencedSavedRawImageTime = 0.0f ;
@@ -3066,9 +3086,10 @@ void LLViewerLODTexture::scaleDown()
{
switchToCachedImage() ;
- if(LLViewerTextureManager::sTesterp)
+ LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
{
- LLViewerTextureManager::sTesterp->setStablizingTime() ;
+ tester->setStablizingTime() ;
}
}
}
@@ -3578,23 +3599,22 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()
//----------------------------------------------------------------------------------------------
//start of LLTexturePipelineTester
//----------------------------------------------------------------------------------------------
-LLTexturePipelineTester::LLTexturePipelineTester() :
- LLMetricPerformanceTester("TextureTester", FALSE)
-{
- addMetricString("TotalBytesLoaded") ;
- addMetricString("TotalBytesLoadedFromCache") ;
- addMetricString("TotalBytesLoadedForLargeImage") ;
- addMetricString("TotalBytesLoadedForSculpties") ;
- addMetricString("StartFetchingTime") ;
- addMetricString("TotalGrayTime") ;
- addMetricString("TotalStablizingTime") ;
- addMetricString("StartTimeLoadingSculpties") ;
- addMetricString("EndTimeLoadingSculpties") ;
-
- addMetricString("Time") ;
- addMetricString("TotalBytesBound") ;
- addMetricString("TotalBytesBoundForLargeImage") ;
- addMetricString("PercentageBytesBound") ;
+LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWithSession(sTesterName)
+{
+ addMetric("TotalBytesLoaded") ;
+ addMetric("TotalBytesLoadedFromCache") ;
+ addMetric("TotalBytesLoadedForLargeImage") ;
+ addMetric("TotalBytesLoadedForSculpties") ;
+ addMetric("StartFetchingTime") ;
+ addMetric("TotalGrayTime") ;
+ addMetric("TotalStablizingTime") ;
+ addMetric("StartTimeLoadingSculpties") ;
+ addMetric("EndTimeLoadingSculpties") ;
+
+ addMetric("Time") ;
+ addMetric("TotalBytesBound") ;
+ addMetric("TotalBytesBoundForLargeImage") ;
+ addMetric("PercentageBytesBound") ;
mTotalBytesLoaded = 0 ;
mTotalBytesLoadedFromCache = 0 ;
@@ -3606,7 +3626,7 @@ LLTexturePipelineTester::LLTexturePipelineTester() :
LLTexturePipelineTester::~LLTexturePipelineTester()
{
- LLViewerTextureManager::sTesterp = NULL ;
+ LLViewerTextureManager::sTesterp = NULL;
}
void LLTexturePipelineTester::update()
@@ -3672,22 +3692,23 @@ void LLTexturePipelineTester::reset()
//virtual
void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
{
- (*sd)[mCurLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
- (*sd)[mCurLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
- (*sd)[mCurLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
- (*sd)[mCurLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
+ std::string currentLabel = getCurrentLabelName();
+ (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
+ (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
+ (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
+ (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
- (*sd)[mCurLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ;
- (*sd)[mCurLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ;
- (*sd)[mCurLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ;
+ (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ;
+ (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ;
+ (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ;
- (*sd)[mCurLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ;
- (*sd)[mCurLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ;
+ (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ;
+ (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ;
- (*sd)[mCurLabel]["Time"] = LLImageGL::sLastFrameTime ;
- (*sd)[mCurLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
- (*sd)[mCurLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
- (*sd)[mCurLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
+ (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime ;
+ (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
+ (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
+ (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
}
void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep)
@@ -3776,7 +3797,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
}
//compare and output the comparison
- *os << llformat("%s\n", mName.c_str()) ;
+ *os << llformat("%s\n", getTesterName().c_str()) ;
*os << llformat("AggregateResults\n") ;
compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ;
@@ -3831,7 +3852,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
}
//virtual
-LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
+LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
{
LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ;
if(!sessionp)
@@ -3858,12 +3879,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
//load a session
- BOOL in_log = (*log).has(mCurLabel) ;
- while(in_log)
+ std::string currentLabel = getCurrentLabelName();
+ BOOL in_log = (*log).has(currentLabel) ;
+ while (in_log)
{
- LLSD::String label = mCurLabel ;
- incLabel() ;
- in_log = (*log).has(mCurLabel) ;
+ LLSD::String label = currentLabel ;
if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size())
{
@@ -3929,7 +3949,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
- }
+ }
+ // Next label
+ incrementCurrentCount() ;
+ currentLabel = getCurrentLabelName();
+ in_log = (*log).has(currentLabel) ;
}
sessionp->mTotalFetchingTime += total_fetching_time ;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 7cb8bea4c8..b5636bbdc7 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -441,6 +441,7 @@ public:
LLImageRaw* reloadRawImage(S8 discard_level) ;
void destroyRawImage();
+ bool needsToSaveRawImage();
const std::string& getUrl() const {return mUrl;}
//---------------
@@ -532,6 +533,7 @@ protected:
S8 mLoadedCallbackDesiredDiscardLevel;
BOOL mPauseLoadedCallBacks;
callback_list_t mLoadedCallbackList;
+ F32 mLastCallBackActiveTime;
LLPointer<LLImageRaw> mRawImage;
S32 mRawDiscardLevel;
@@ -543,6 +545,7 @@ protected:
//keep a copy of mRawImage for some special purposes
//when mForceToSaveRawImage is set.
BOOL mForceToSaveRawImage ;
+ BOOL mSaveRawImage;
LLPointer<LLImageRaw> mSavedRawImage;
S32 mSavedRawDiscardLevel;
S32 mDesiredSavedRawDiscardLevel;
@@ -732,7 +735,7 @@ public:
//it tracks the activities of the texture pipeline
//records them, and outputs them to log files
//
-class LLTexturePipelineTester : public LLMetricPerformanceTester
+class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession
{
enum
{
@@ -748,8 +751,6 @@ public:
void updateGrayTextureBinding() ;
void setStablizingTime() ;
- /*virtual*/ void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
-
private:
void reset() ;
void updateStablizingTime() ;
@@ -820,7 +821,7 @@ private:
S32 mInstantPerformanceListCounter ;
};
- /*virtual*/ LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) ;
+ /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ;
/*virtual*/ void compareTestSessions(std::ofstream* os) ;
};
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index bbf7c8e60e..275dfaa996 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1161,6 +1161,8 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
// static
void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data)
{
+ static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
+
LLFastTimer t(FTM_PROCESS_IMAGES);
// Receive image header, copy into image object and decompresses
@@ -1171,14 +1173,16 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
char ip_string[256];
u32_to_ip_string(msg->getSenderIP(),ip_string);
+ U32 received_size ;
if (msg->getReceiveCompressedSize())
{
- gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8;
+ received_size = msg->getReceiveCompressedSize() ;
}
else
{
- gTextureList.sTextureBits += msg->getReceiveSize() * 8;
+ received_size = msg->getReceiveSize() ;
}
+ gTextureList.sTextureBits += received_size * 8;
gTextureList.sTexturePackets++;
U8 codec;
@@ -1213,6 +1217,11 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
delete [] data;
return;
}
+ if(log_texture_traffic)
+ {
+ gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ;
+ }
+
//image->getLastPacketTimer()->reset();
bool res = LLAppViewer::getTextureFetch()->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data);
if (!res)
@@ -1224,6 +1233,8 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
// static
void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data)
{
+ static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
+
LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE);
LLFastTimer t(FTM_PROCESS_IMAGES);
@@ -1236,14 +1247,16 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d
char ip_string[256];
u32_to_ip_string(msg->getSenderIP(),ip_string);
+ U32 received_size ;
if (msg->getReceiveCompressedSize())
{
- gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8;
+ received_size = msg->getReceiveCompressedSize() ;
}
else
{
- gTextureList.sTextureBits += msg->getReceiveSize() * 8;
+ received_size = msg->getReceiveSize() ;
}
+ gTextureList.sTextureBits += received_size * 8;
gTextureList.sTexturePackets++;
//llprintline("Start decode, image header...");
@@ -1277,6 +1290,11 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d
delete [] data;
return;
}
+ if(log_texture_traffic)
+ {
+ gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ;
+ }
+
//image->getLastPacketTimer()->reset();
bool res = LLAppViewer::getTextureFetch()->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data);
if (!res)
diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp
index b614ccdbc2..5147272122 100644
--- a/indra/newview/llviewerthrottle.cpp
+++ b/indra/newview/llviewerthrottle.cpp
@@ -46,7 +46,7 @@ const F32 MAX_FRACTIONAL = 1.5f;
const F32 MIN_FRACTIONAL = 0.2f;
const F32 MIN_BANDWIDTH = 50.f;
-const F32 MAX_BANDWIDTH = 1500.f;
+const F32 MAX_BANDWIDTH = 3000.f;
const F32 STEP_FRACTIONAL = 0.1f;
const F32 TIGHTEN_THROTTLE_THRESHOLD = 3.0f; // packet loss % per s
const F32 EASE_THROTTLE_THRESHOLD = 0.5f; // packet loss % per s
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ebcb6e3738..a7790243ed 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -306,6 +306,8 @@ public:
void update()
{
+ static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
+
std::string wind_vel_text;
std::string wind_vector_text;
std::string rwind_vel_text;
@@ -582,6 +584,23 @@ public:
ypos += y_inc;
}
}
+ if(log_texture_traffic)
+ {
+ U32 old_y = ypos ;
+ for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++)
+ {
+ if(gTotalTextureBytesPerBoostLevel[i] > 0)
+ {
+ addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, (F32)gTotalTextureBytesPerBoostLevel[i] / (1024 * 1024)));
+ ypos += y_inc;
+ }
+ }
+ if(ypos != old_y)
+ {
+ addText(xpos, ypos, "Network traffic for textures:");
+ ypos += y_inc;
+ }
+ }
}
void draw()
@@ -1404,6 +1423,11 @@ LLViewerWindow::LLViewerWindow(
gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
}
+ if (!gGLManager.mHasDepthClamp)
+ {
+ LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
+ }
+
// If we crashed while initializng GL stuff last time, disable certain features
if (gSavedSettings.getBOOL("RenderInitError"))
{
@@ -1839,6 +1863,8 @@ void LLViewerWindow::reshape(S32 width, S32 height)
return;
}
+ gWindowResized = TRUE;
+
// update our window rectangle
mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
@@ -2240,6 +2266,20 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
return TRUE;
}
+ // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook,
+ // no view has keyboard focus, this is a printable character key (and no modifier key is
+ // pressed except shift), then give focus to nearby chat (STORM-560)
+ if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&
+ !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
+ {
+ LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
+ if (chat_editor)
+ {
+ // passing NULL here, character will be added later when it is handled by character handler.
+ LLBottomTray::getInstance()->getNearbyChatBar()->startChat(NULL);
+ return TRUE;
+ }
+ }
// give menus a chance to handle unmodified accelerator keys
if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
@@ -3985,30 +4025,19 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
gDisplaySwapBuffers = FALSE;
gDepthDirty = TRUE;
- if (type == SNAPSHOT_TYPE_OBJECT_ID)
- {
- glClearColor(0.f, 0.f, 0.f, 0.f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
- setup3DRender();
- gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
+ const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ display(do_rebuild, scale_factor, subfield, TRUE);
}
else
{
- const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
-
- if (LLPipeline::sRenderDeferred)
- {
- display(do_rebuild, scale_factor, subfield, TRUE);
- }
- else
- {
- display(do_rebuild, scale_factor, subfield, TRUE);
+ display(do_rebuild, scale_factor, subfield, TRUE);
// Required for showing the GUI in snapshots and performing bloom composite overlay
// Call even if show_ui is FALSE
- render_ui(scale_factor, subfield);
- }
+ render_ui(scale_factor, subfield);
}
S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
@@ -4031,7 +4060,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
}
- if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR)
+ if (type == SNAPSHOT_TYPE_COLOR)
{
glReadPixels(
subimage_x_offset, out_y + subimage_y_offset,
@@ -4415,6 +4444,7 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
LLVOAvatar::restoreGL();
gResizeScreenTexture = TRUE;
+ gWindowResized = TRUE;
if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
{
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 633c3a41d2..47fb7c4883 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -316,8 +316,7 @@ public:
typedef enum
{
SNAPSHOT_TYPE_COLOR,
- SNAPSHOT_TYPE_DEPTH,
- SNAPSHOT_TYPE_OBJECT_ID
+ SNAPSHOT_TYPE_DEPTH
} ESnapshotType;
BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR);
BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE,
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
index 4473b5820d..0b52948680 100644
--- a/indra/newview/llviewerwindowlistener.cpp
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -54,7 +54,7 @@ LLViewerWindowListener::LLViewerWindowListener(LLViewerWindow* llviewerwindow):
// saveSnapshotArgs["type"] = LLSD::String();
add("saveSnapshot",
"Save screenshot: [\"filename\"], [\"width\"], [\"height\"], [\"showui\"], [\"rebuild\"], [\"type\"]\n"
- "type: \"COLOR\", \"DEPTH\", \"OBJECT_ID\"\n"
+ "type: \"COLOR\", \"DEPTH\"\n"
"Post on [\"reply\"] an event containing [\"ok\"]",
&LLViewerWindowListener::saveSnapshot,
saveSnapshotArgs);
@@ -71,7 +71,6 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
#define tp(name) types[#name] = LLViewerWindow::SNAPSHOT_TYPE_##name
tp(COLOR);
tp(DEPTH);
- tp(OBJECT_ID);
#undef tp
// Our add() call should ensure that the incoming LLSD does in fact
// contain our required arguments. Deal with the optional ones.
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 8738ad7687..f4dec9294f 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -3024,7 +3024,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
std::deque<LLChat>::iterator chat_iter = mChats.begin();
mNameText->clearString();
- LLColor4 new_chat = LLUIColorTable::instance().getColor( "NameTagChat" );
+ LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" );
LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)
@@ -3992,7 +3992,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
// *NOTE: this is disabled (there is no UI for enabling sShowFootPlane) due
// to DEV-14477. the code is left here to aid in tracking down the cause
// of the crash in the future. -brad
- if (!gRenderForSelect && sShowFootPlane && mDrawable.notNull())
+ if (sShowFootPlane && mDrawable.notNull())
{
LLVector3 slaved_pos = mDrawable->getPositionAgent();
LLVector3 foot_plane_normal(mFootPlane.mV[VX], mFootPlane.mV[VY], mFootPlane.mV[VZ]);
@@ -7864,6 +7864,7 @@ BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root)
//virtual
void LLVOAvatar::updateRegion(LLViewerRegion *regionp)
{
+ LLViewerObject::updateRegion(regionp);
}
std::string LLVOAvatar::getFullname() const
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index e5cbf65682..0250627d1b 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -806,7 +806,24 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
//virtual
void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
{
+ // Save the global position
+ LLVector3d global_pos_from_old_region = getPositionGlobal();
+
+ // Change the region
setRegion(regionp);
+
+ if (regionp)
+ { // Set correct region-relative position from global coordinates
+ setPositionGlobal(global_pos_from_old_region);
+
+ // Diagnostic info
+ //LLVector3d pos_from_new_region = getPositionGlobal();
+ //llinfos << "pos_from_old_region is " << global_pos_from_old_region
+ // << " while pos_from_new_region is " << pos_from_new_region
+ // << llendl;
+ }
+
+
if (!regionp || (regionp->getHandle() != mLastRegionHandle))
{
if (mLastRegionHandle != 0)
@@ -820,6 +837,9 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
F64 max = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_MAX);
max = llmax(delta, max);
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_MAX, max);
+
+ // Diagnostics
+ llinfos << "Region crossing took " << (F32)(delta * 1000.0) << " ms " << llendl;
}
if (regionp)
{
@@ -827,6 +847,7 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp)
}
}
mRegionCrossingTimer.reset();
+ LLViewerObject::updateRegion(regionp);
}
//--------------------------------------------------------------------
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 23a799ea3a..d13cf5ba38 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -123,6 +123,8 @@ public:
//--------------------------------------------------------------------
// Region state
//--------------------------------------------------------------------
+ void resetRegionCrossingTimer() { mRegionCrossingTimer.reset(); }
+
private:
U64 mLastRegionHandle;
LLFrameTimer mRegionCrossingTimer;
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index b1c6ea26cc..145ee31260 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -28,6 +28,7 @@
#include "llvocache.h"
#include "llerror.h"
#include "llregionhandle.h"
+#include "llviewercontrol.h"
BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)
{
@@ -231,11 +232,11 @@ LLVOCache* LLVOCache::sInstance = NULL;
//static
LLVOCache* LLVOCache::getInstance()
-{
+{
if(!sInstance)
{
sInstance = new LLVOCache() ;
-}
+ }
return sInstance ;
}
@@ -261,13 +262,17 @@ LLVOCache::LLVOCache():
mNumEntries(0),
mCacheSize(1)
{
+ mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled");
mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
}
LLVOCache::~LLVOCache()
{
- writeCacheHeader();
- clearCacheInMemory();
+ if(mEnabled)
+ {
+ writeCacheHeader();
+ clearCacheInMemory();
+ }
delete mLocalAPRFilePoolp;
}
@@ -281,7 +286,7 @@ void LLVOCache::setDirNames(ELLPath location)
void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
{
- if(mInitialized)
+ if(mInitialized || !mEnabled)
{
return ;
}
@@ -408,6 +413,11 @@ BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes)
void LLVOCache::readCacheHeader()
{
+ if(!mEnabled)
+ {
+ return ;
+ }
+
//clear stale info.
clearCacheInMemory();
@@ -452,7 +462,7 @@ void LLVOCache::readCacheHeader()
void LLVOCache::writeCacheHeader()
{
- if(mReadOnly)
+ if(mReadOnly || !mEnabled)
{
return ;
}
@@ -503,6 +513,10 @@ BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry)
void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)
{
+ if(!mEnabled)
+ {
+ return ;
+ }
llassert_always(mInitialized);
handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
@@ -572,6 +586,10 @@ void LLVOCache::purgeEntries()
void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache)
{
+ if(!mEnabled)
+ {
+ return ;
+ }
llassert_always(mInitialized);
if(mReadOnly)
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index ccdff5e96c..ed2bc8bafe 100644
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -129,6 +129,7 @@ private:
BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) ;
private:
+ BOOL mEnabled;
BOOL mInitialized ;
BOOL mReadOnly ;
HeaderMetaInfo mMetaInfo;
@@ -143,7 +144,7 @@ private:
static LLVOCache* sInstance ;
public:
static LLVOCache* getInstance() ;
- static BOOL hasInstance() ;
+ static BOOL hasInstance() ;
static void destroyClass() ;
};
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index eba600b50a..2eb4398488 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -80,7 +80,7 @@ public:
//============================================================================
LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
- : LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp),
+ : LLStaticViewerObject(id, pcode, regionp),
mDirtiedPatch(FALSE),
mPool(NULL),
mBaseComp(0),
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 598938b710..71f08ec36d 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -60,8 +60,11 @@ const U32 WIDTH = (N_RES * WAVE_STEP); //128.f //64 // width of wave tile, in
const F32 WAVE_STEP_INV = (1. / WAVE_STEP);
-LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-: LLStaticViewerObject(id, LL_VO_WATER, regionp)
+LLVOWater::LLVOWater(const LLUUID &id,
+ const LLPCode pcode,
+ LLViewerRegion *regionp) :
+ LLStaticViewerObject(id, pcode, regionp),
+ mRenderType(LLPipeline::RENDER_TYPE_WATER)
{
// Terrain must draw during selection passes so it can block objects behind it.
mbCanSelect = FALSE;
@@ -114,7 +117,7 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
{
pipeline->allocDrawable(this);
mDrawable->setLit(FALSE);
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WATER);
+ mDrawable->setRenderType(mRenderType);
LLDrawPoolWater *pool = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
@@ -152,11 +155,17 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
LLStrider<U16> indicesp;
U16 index_offset;
- S32 size = 16;
- S32 num_quads = size*size;
- face->setSize(4*num_quads, 6*num_quads);
+ // A quad is 4 vertices and 6 indices (making 2 triangles)
+ static const unsigned int vertices_per_quad = 4;
+ static const unsigned int indices_per_quad = 6;
+ const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") ? 16 : 1;
+
+ const S32 num_quads = size * size;
+ face->setSize(vertices_per_quad * num_quads,
+ indices_per_quad * num_quads);
+
if (face->mVertexBuffer.isNull())
{
face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
@@ -268,6 +277,11 @@ U32 LLVOWater::getPartitionType() const
return LLViewerRegion::PARTITION_WATER;
}
+U32 LLVOVoidWater::getPartitionType() const
+{
+ return LLViewerRegion::PARTITION_VOIDWATER;
+}
+
LLWaterPartition::LLWaterPartition()
: LLSpatialPartition(0, FALSE, 0)
{
@@ -275,3 +289,9 @@ LLWaterPartition::LLWaterPartition()
mDrawableType = LLPipeline::RENDER_TYPE_WATER;
mPartitionType = LLViewerRegion::PARTITION_WATER;
}
+
+LLVoidWaterPartition::LLVoidWaterPartition()
+{
+ mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER;
+ mPartitionType = LLViewerRegion::PARTITION_VOIDWATER;
+}
diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h
index beefc3f17f..cb9584cabf 100644
--- a/indra/newview/llvowater.h
+++ b/indra/newview/llvowater.h
@@ -29,6 +29,7 @@
#include "llviewerobject.h"
#include "llviewertexture.h"
+#include "pipeline.h"
#include "v2math.h"
const U32 N_RES = 16; //32 // number of subdivisions of wave tile
@@ -77,6 +78,19 @@ public:
protected:
BOOL mUseTexture;
BOOL mIsEdgePatch;
+ S32 mRenderType;
};
+class LLVOVoidWater : public LLVOWater
+{
+public:
+ LLVOVoidWater(LLUUID const& id, LLPCode pcode, LLViewerRegion* regionp) : LLVOWater(id, pcode, regionp)
+ {
+ mRenderType = LLPipeline::RENDER_TYPE_VOIDWATER;
+ }
+
+ /*virtual*/ U32 getPartitionType() const;
+};
+
+
#endif // LL_VOSURFACEPATCH_H
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 7314894c2e..d239347810 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -89,7 +89,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
while(found)
{
std::string name;
- found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
+ found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name);
if(found)
{
@@ -115,7 +115,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
while(found)
{
std::string name;
- found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
+ found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name);
if(found)
{
name=name.erase(name.length()-4);
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index 9b6047395a..e5f52dfc97 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -104,7 +104,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
while(found)
{
std::string name;
- found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name, false);
+ found = gDirUtilp->getNextFileInDir(path_name, "*.xml", name);
if(found)
{
@@ -130,7 +130,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
while(found)
{
std::string name;
- found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name, false);
+ found = gDirUtilp->getNextFileInDir(path_name2, "*.xml", name);
if(found)
{
name=name.erase(name.length()-4);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 5760d04a08..399442e5c4 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -55,6 +55,11 @@
#include "pipeline.h"
#include "llappviewer.h" // for do_disconnect()
+#include <deque>
+#include <queue>
+#include <map>
+#include <cstring>
+
//
// Globals
//
@@ -121,7 +126,10 @@ void LLWorld::destroyClass()
LLViewerRegion* region_to_delete = *region_it++;
removeRegion(region_to_delete->getHost());
}
- LLVOCache::getInstance()->destroyClass() ;
+ if(LLVOCache::hasInstance())
+ {
+ LLVOCache::getInstance()->destroyClass() ;
+ }
LLViewerPartSim::getInstance()->destroyClass();
}
@@ -423,14 +431,15 @@ BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global)
// Allow objects to go up to their radius underground.
-F32 LLWorld::getMinAllowedZ(LLViewerObject* object)
+F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos)
{
- F32 land_height = resolveLandHeightGlobal(object->getPositionGlobal());
+ F32 land_height = resolveLandHeightGlobal(global_pos);
F32 radius = 0.5f * object->getScale().length();
return land_height - radius;
}
+
LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global)
{
LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
@@ -834,10 +843,69 @@ F32 LLWorld::getLandFarClip() const
void LLWorld::setLandFarClip(const F32 far_clip)
{
+ static S32 const rwidth = (S32)REGION_WIDTH_U32;
+ S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
+ S32 const n2 = (llceil(far_clip) - 1) / rwidth;
+ bool need_water_objects_update = n1 != n2;
+
mLandFarClip = far_clip;
+
+ if (need_water_objects_update)
+ {
+ updateWaterObjects();
+ }
}
+// Some region that we're connected to, but not the one we're in, gave us
+// a (possibly) new water height. Update it in our local copy.
+void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height)
+{
+ for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
+ {
+ if ((*iter)->getName() == sim_name)
+ {
+ (*iter)->setWaterHeight(water_height);
+ break;
+ }
+ }
+}
+// There are three types of water objects:
+// Region water objects: the water in a region.
+// Hole water objects: water in the void but within current draw distance.
+// Edge water objects: the water outside the draw distance, up till the horizon.
+//
+// For example:
+//
+// -----------------------horizon-------------------------
+// | | | |
+// | Edge Water | | |
+// | | | |
+// | | | |
+// | | | |
+// | | | |
+// | | rwidth | |
+// | | <-----> | |
+// -------------------------------------------------------
+// | |Hole |other| | |
+// | |Water|reg. | | |
+// | |-----------------| |
+// | |other|cur. |<--> | |
+// | |reg. | reg.| \__|_ draw distance |
+// | |-----------------| |
+// | | | |<--->| |
+// | | | | \__|_ range |
+// -------------------------------------------------------
+// | |<----width------>|<--horizon ext.->|
+// | | | |
+// | | | |
+// | | | |
+// | | | |
+// | | | |
+// | | | |
+// | | | |
+// -------------------------------------------------------
+//
void LLWorld::updateWaterObjects()
{
if (!gAgent.getRegion())
@@ -850,128 +918,265 @@ void LLWorld::updateWaterObjects()
return;
}
- // First, determine the min and max "box" of water objects
- S32 min_x = 0;
- S32 min_y = 0;
- S32 max_x = 0;
- S32 max_y = 0;
+ // Region width in meters.
+ S32 const rwidth = (S32)REGION_WIDTH_U32;
+
+ // The distance we might see into the void
+ // when standing on the edge of a region, in meters.
+ S32 const draw_distance = llceil(mLandFarClip);
+
+ // We can only have "holes" in the water (where there no region) if we
+ // can have existing regions around it. Taking into account that this
+ // code is only executed when we enter a region, and not when we walk
+ // around in it, we (only) need to take into account regions that fall
+ // within the draw_distance.
+ //
+ // Set 'range' to draw_distance, rounded up to the nearest multiple of rwidth.
+ S32 const nsims = (draw_distance + rwidth - 1) / rwidth;
+ S32 const range = nsims * rwidth;
+
+ // Get South-West corner of current region.
+ LLViewerRegion const* regionp = gAgent.getRegion();
U32 region_x, region_y;
-
- S32 rwidth = 256;
-
- // We only want to fill in water for stuff that's near us, say, within 256 or 512m
- S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
-
- LLViewerRegion* regionp = gAgent.getRegion();
from_region_handle(regionp->getHandle(), &region_x, &region_y);
- min_x = (S32)region_x - range;
- min_y = (S32)region_y - range;
- max_x = (S32)region_x + range;
- max_y = (S32)region_y + range;
+ // The min. and max. coordinates of the South-West corners of the Hole water objects.
+ S32 const min_x = (S32)region_x - range;
+ S32 const min_y = (S32)region_y - range;
+ S32 const max_x = (S32)region_x + range;
+ S32 const max_y = (S32)region_y + range;
+
+ // Attempt to determine a sensible water height for all the
+ // Hole Water objects.
+ //
+ // It make little sense to try to guess what the best water
+ // height should be when that isn't completely obvious: if it's
+ // impossible to satisfy every region's water height without
+ // getting a jump in the water height.
+ //
+ // In order to keep the reasoning simple, we assume something
+ // logical as a group of connected regions, where the coastline
+ // is at the outer edge. Anything more complex that would "break"
+ // under such an assumption would probably break anyway (would
+ // depend on terrain editing and existing mega prims, say, if
+ // anything would make sense at all).
+ //
+ // So, what we do is find all connected regions within the
+ // draw distance that border void, and then pick the lowest
+ // water height of those (coast) regions.
+ S32 const n = 2 * nsims + 1;
+ S32 const origin = nsims + nsims * n;
+ std::vector<F32> water_heights(n * n);
+ std::vector<U8> checked(n * n, 0); // index = nx + ny * n + origin;
+ U8 const region_bit = 1;
+ U8 const hole_bit = 2;
+ U8 const bordering_hole_bit = 4;
+ U8 const bordering_edge_bit = 8;
+ // Use the legacy waterheight for the Edge water in the case
+ // that we don't find any Hole water at all.
+ F32 water_height = DEFAULT_WATER_HEIGHT;
+ int max_count = 0;
+ LL_DEBUGS("WaterHeight") << "Current region: " << regionp->getName() << "; water height: " << regionp->getWaterHeight() << " m." << LL_ENDL;
+ std::map<S32, int> water_height_counts;
+ typedef std::queue<std::pair<S32, S32>, std::deque<std::pair<S32, S32> > > nxny_pairs_type;
+ nxny_pairs_type nxny_pairs;
+ nxny_pairs.push(nxny_pairs_type::value_type(0, 0));
+ water_heights[origin] = regionp->getWaterHeight();
+ checked[origin] = region_bit;
+ // For debugging purposes.
+ int number_of_connected_regions = 1;
+ int uninitialized_regions = 0;
+ int bordering_hole = 0;
+ int bordering_edge = 0;
+ while(!nxny_pairs.empty())
+ {
+ S32 const nx = nxny_pairs.front().first;
+ S32 const ny = nxny_pairs.front().second;
+ LL_DEBUGS("WaterHeight") << "nx,ny = " << nx << "," << ny << LL_ENDL;
+ S32 const index = nx + ny * n + origin;
+ nxny_pairs.pop();
+ for (S32 dir = 0; dir < 4; ++dir)
+ {
+ S32 const cnx = nx + gDirAxes[dir][0];
+ S32 const cny = ny + gDirAxes[dir][1];
+ LL_DEBUGS("WaterHeight") << "dir = " << dir << "; cnx,cny = " << cnx << "," << cny << LL_ENDL;
+ S32 const cindex = cnx + cny * n + origin;
+ bool is_hole = false;
+ bool is_edge = false;
+ LLViewerRegion* new_region_found = NULL;
+ if (cnx < -nsims || cnx > nsims ||
+ cny < -nsims || cny > nsims)
+ {
+ LL_DEBUGS("WaterHeight") << " Edge Water!" << LL_ENDL;
+ // Bumped into Edge water object.
+ is_edge = true;
+ }
+ else if (checked[cindex])
+ {
+ LL_DEBUGS("WaterHeight") << " Already checked before!" << LL_ENDL;
+ // Already checked.
+ is_hole = (checked[cindex] & hole_bit);
+ }
+ else
+ {
+ S32 x = (S32)region_x + cnx * rwidth;
+ S32 y = (S32)region_y + cny * rwidth;
+ U64 region_handle = to_region_handle(x, y);
+ new_region_found = getRegionFromHandle(region_handle);
+ is_hole = !new_region_found;
+ checked[cindex] = is_hole ? hole_bit : region_bit;
+ }
+ if (is_hole)
+ {
+ // This was a region that borders at least one 'hole'.
+ // Count the found coastline.
+ F32 new_water_height = water_heights[index];
+ LL_DEBUGS("WaterHeight") << " This is void; counting coastline with water height of " << new_water_height << LL_ENDL;
+ S32 new_water_height_cm = llround(new_water_height * 100);
+ int count = (water_height_counts[new_water_height_cm] += 1);
+ // Just use the lowest water height: this is mainly about the horizon water,
+ // and whatever we do, we don't want it to be possible to look under the water
+ // when looking in the distance: it is better to make a step downwards in water
+ // height when going away from the avie than a step upwards. However, since
+ // everyone is used to DEFAULT_WATER_HEIGHT, don't allow a single region
+ // to drag the water level below DEFAULT_WATER_HEIGHT on it's own.
+ if (bordering_hole == 0 || // First time we get here.
+ (new_water_height >= DEFAULT_WATER_HEIGHT &&
+ new_water_height < water_height) ||
+ (new_water_height < DEFAULT_WATER_HEIGHT &&
+ count > max_count)
+ )
+ {
+ water_height = new_water_height;
+ }
+ if (count > max_count)
+ {
+ max_count = count;
+ }
+ if (!(checked[index] & bordering_hole_bit))
+ {
+ checked[index] |= bordering_hole_bit;
+ ++bordering_hole;
+ }
+ }
+ else if (is_edge && !(checked[index] & bordering_edge_bit))
+ {
+ checked[index] |= bordering_edge_bit;
+ ++bordering_edge;
+ }
+ if (!new_region_found)
+ {
+ // Dead end, there is no region here.
+ continue;
+ }
+ // Found a new connected region.
+ ++number_of_connected_regions;
+ if (new_region_found->getName().empty())
+ {
+ // Uninitialized LLViewerRegion, don't use it's water height.
+ LL_DEBUGS("WaterHeight") << " Uninitialized region." << LL_ENDL;
+ ++uninitialized_regions;
+ continue;
+ }
+ nxny_pairs.push(nxny_pairs_type::value_type(cnx, cny));
+ water_heights[cindex] = new_region_found->getWaterHeight();
+ LL_DEBUGS("WaterHeight") << " Found a new region (name: " << new_region_found->getName() << "; water height: " << water_heights[cindex] << " m)!" << LL_ENDL;
+ }
+ }
+ llinfos << "Number of connected regions: " << number_of_connected_regions << " (" << uninitialized_regions <<
+ " uninitialized); number of regions bordering Hole water: " << bordering_hole <<
+ "; number of regions bordering Edge water: " << bordering_edge << llendl;
+ llinfos << "Coastline count (height, count): ";
+ bool first = true;
+ for (std::map<S32, int>::iterator iter = water_height_counts.begin(); iter != water_height_counts.end(); ++iter)
+ {
+ if (!first) llcont << ", ";
+ llcont << "(" << (iter->first / 100.f) << ", " << iter->second << ")";
+ first = false;
+ }
+ llcont << llendl;
+ llinfos << "Water height used for Hole and Edge water objects: " << water_height << llendl;
- F32 height = 0.f;
-
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
+ // Update all Region water objects.
+ for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
{
LLViewerRegion* regionp = *iter;
LLVOWater* waterp = regionp->getLand().getWaterObj();
- height += regionp->getWaterHeight();
if (waterp)
{
gObjectList.updateActive(waterp);
}
}
+ // Clean up all existing Hole water objects.
for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
- iter != mHoleWaterObjects.end(); ++ iter)
+ iter != mHoleWaterObjects.end(); ++iter)
{
LLVOWater* waterp = *iter;
gObjectList.killObject(waterp);
}
mHoleWaterObjects.clear();
- // Now, get a list of the holes
- S32 x, y;
- for (x = min_x; x <= max_x; x += rwidth)
+ // Let the Edge and Hole water boxes be 1024 meter high so that they
+ // are never too small to be drawn (A LL_VO_*_WATER box has water
+ // rendered on it's bottom surface only), and put their bottom at
+ // the current regions water height.
+ F32 const box_height = 1024;
+ F32 const water_center_z = water_height + box_height / 2;
+
+ // Create new Hole water objects within 'range' where there is no region.
+ for (S32 x = min_x; x <= max_x; x += rwidth)
{
- for (y = min_y; y <= max_y; y += rwidth)
+ for (S32 y = min_y; y <= max_y; y += rwidth)
{
U64 region_handle = to_region_handle(x, y);
if (!getRegionFromHandle(region_handle))
{
- LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
+ LLVOWater* waterp = (LLVOWater*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());
waterp->setUseTexture(FALSE);
- waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
- y + rwidth/2,
- 256.f+DEFAULT_WATER_HEIGHT));
- waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
+ waterp->setPositionGlobal(LLVector3d(x + rwidth / 2, y + rwidth / 2, water_center_z));
+ waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, box_height));
gPipeline.createObject(waterp);
mHoleWaterObjects.push_back(waterp);
}
}
}
- // Update edge water objects
- S32 wx, wy;
- S32 center_x, center_y;
- wx = (max_x - min_x) + rwidth;
- wy = (max_y - min_y) + rwidth;
- center_x = min_x + (wx >> 1);
- center_y = min_y + (wy >> 1);
-
- S32 add_boundary[4] = {
- 512 - (max_x - region_x),
- 512 - (max_y - region_y),
- 512 - (region_x - min_x),
- 512 - (region_y - min_y) };
+ // Center of the region.
+ S32 const center_x = region_x + rwidth / 2;
+ S32 const center_y = region_y + rwidth / 2;
+ // Width of the area with Hole water objects.
+ S32 const width = rwidth + 2 * range;
+ S32 const horizon_extend = 2048 + 512 - range; // Legacy value.
+ // The overlap is needed to get rid of sky pixels being visible between the
+ // Edge and Hole water object at greater distances (due to floating point
+ // round off errors).
+ S32 const edge_hole_overlap = 1; // Twice the actual overlap.
- S32 dir;
- for (dir = 0; dir < 8; dir++)
+ for (S32 dir = 0; dir < 8; ++dir)
{
- S32 dim[2] = { 0 };
- switch (gDirAxes[dir][0])
- {
- case -1: dim[0] = add_boundary[2]; break;
- case 0: dim[0] = wx; break;
- default: dim[0] = add_boundary[0]; break;
- }
- switch (gDirAxes[dir][1])
- {
- case -1: dim[1] = add_boundary[3]; break;
- case 0: dim[1] = wy; break;
- default: dim[1] = add_boundary[1]; break;
- }
+ // Size of the Edge water objects.
+ S32 const dim_x = (gDirAxes[dir][0] == 0) ? width : (horizon_extend + edge_hole_overlap);
+ S32 const dim_y = (gDirAxes[dir][1] == 0) ? width : (horizon_extend + edge_hole_overlap);
+ // And their position.
+ S32 const water_center_x = center_x + (width + horizon_extend) / 2 * gDirAxes[dir][0];
+ S32 const water_center_y = center_y + (width + horizon_extend) / 2 * gDirAxes[dir][1];
- // Resize and reshape the water objects
- const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
- const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
-
LLVOWater* waterp = mEdgeWaterObjects[dir];
if (!waterp || waterp->isDead())
{
// The edge water objects can be dead because they're attached to the region that the
// agent was in when they were originally created.
- mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER,
- gAgent.getRegion());
+ mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());
waterp = mEdgeWaterObjects[dir];
waterp->setUseTexture(FALSE);
- waterp->setIsEdgePatch(TRUE);
+ waterp->setIsEdgePatch(TRUE); // Mark that this is edge water and not hole water.
gPipeline.createObject(waterp);
}
waterp->setRegion(gAgent.getRegion());
- LLVector3d water_pos(water_center_x, water_center_y,
- DEFAULT_WATER_HEIGHT+256.f);
- LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
-
- //stretch out to horizon
- water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
- water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
-
- water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
- water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
+ LLVector3d water_pos(water_center_x, water_center_y, water_center_z);
+ LLVector3 water_scale((F32) dim_x, (F32) dim_y, box_height);
waterp->setPositionGlobal(water_pos);
waterp->setScale(water_scale);
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 4465fde210..d8ab4bc508 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -89,7 +89,7 @@ public:
// Return the lowest allowed Z point to prevent objects from being moved
// underground.
- F32 getMinAllowedZ(LLViewerObject* object);
+ F32 getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos);
// takes a line segment defined by point_a and point_b, then
// determines the closest (to point_a) point of intersection that is
@@ -137,6 +137,7 @@ public:
LLViewerTexture *getDefaultWaterTexture();
void updateWaterObjects();
+ void waterHeightRegionInfo(std::string const& sim_name, F32 water_height);
void shiftRegions(const LLVector3& offset);
void setSpaceTimeUSec(const U64 space_time_usec);
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 0c17b5e297..8ef3a3b839 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -880,8 +880,10 @@ void LLWorldMapView::drawFrustum()
F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 );
F32 half_width_pixels = half_width_meters * meters_to_pixels;
- F32 ctr_x = getLocalRect().getWidth() * 0.5f + sPanX;
- F32 ctr_y = getLocalRect().getHeight() * 0.5f + sPanY;
+ // Compute the frustum coordinates. Take the UI scale into account.
+ F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+ F32 ctr_x = (getLocalRect().getWidth() * 0.5f + sPanX) * ui_scale_factor;
+ F32 ctr_y = (getLocalRect().getHeight() * 0.5f + sPanY) * ui_scale_factor;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 03e6e65788..15477e0a80 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -130,8 +130,6 @@ static S32 sDelayedVBOEnable = 0;
BOOL gAvatarBacklight = FALSE;
-BOOL gRenderForSelect = FALSE;
-
BOOL gDebugPipeline = FALSE;
LLPipeline gPipeline;
const LLMatrix4* gGLLastMatrix = NULL;
@@ -629,14 +627,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
//static
void LLPipeline::updateRenderDeferred()
{
- BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") &&
- LLRenderTarget::sUseFBO &&
- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
- gSavedSettings.getBOOL("VertexShaderEnable") &&
- gSavedSettings.getBOOL("RenderAvatarVP") &&
- (gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) &&
- !gUseWireframe;
-
+ BOOL deferred = ((gSavedSettings.getBOOL("RenderDeferred") &&
+ LLRenderTarget::sUseFBO &&
+ LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
+ gSavedSettings.getBOOL("VertexShaderEnable") &&
+ gSavedSettings.getBOOL("RenderAvatarVP") &&
+ gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) &&
+ !gUseWireframe;
+
sRenderDeferred = deferred;
}
@@ -1638,20 +1636,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
camera.disableUserClipPlane();
- if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull())
+ if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) &&
+ gSky.mVOSkyp.notNull() &&
+ gSky.mVOSkyp->mDrawable.notNull())
{
- // Hack for sky - always visible.
- if (hasRenderType(LLPipeline::RENDER_TYPE_SKY))
- {
- gSky.mVOSkyp->mDrawable->setVisible(camera);
- sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
- gSky.updateCull();
- stop_glerror();
- }
- }
- else
- {
- llinfos << "No sky drawable!" << llendl;
+ gSky.mVOSkyp->mDrawable->setVisible(camera);
+ sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
+ gSky.updateCull();
+ stop_glerror();
}
if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) &&
@@ -2221,6 +2213,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
LLPipeline::RENDER_TYPE_TERRAIN,
LLPipeline::RENDER_TYPE_TREE,
LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
LLPipeline::RENDER_TYPE_WATER,
LLPipeline::END_RENDER_TYPES))
{
@@ -3812,185 +3805,6 @@ void LLPipeline::renderDebug()
gGL.flush();
}
-void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect)
-{
- assertInitialized();
-
- gGL.setColorMask(true, false);
- gPipeline.resetDrawOrders();
-
- LLViewerCamera* camera = LLViewerCamera::getInstance();
- for (std::set<LLViewerObject*>::iterator iter = objects.begin(); iter != objects.end(); ++iter)
- {
- stateSort((*iter)->mDrawable, *camera);
- }
-
- LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_SELECT);
-
-
-
- glMatrixMode(GL_MODELVIEW);
-
- LLGLSDefault gls_default;
- LLGLSObjectSelect gls_object_select;
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE);
- disableLights();
-
- LLVertexBuffer::unbind();
-
- //for each drawpool
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
- U32 last_type = 0;
-
- // If we don't do this, we crash something on changing graphics settings
- // from Medium -> Low, because we unload all the shaders and the
- // draw pools aren't aware. I don't know if this has to be a separate
- // loop before actual rendering. JC
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (poolp->isFacePool() && hasRenderType(poolp->getType()))
- {
- poolp->prerender();
- }
- }
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (poolp->isFacePool() && hasRenderType(poolp->getType()))
- {
- LLFacePool* face_pool = (LLFacePool*) poolp;
- face_pool->renderForSelect();
- LLVertexBuffer::unbind();
- gGLLastMatrix = NULL;
- glLoadMatrixd(gGLModelView);
-
- if (poolp->getType() != last_type)
- {
- last_type = poolp->getType();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
- }
- }
- }
-
- LLGLEnable alpha_test(GL_ALPHA_TEST);
- if (render_transparent)
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f);
- }
- else
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.2f);
- }
-
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_COLOR);
- gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
-
- U32 prim_mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0;
-
- for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i)
- {
- LLViewerObject* vobj = *i;
- LLDrawable* drawable = vobj->mDrawable;
- if (vobj->isDead() ||
- vobj->isHUDAttachment() ||
- (LLSelectMgr::getInstance()->mHideSelectedObjects && vobj->isSelected()) ||
- drawable->isDead() ||
- !hasRenderType(drawable->getRenderType()))
- {
- continue;
- }
-
- for (S32 j = 0; j < drawable->getNumFaces(); ++j)
- {
- LLFace* facep = drawable->getFace(j);
- if (!facep->getPool())
- {
- facep->renderForSelect(prim_mask);
- }
- }
- }
-
- // pick HUD objects
- if (isAgentAvatarValid() && sShowHUDAttachments)
- {
- glh::matrix4f save_proj(glh_get_current_projection());
- glh::matrix4f save_model(glh_get_current_modelview());
-
- setup_hud_matrices(screen_rect);
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment())
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- if (LLViewerObject* attached_object = (*attachment_iter))
- {
- LLDrawable* drawable = attached_object->mDrawable;
- if (drawable->isDead())
- {
- continue;
- }
-
- for (S32 j = 0; j < drawable->getNumFaces(); ++j)
- {
- LLFace* facep = drawable->getFace(j);
- if (!facep->getPool())
- {
- facep->renderForSelect(prim_mask);
- }
- }
-
- //render child faces
- LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child = *iter;
- LLDrawable* child_drawable = child->mDrawable;
- for (S32 l = 0; l < child_drawable->getNumFaces(); ++l)
- {
- LLFace* facep = child_drawable->getFace(l);
- if (!facep->getPool())
- {
- facep->renderForSelect(prim_mask);
- }
- }
- }
- }
- }
- }
- }
-
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(save_proj.m);
- glh_set_current_projection(save_proj);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(save_model.m);
- glh_set_current_modelview(save_model);
-
-
- }
-
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
- LLVertexBuffer::unbind();
-
- gGL.setColorMask(true, true);
-}
-
void LLPipeline::rebuildPools()
{
LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
@@ -5012,6 +4826,10 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
void LLPipeline::toggleRenderType(U32 type)
{
gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
+ if (type == LLPipeline::RENDER_TYPE_WATER)
+ {
+ gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
+ }
}
//static
@@ -7339,6 +7157,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
gPipeline.pushRenderTypeMask();
clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
LLPipeline::RENDER_TYPE_GROUND,
LLPipeline::RENDER_TYPE_SKY,
LLPipeline::RENDER_TYPE_CLOUDS,
@@ -7391,6 +7210,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
{
camera.setFar(camera_in.getFar());
clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
LLPipeline::RENDER_TYPE_GROUND,
END_RENDER_TYPES);
stop_glerror();
@@ -7907,6 +7727,7 @@ void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<L
LLPipeline::RENDER_TYPE_TREE,
LLPipeline::RENDER_TYPE_TERRAIN,
LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
LLPipeline::RENDER_TYPE_AVATAR,
LLPipeline::RENDER_TYPE_PASS_SIMPLE,
@@ -8090,6 +7911,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLPipeline::RENDER_TYPE_TREE,
LLPipeline::RENDER_TYPE_TERRAIN,
LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
LLPipeline::RENDER_TYPE_PASS_SIMPLE,
LLPipeline::RENDER_TYPE_PASS_BUMP,
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index b80765dac6..3f785a99fe 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -245,7 +245,6 @@ public:
void renderHighlights();
void renderDebug();
- void renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect);
void rebuildPools(); // Rebuild pools
void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object
@@ -359,6 +358,7 @@ public:
RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
+ RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER,
RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
@@ -712,7 +712,6 @@ void render_bbox(const LLVector3 &min, const LLVector3 &max);
void render_hud_elements();
extern LLPipeline gPipeline;
-extern BOOL gRenderForSelect;
extern BOOL gDebugPipeline;
extern const LLMatrix4* gGLLastMatrix;
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index ddd2ff196b..62441fd984 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -139,9 +139,6 @@
name="AvatarListItemIconVoiceLeftColor"
reference="AvatarListItemIconOfflineColor" />
<color
- name="BackgroundChatColor"
- reference="DkGray_66" />
- <color
name="ButtonBorderColor"
reference="Unused?" />
<color
@@ -400,9 +397,6 @@
name="HighlightParentColor"
value="0.67 0.83 0.96 1" />
<color
- name="IMChatColor"
- reference="LtGray" />
- <color
name="IMHistoryBgColor"
reference="Unused?" />
<color
@@ -767,9 +761,6 @@
name="SysWellItemSelected"
value="0.3 0.3 0.3 1.0" />
<color
- name="ChatToastAgentNameColor"
- reference="EmphasisColor" />
- <color
name="ColorSwatchBorderColor"
value="0.45098 0.517647 0.607843 1"/>
<color
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index cd5922a9a2..49deb9b025 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -20,6 +20,7 @@
left="0"
name="normal_background"
top="17"
+ use_draw_context_alpha="false"
width="350" />
<text
type="string"
@@ -292,6 +293,7 @@ Re-enter amount to see the latest exchange rate.
left="0"
name="error_background"
top="15"
+ use_draw_context_alpha="false"
width="350"/>
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 4c5113aa55..ab966dbb0e 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -2,9 +2,6 @@
<floater
border_visible="false"
border="false"
- bg_opaque_image="Window_Foreground"
- bg_alpha_image="Window_Background"
- bg_alpha_image_overlay="DkGray_66"
legacy_header_height="18"
can_minimize="true"
can_tear_off="false"
diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml
index 0fb7691ee7..6c8d994bc6 100644
--- a/indra/newview/skins/default/xui/en/panel_classified_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml
@@ -49,7 +49,8 @@
left="10"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
index f60c1e62ac..e512d63f9e 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml
@@ -33,7 +33,8 @@
left="10"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
index a284d3ccc0..a028e3ab9f 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -27,7 +27,8 @@
left="10"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index b3e9586ee9..ac8917d272 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -147,7 +147,8 @@
pad_left="24"
tool_tip="Return to Edit Outfit"
top="3"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
index 0347d2feec..ec3f3b48bc 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -45,7 +45,8 @@ background_visible="true"
left="7"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text_editor
allow_scroll="false"
bg_visible="false"
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index 6ee2abc70f..d2088594dd 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -68,7 +68,8 @@
tool_tip="Back"
tab_stop="false"
top="4"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml
index b181ca3bba..89feba7c3c 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -127,7 +127,7 @@ top="20"
</text>
<combo_box
allow_text_entry="true"
-control_name="LoginLocation"
+control_name="NextLoginLocation"
follows="left|bottom"
height="23"
max_chars="128"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index f4dee9cd55..e1cd78bad8 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -70,7 +70,8 @@
left="5"
tab_stop="false"
top="1"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml
index 0496c86215..7daa52b2d9 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -21,7 +21,8 @@
left="10"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index 8036411d2b..7e89860c60 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -165,7 +165,8 @@
tool_tip="Back"
tab_stop="false"
top="4"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
index 0c75399764..5797a63f4e 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
@@ -275,14 +275,14 @@
height="12"
name="bubble_chat"
top_pad="20"
- width="120"
+ width="140"
>
- Bubble chat:
+ Bubble chat background:
</text>
<color_swatch
can_apply_immediately="true"
color="0 0 0 1"
- control_name="BackgroundChatColor"
+ control_name="NameTagBackground"
follows="left|top"
height="24"
label_height="0"
@@ -294,10 +294,10 @@
width="44">
<color_swatch.init_callback
function="Pref.getUIColor"
- parameter="BackgroundChatColor" />
+ parameter="NameTagBackground" />
<color_swatch.commit_callback
function="Pref.applyUIColor"
- parameter="BackgroundChatColor" />
+ parameter="NameTagBackground" />
</color_swatch>
<slider
control_name="ChatBubbleOpacity"
@@ -333,7 +333,7 @@
initial_value="0.8"
layout="topleft"
label_width="115"
- label="Active :"
+ label="Active:"
left="50"
max_val="1.00"
min_val="0.00"
@@ -351,7 +351,7 @@
initial_value="0.5"
layout="topleft"
label_width="115"
- label="Inctive :"
+ label="Inactive:"
left="50"
max_val="1.00"
min_val="0.00"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 3ceee60927..6573822d1a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -181,7 +181,7 @@
label="Transparent Water"
layout="topleft"
left_delta="0"
- name="BumpShiny"
+ name="TransparentWater"
top_pad="7"
width="256" />
<check_box
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
index 2ddb81559f..626122c0b0 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -185,7 +185,7 @@
layout="topleft"
left_pad="10"
mouse_opaque="false"
- name="cache_size_label_l"
+ name="block_list_label"
top_delta="3"
text_color="LtGray_50"
width="300">
diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml
index 97229c413c..c553a3aba0 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -27,7 +27,8 @@
left="10"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
top="10"
follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
index 6940d1549b..54a312bd59 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -56,7 +56,8 @@
name="back_btn"
tab_stop="false"
top="2"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHugeBold"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
index ca63d2df39..afaf41d073 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
@@ -65,7 +65,8 @@
name="back_btn"
tab_stop="false"
top="0"
- width="30" />
+ width="30"
+ use_draw_context_alpha="false" />
<text
follows="top|left|right"
font="SansSerifHuge"
diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml
index a35e2c3663..a1e32e44de 100644
--- a/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml
+++ b/indra/newview/skins/default/xui/en/widgets/avatar_icon.xml
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<avatar_icon default_icon_name="Generic_Person_Large">
+<avatar_icon
+ default_icon_name="Generic_Person_Large"
+ use_draw_context_alpha="false">
</avatar_icon>
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
index 2d0a1728d5..1746a045cf 100644
--- a/indra/newview/skins/default/xui/en/widgets/button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -24,5 +24,6 @@
halign="center"
pad_bottom="3"
height="23"
- scale_image="true">
+ scale_image="true"
+ use_draw_context_alpha="true">
</button>
diff --git a/indra/newview/skins/default/xui/en/widgets/icon.xml b/indra/newview/skins/default/xui/en/widgets/icon.xml
index adb743a628..cf8edfcedb 100644
--- a/indra/newview/skins/default/xui/en/widgets/icon.xml
+++ b/indra/newview/skins/default/xui/en/widgets/icon.xml
@@ -3,5 +3,6 @@
tab_stop="false"
mouse_opaque="false"
name="icon"
+ use_draw_context_alpha="true"
follows="left|top">
</icon>
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index db50b89620..309e9e9ee3 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -48,6 +48,9 @@ const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
+const std::string VIEWERLOGIN_CHANNEL("invalid_channel");
+const std::string VIEWERLOGIN_VERSION_CHANNEL("invalid_version");
+
// Link seams.
//-----------------------------------------------------------------------------
@@ -160,7 +163,6 @@ std::string LLGridManager::getAppSLURLBase(const std::string& grid_name)
//-----------------------------------------------------------------------------
#include "../llviewercontrol.h"
LLControlGroup gSavedSettings("Global");
-std::string gCurrentVersion = "invalid_version";
LLControlGroup::LLControlGroup(const std::string& name) :
LLInstanceTracker<LLControlGroup, std::string>(name){}
@@ -177,6 +179,10 @@ BOOL LLControlGroup::declareString(const std::string& name, const std::string &i
#include "lluicolortable.h"
void LLUIColorTable::saveUserSettings(void)const {}
+//-----------------------------------------------------------------------------
+#include "../llversioninfo.h"
+const std::string &LLVersionInfo::getChannelAndVersion() { return VIEWERLOGIN_VERSION_CHANNEL; }
+const std::string &LLVersionInfo::getChannel() { return VIEWERLOGIN_CHANNEL; }
//-----------------------------------------------------------------------------
#include "llnotifications.h"
@@ -290,7 +296,6 @@ namespace tut
gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
- gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE);
gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
new file mode 100644
index 0000000000..a6c1f69c82
--- /dev/null
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -0,0 +1,134 @@
+/**
+ * @file llremoteparcelrequest_test.cpp
+ * @author Brad Kittenbrink <brad@lindenlab.com>
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llremoteparcelrequest.h"
+
+#include "../llagent.h"
+#include "message.h"
+
+namespace {
+ LLControlGroup s_saved_settings("dummy_settings");
+ const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
+}
+
+LLCurl::Responder::Responder() { }
+LLCurl::Responder::~Responder() { }
+void LLCurl::Responder::error(U32,std::string const &) { }
+void LLCurl::Responder::result(LLSD const &) { }
+void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { }
+void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
+void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { }
+void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { }
+void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { }
+void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { }
+void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { }
+void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { }
+void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32)
+{
+ out_id = TEST_PARCEL_ID;
+}
+void LLMessageSystem::nextBlock(char const *) { }
+void LLMessageSystem::addUUID(char const *,LLUUID const &) { }
+void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }
+void LLMessageSystem::nextBlockFast(char const *) { }
+void LLMessageSystem::newMessage(char const *) { }
+LLMessageSystem * gMessageSystem;
+char * _PREHASH_AgentID;
+char * _PREHASH_AgentData;
+LLAgent gAgent;
+LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { }
+LLAgent::~LLAgent() { }
+void LLAgent::sendReliableMessage(void) { }
+LLUUID gAgentSessionID;
+LLUUID gAgentID;
+LLUIColor::LLUIColor(void) { }
+LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }
+LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
+LLControlGroup::~LLControlGroup(void) { }
+
+namespace tut
+{
+ struct TestObserver : public LLRemoteParcelInfoObserver {
+ TestObserver() : mProcessed(false) { }
+
+ virtual void processParcelInfo(const LLParcelData& parcel_data)
+ {
+ mProcessed = true;
+ }
+
+ virtual void setParcelID(const LLUUID& parcel_id) { }
+
+ virtual void setErrorStatus(U32 status, const std::string& reason) { }
+
+ bool mProcessed;
+ };
+
+ struct RemoteParcelRequestData
+ {
+ RemoteParcelRequestData()
+ {
+ }
+ };
+
+ typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t;
+ typedef remoteparcelrequest_t::object remoteparcelrequest_object_t;
+ tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest");
+
+ template<> template<>
+ void remoteparcelrequest_object_t::test<1>()
+ {
+ set_test_name("observer pointer");
+
+ boost::scoped_ptr<TestObserver> observer(new TestObserver());
+
+ LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
+ processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get());
+
+ processor.processParcelInfoReply(gMessageSystem, NULL);
+
+ ensure(observer->mProcessed);
+ }
+
+ template<> template<>
+ void remoteparcelrequest_object_t::test<2>()
+ {
+ set_test_name("CHOP-220: dangling observer pointer");
+
+ LLRemoteParcelInfoObserver * observer = new TestObserver();
+
+ LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
+ processor.addObserver(LLUUID(TEST_PARCEL_ID), observer);
+
+ delete observer;
+ observer = NULL;
+
+ processor.processParcelInfoReply(gMessageSystem, NULL);
+ }
+}
diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp
new file mode 100644
index 0000000000..398d8f16ed
--- /dev/null
+++ b/indra/newview/tests/llversioninfo_test.cpp
@@ -0,0 +1,114 @@
+/**
+ * @file llversioninfo_test.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llversioninfo.h"
+#include "llversionviewer.h"
+
+namespace tut
+{
+ struct versioninfo
+ {
+ versioninfo()
+ : mResetChannel("Reset Channel")
+ {
+ std::ostringstream stream;
+ stream << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH << "."
+ << LL_VERSION_BUILD;
+ mVersion = stream.str();
+ stream.str("");
+
+ stream << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH;
+ mShortVersion = stream.str();
+ stream.str("");
+
+ stream << LL_CHANNEL
+ << " "
+ << mVersion;
+ mVersionAndChannel = stream.str();
+ stream.str("");
+
+ stream << mResetChannel
+ << " "
+ << mVersion;
+ mResetVersionAndChannel = stream.str();
+ }
+ std::string mResetChannel;
+ std::string mVersion;
+ std::string mShortVersion;
+ std::string mVersionAndChannel;
+ std::string mResetVersionAndChannel;
+ };
+
+ typedef test_group<versioninfo> versioninfo_t;
+ typedef versioninfo_t::object versioninfo_object_t;
+ tut::versioninfo_t tut_versioninfo("LLVersionInfo");
+
+ template<> template<>
+ void versioninfo_object_t::test<1>()
+ {
+ ensure_equals("Major version",
+ LLVersionInfo::getMajor(),
+ LL_VERSION_MAJOR);
+ ensure_equals("Minor version",
+ LLVersionInfo::getMinor(),
+ LL_VERSION_MINOR);
+ ensure_equals("Patch version",
+ LLVersionInfo::getPatch(),
+ LL_VERSION_PATCH);
+ ensure_equals("Build version",
+ LLVersionInfo::getBuild(),
+ LL_VERSION_BUILD);
+ ensure_equals("Channel version",
+ LLVersionInfo::getChannel(),
+ LL_CHANNEL);
+
+ ensure_equals("Version String",
+ LLVersionInfo::getVersion(),
+ mVersion);
+ ensure_equals("Short Version String",
+ LLVersionInfo::getShortVersion(),
+ mShortVersion);
+ ensure_equals("Version and channel String",
+ LLVersionInfo::getChannelAndVersion(),
+ mVersionAndChannel);
+
+ LLVersionInfo::resetChannel(mResetChannel);
+ ensure_equals("Reset channel version",
+ LLVersionInfo::getChannel(),
+ mResetChannel);
+
+ ensure_equals("Reset Version and channel String",
+ LLVersionInfo::getChannelAndVersion(),
+ mResetVersionAndChannel);
+ }
+}
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index a0f1d1c3c3..b425b50c8b 100644
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -72,16 +72,13 @@ static void substitute_string(std::string &input, const std::string &search, con
}
}
-class LLAgent
-{
-public:
- LLAgent() {}
- ~LLAgent() {}
-#ifdef __GNUC__
- __attribute__ ((noinline))
-#endif
- bool isGodlike() const { return FALSE; }
-};
+#include "../llagent.h"
+LLAgent::LLAgent() : mAgentAccess(gSavedSettings) { }
+LLAgent::~LLAgent() { }
+bool LLAgent::isGodlike() const { return FALSE; }
+LLAgentAccess::LLAgentAccess(LLControlGroup& settings) : mSavedSettings(settings) { }
+LLUIColor::LLUIColor() {}
+
LLAgent gAgent;
std::string LLWeb::expandURLSubstitutions(const std::string &url,
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 6861f02bfb..6c77f8ec38 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -247,6 +247,8 @@ class WindowsManifest(ViewerManifest):
self.disable_manifest_check()
+ self.path(src="../viewer_components/updater/scripts/windows/update_install.bat", dst="update_install.bat")
+
# Get shared libs from the shared libs staging directory
if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']),
dst=""):
@@ -572,6 +574,8 @@ class DarwinManifest(ViewerManifest):
# copy additional libs in <bundle>/Contents/MacOS/
self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib")
+ self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install")
+
# most everything goes in the Resources directory
if self.prefix(src="", dst="Resources"):
super(DarwinManifest, self).construct()
@@ -707,6 +711,11 @@ class DarwinManifest(ViewerManifest):
self.run_command('strip -S %(viewer_binary)r' %
{ 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
+ def copy_finish(self):
+ # Force executable permissions to be set for scripts
+ # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
+ for script in 'Contents/MacOS/update_install',:
+ self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
def package_finish(self):
channel_standin = 'Second Life Viewer 2' # hah, our default channel is not usable on its own
@@ -743,6 +752,11 @@ class DarwinManifest(ViewerManifest):
devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
+ if devfile != '/dev/disk1':
+ # adding more debugging info based upon nat's hunches to the
+ # logs to help track down 'SetFile -a V' failures -brad
+ print "WARNING: 'SetFile -a V' command below is probably gonna fail"
+
# Copy everything in to the mounted .dmg
if self.default_channel() and not self.default_grid():
@@ -842,6 +856,8 @@ class LinuxManifest(ViewerManifest):
# recurse
self.end_prefix("res-sdl")
+ self.path("../viewer_components/updater/scripts/linux/update_install", "bin/update_install")
+
# plugins
if self.prefix(src="", dst="bin/llplugin"):
self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
@@ -855,6 +871,12 @@ class LinuxManifest(ViewerManifest):
self.path("featuretable_linux.txt")
+ def copy_finish(self):
+ # Force executable permissions to be set for scripts
+ # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
+ for script in 'secondlife', 'bin/update_install':
+ self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
+
def package_finish(self):
if 'installer_name' in self.args:
installer_name = self.args['installer_name']
@@ -870,7 +892,7 @@ class LinuxManifest(ViewerManifest):
if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
- self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
+ self.run_command("find %(d)r/bin %(d)r/lib -type f \\! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
# Fix access permissions
self.run_command("""
@@ -897,6 +919,9 @@ class LinuxManifest(ViewerManifest):
'dir': self.get_build_prefix(),
'inst_name': installer_name,
'inst_path':self.build_path_of(installer_name)})
+ else:
+ print "Skipping %s.tar.bz2 for non-Release build (%s)" % \
+ (installer_name, self.args['buildtype'])
finally:
self.run_command("mv %(inst)s %(dst)s" % {
'dst': self.get_dst_prefix(),
diff --git a/indra/viewer_components/CMakeLists.txt b/indra/viewer_components/CMakeLists.txt
index 0993b64b14..74c9b4568d 100644
--- a/indra/viewer_components/CMakeLists.txt
+++ b/indra/viewer_components/CMakeLists.txt
@@ -1,4 +1,4 @@
# -*- cmake -*-
add_subdirectory(login)
-
+add_subdirectory(updater)
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt
new file mode 100644
index 0000000000..0e288bb496
--- /dev/null
+++ b/indra/viewer_components/updater/CMakeLists.txt
@@ -0,0 +1,82 @@
+# -*- cmake -*-
+
+project(updater_service)
+
+include(00-Common)
+if(LL_TESTS)
+ include(LLAddBuildTest)
+endif(LL_TESTS)
+include(CMakeCopyIfDifferent)
+include(CURL)
+include(LLCommon)
+include(LLMessage)
+include(LLPlugin)
+include(LLVFS)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLMESSAGE_INCLUDE_DIRS}
+ ${LLPLUGIN_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
+ ${CURL_INCLUDE_DIRS}
+ )
+
+set(updater_service_SOURCE_FILES
+ llupdaterservice.cpp
+ llupdatechecker.cpp
+ llupdatedownloader.cpp
+ llupdateinstaller.cpp
+ )
+
+set(updater_service_HEADER_FILES
+ llupdaterservice.h
+ llupdatechecker.h
+ llupdatedownloader.h
+ llupdateinstaller.h
+ )
+
+set_source_files_properties(${updater_service_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND
+ updater_service_SOURCE_FILES
+ ${updater_service_HEADER_FILES}
+ )
+
+add_library(llupdaterservice
+ ${updater_service_SOURCE_FILES}
+ )
+
+target_link_libraries(llupdaterservice
+ ${LLCOMMON_LIBRARIES}
+ ${LLMESSAGE_LIBRARIES}
+ ${LLPLUGIN_LIBRARIES}
+ ${LLVFS_LIBRARIES}
+ )
+
+if(LL_TESTS)
+ SET(llupdater_service_TEST_SOURCE_FILES
+ llupdaterservice.cpp
+ )
+
+# *NOTE:Mani - I was trying to use the preprocessor seam to mock out
+# llifstream (and other) llcommon classes. I didn't work
+# because of the windows declspec(dllimport)attribute.
+#set_source_files_properties(
+# llupdaterservice.cpp
+# PROPERTIES
+# LL_TEST_ADDITIONAL_CFLAGS "-Dllifstream=llus_mock_llifstream"
+# )
+
+ LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}")
+endif(LL_TESTS)
+
+set(UPDATER_INCLUDE_DIRS
+ ${LIBS_OPEN_DIR}/viewer_components/updater
+ CACHE INTERNAL ""
+)
+
+set(UPDATER_LIBRARIES
+ llupdaterservice
+ CACHE INTERNAL ""
+)
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
new file mode 100644
index 0000000000..c6aa9b0f11
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -0,0 +1,194 @@
+/**
+ * @file llupdaterservice.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <stdexcept>
+#include <boost/format.hpp>
+#include "llhttpclient.h"
+#include "llsd.h"
+#include "llupdatechecker.h"
+#include "lluri.h"
+
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+
+class LLUpdateChecker::CheckError:
+ public std::runtime_error
+{
+public:
+ CheckError(const char * message):
+ std::runtime_error(message)
+ {
+ ; // No op.
+ }
+};
+
+
+class LLUpdateChecker::Implementation:
+ public LLHTTPClient::Responder
+{
+public:
+ Implementation(Client & client);
+ ~Implementation();
+ void check(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version);
+
+ // Responder:
+ virtual void completed(U32 status,
+ const std::string & reason,
+ const LLSD& content);
+ virtual void error(U32 status, const std::string & reason);
+
+private:
+ static const char * sProtocolVersion;
+
+ Client & mClient;
+ LLHTTPClient mHttpClient;
+ bool mInProgress;
+ std::string mVersion;
+
+ std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version);
+
+ LOG_CLASS(LLUpdateChecker::Implementation);
+};
+
+
+
+// LLUpdateChecker
+//-----------------------------------------------------------------------------
+
+
+LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
+ mImplementation(new LLUpdateChecker::Implementation(client))
+{
+ ; // No op.
+}
+
+
+void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version)
+{
+ mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version);
+}
+
+
+
+// LLUpdateChecker::Implementation
+//-----------------------------------------------------------------------------
+
+
+const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0";
+
+
+LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
+ mClient(client),
+ mInProgress(false)
+{
+ ; // No op.
+}
+
+
+LLUpdateChecker::Implementation::~Implementation()
+{
+ ; // No op.
+}
+
+
+void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version)
+{
+ llassert(!mInProgress);
+
+ if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol");
+
+ mInProgress = true;
+ mVersion = version;
+ std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version);
+ LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
+
+ // The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the
+ // passed object to be silently and automatically deleted. We pass a self-
+ // referential intrusive pointer to which we add a reference to keep the
+ // client from deleting the update checker implementation instance.
+ LLHTTPClient::ResponderPtr temporaryPtr(this);
+ boost::intrusive_ptr_add_ref(temporaryPtr.get());
+ mHttpClient.get(checkUrl, temporaryPtr);
+}
+
+void LLUpdateChecker::Implementation::completed(U32 status,
+ const std::string & reason,
+ const LLSD & content)
+{
+ mInProgress = false;
+
+ if(status != 200) {
+ LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
+ mClient.error(reason);
+ } else if(!content.asBoolean()) {
+ LL_INFOS("UpdateCheck") << "up to date" << llendl;
+ mClient.upToDate();
+ } else if(content["required"].asBoolean()) {
+ LL_INFOS("UpdateCheck") << "version invalid" << llendl;
+ LLURI uri(content["url"].asString());
+ mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString());
+ } else {
+ LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl;
+ LLURI uri(content["url"].asString());
+ mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString());
+ }
+}
+
+
+void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
+{
+ mInProgress = false;
+ LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
+ mClient.error(reason);
+}
+
+
+std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version)
+{
+#ifdef LL_WINDOWS
+ static const char * platform = "win";
+#elif LL_DARWIN
+ static const char * platform = "mac";
+#else
+ static const char * platform = "lnx";
+#endif
+
+ LLSD path;
+ path.append(servicePath);
+ path.append(protocolVersion);
+ path.append(channel);
+ path.append(version);
+ path.append(platform);
+ return LLURI::buildHTTP(hostUrl, path).asString();
+}
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
new file mode 100644
index 0000000000..cea1f13647
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -0,0 +1,82 @@
+/**
+ * @file llupdatechecker.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATERCHECKER_H
+#define LL_UPDATERCHECKER_H
+
+
+#include <boost/shared_ptr.hpp>
+
+
+//
+// Implements asynchronous checking for updates.
+//
+class LLUpdateChecker {
+public:
+ class Client;
+ class Implementation;
+
+ // An exception that may be raised on check errors.
+ class CheckError;
+
+ LLUpdateChecker(Client & client);
+
+ // Check status of current app on the given host for the channel and version provided.
+ void check(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version);
+
+private:
+ boost::shared_ptr<Implementation> mImplementation;
+};
+
+
+class LLURI; // From lluri.h
+
+
+//
+// The client interface implemented by a requestor checking for an update.
+//
+class LLUpdateChecker::Client
+{
+public:
+ // An error occurred while checking for an update.
+ virtual void error(std::string const & message) = 0;
+
+ // A newer version is available, but the current version may still be used.
+ virtual void optionalUpdate(std::string const & newVersion,
+ LLURI const & uri,
+ std::string const & hash) = 0;
+
+ // A newer version is available, and the current version is no longer valid.
+ virtual void requiredUpdate(std::string const & newVersion,
+ LLURI const & uri,
+ std::string const & hash) = 0;
+
+ // The checked version is up to date; no newer version exists.
+ virtual void upToDate(void) = 0;
+};
+
+
+#endif
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
new file mode 100644
index 0000000000..c17a50e242
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -0,0 +1,428 @@
+/**
+ * @file llupdatedownloader.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <stdexcept>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+#include <curl/curl.h>
+#include "lldir.h"
+#include "llfile.h"
+#include "llmd5.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llthread.h"
+#include "llupdatedownloader.h"
+#include "llupdaterservice.h"
+
+
+class LLUpdateDownloader::Implementation:
+ public LLThread
+{
+public:
+ Implementation(LLUpdateDownloader::Client & client);
+ ~Implementation();
+ void cancel(void);
+ void download(LLURI const & uri, std::string const & hash);
+ bool isDownloading(void);
+ size_t onHeader(void * header, size_t size);
+ size_t onBody(void * header, size_t size);
+ void resume(void);
+
+private:
+ bool mCancelled;
+ LLUpdateDownloader::Client & mClient;
+ CURL * mCurl;
+ LLSD mDownloadData;
+ llofstream mDownloadStream;
+ std::string mDownloadRecordPath;
+ curl_slist * mHeaderList;
+
+ void initializeCurlGet(std::string const & url, bool processHeader);
+ void resumeDownloading(size_t startByte);
+ void run(void);
+ void startDownloading(LLURI const & uri, std::string const & hash);
+ void throwOnCurlError(CURLcode code);
+ bool validateDownload(void);
+
+ LOG_CLASS(LLUpdateDownloader::Implementation);
+};
+
+
+namespace {
+ class DownloadError:
+ public std::runtime_error
+ {
+ public:
+ DownloadError(const char * message):
+ std::runtime_error(message)
+ {
+ ; // No op.
+ }
+ };
+
+
+ const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml";
+};
+
+
+
+// LLUpdateDownloader
+//-----------------------------------------------------------------------------
+
+
+
+std::string LLUpdateDownloader::downloadMarkerPath(void)
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, gSecondLifeUpdateRecord);
+}
+
+
+LLUpdateDownloader::LLUpdateDownloader(Client & client):
+ mImplementation(new LLUpdateDownloader::Implementation(client))
+{
+ ; // No op.
+}
+
+
+void LLUpdateDownloader::cancel(void)
+{
+ mImplementation->cancel();
+}
+
+
+void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash)
+{
+ mImplementation->download(uri, hash);
+}
+
+
+bool LLUpdateDownloader::isDownloading(void)
+{
+ return mImplementation->isDownloading();
+}
+
+
+void LLUpdateDownloader::resume(void)
+{
+ mImplementation->resume();
+}
+
+
+
+// LLUpdateDownloader::Implementation
+//-----------------------------------------------------------------------------
+
+
+namespace {
+ size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader)
+ {
+ size_t bytes = blockSize * blocks;
+ return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onBody(data, bytes);
+ }
+
+
+ size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader)
+ {
+ size_t bytes = blockSize * blocks;
+ return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes);
+ }
+}
+
+
+LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client):
+ LLThread("LLUpdateDownloader"),
+ mCancelled(false),
+ mClient(client),
+ mCurl(0),
+ mHeaderList(0)
+{
+ CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case.
+ llverify(code == CURLE_OK); // TODO: real error handling here.
+}
+
+
+LLUpdateDownloader::Implementation::~Implementation()
+{
+ if(isDownloading()) {
+ cancel();
+ shutdown();
+ } else {
+ ; // No op.
+ }
+ if(mCurl) curl_easy_cleanup(mCurl);
+}
+
+
+void LLUpdateDownloader::Implementation::cancel(void)
+{
+ mCancelled = true;
+}
+
+
+void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash)
+{
+ if(isDownloading()) mClient.downloadError("download in progress");
+
+ mDownloadRecordPath = downloadMarkerPath();
+ mDownloadData = LLSD();
+ try {
+ startDownloading(uri, hash);
+ } catch(DownloadError const & e) {
+ mClient.downloadError(e.what());
+ }
+}
+
+
+bool LLUpdateDownloader::Implementation::isDownloading(void)
+{
+ return !isStopped();
+}
+
+
+void LLUpdateDownloader::Implementation::resume(void)
+{
+ mCancelled = false;
+
+ if(isDownloading()) {
+ mClient.downloadError("download in progress");
+ }
+
+ mDownloadRecordPath = downloadMarkerPath();
+ llifstream dataStream(mDownloadRecordPath);
+ if(!dataStream) {
+ mClient.downloadError("no download marker");
+ return;
+ }
+
+ LLSDSerialize::fromXMLDocument(mDownloadData, dataStream);
+
+ if(!mDownloadData.asBoolean()) {
+ mClient.downloadError("no download information in marker");
+ return;
+ }
+
+ std::string filePath = mDownloadData["path"].asString();
+ try {
+ if(LLFile::isfile(filePath)) {
+ llstat fileStatus;
+ LLFile::stat(filePath, &fileStatus);
+ if(fileStatus.st_size != mDownloadData["size"].asInteger()) {
+ resumeDownloading(fileStatus.st_size);
+ } else if(!validateDownload()) {
+ LLFile::remove(filePath);
+ download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString());
+ } else {
+ mClient.downloadComplete(mDownloadData);
+ }
+ } else {
+ download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString());
+ }
+ } catch(DownloadError & e) {
+ mClient.downloadError(e.what());
+ }
+}
+
+
+size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
+{
+ char const * headerPtr = reinterpret_cast<const char *> (buffer);
+ std::string header(headerPtr, headerPtr + size);
+ size_t colonPosition = header.find(':');
+ if(colonPosition == std::string::npos) return size; // HTML response; ignore.
+
+ if(header.substr(0, colonPosition) == "Content-Length") {
+ try {
+ size_t firstDigitPos = header.find_first_of("0123456789", colonPosition);
+ size_t lastDigitPos = header.find_last_of("0123456789");
+ std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1);
+ size_t size = boost::lexical_cast<size_t>(contentLength);
+ LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL;
+
+ mDownloadData["size"] = LLSD(LLSD::Integer(size));
+ llofstream odataStream(mDownloadRecordPath);
+ LLSDSerialize::toPrettyXML(mDownloadData, odataStream);
+ } catch (std::exception const & e) {
+ LL_WARNS("UpdateDownload") << "unable to read content length ("
+ << e.what() << ")" << LL_ENDL;
+ }
+ } else {
+ ; // No op.
+ }
+
+ return size;
+}
+
+
+size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size)
+{
+ if(mCancelled) return 0; // Forces a write error which will halt curl thread.
+ if((size == 0) || (buffer == 0)) return 0;
+
+ mDownloadStream.write(reinterpret_cast<const char *>(buffer), size);
+ if(mDownloadStream.bad()) {
+ return 0;
+ } else {
+ return size;
+ }
+}
+
+
+void LLUpdateDownloader::Implementation::run(void)
+{
+ CURLcode code = curl_easy_perform(mCurl);
+ mDownloadStream.close();
+ if(code == CURLE_OK) {
+ LLFile::remove(mDownloadRecordPath);
+ if(validateDownload()) {
+ LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL;
+ mClient.downloadComplete(mDownloadData);
+ } else {
+ LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL;
+ std::string filePath = mDownloadData["path"].asString();
+ if(filePath.size() != 0) LLFile::remove(filePath);
+ mClient.downloadError("failed hash check");
+ }
+ } else if(mCancelled && (code == CURLE_WRITE_ERROR)) {
+ LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL;
+ // Do not call back client.
+ } else {
+ LL_WARNS("UpdateDownload") << "download failed with error '" <<
+ curl_easy_strerror(code) << "'" << LL_ENDL;
+ LLFile::remove(mDownloadRecordPath);
+ if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString());
+ mClient.downloadError("curl error");
+ }
+
+ if(mHeaderList) {
+ curl_slist_free_all(mHeaderList);
+ mHeaderList = 0;
+ }
+}
+
+
+void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)
+{
+ if(mCurl == 0) {
+ mCurl = curl_easy_init();
+ } else {
+ curl_easy_reset(mCurl);
+ }
+
+ if(mCurl == 0) throw DownloadError("failed to initialize curl");
+
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this));
+ if(processHeader) {
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this));
+ }
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true));
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()));
+}
+
+
+void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
+{
+ LL_INFOS("UpdateDownload") << "resuming download from " << mDownloadData["url"].asString()
+ << " at byte " << startByte << LL_ENDL;
+
+ initializeCurlGet(mDownloadData["url"].asString(), false);
+
+ // The header 'Range: bytes n-' will request the bytes remaining in the
+ // source begining with byte n and ending with the last byte.
+ boost::format rangeHeaderFormat("Range: bytes=%u-");
+ rangeHeaderFormat % startByte;
+ mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
+ if(mHeaderList == 0) throw DownloadError("cannot add Range header");
+ throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList));
+
+ mDownloadStream.open(mDownloadData["path"].asString(),
+ std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+ start();
+}
+
+
+void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std::string const & hash)
+{
+ mDownloadData["url"] = uri.asString();
+ mDownloadData["hash"] = hash;
+ mDownloadData["current_version"] = ll_get_version();
+ LLSD path = uri.pathArray();
+ if(path.size() == 0) throw DownloadError("no file path");
+ std::string fileName = path[path.size() - 1].asString();
+ std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);
+ mDownloadData["path"] = filePath;
+
+ LL_INFOS("UpdateDownload") << "downloading " << filePath
+ << " from " << uri.asString() << LL_ENDL;
+ LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL;
+
+ llofstream dataStream(mDownloadRecordPath);
+ LLSDSerialize::toPrettyXML(mDownloadData, dataStream);
+
+ mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary);
+ initializeCurlGet(uri.asString(), true);
+ start();
+}
+
+
+void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
+{
+ if(code != CURLE_OK) {
+ const char * errorString = curl_easy_strerror(code);
+ if(errorString != 0) {
+ throw DownloadError(curl_easy_strerror(code));
+ } else {
+ throw DownloadError("unknown curl error");
+ }
+ } else {
+ ; // No op.
+ }
+}
+
+
+bool LLUpdateDownloader::Implementation::validateDownload(void)
+{
+ std::string filePath = mDownloadData["path"].asString();
+ llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);
+ if(!fileStream) return false;
+
+ std::string hash = mDownloadData["hash"].asString();
+ if(hash.size() != 0) {
+ LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL;
+ char digest[33];
+ LLMD5(fileStream).hex_digest(digest);
+ if(hash != digest) {
+ LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash <<
+ " but download is " << digest << LL_ENDL;
+ }
+ return hash == digest;
+ } else {
+ return true; // No hash check provided.
+ }
+}
diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h
new file mode 100644
index 0000000000..1b3d7480fd
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatedownloader.h
@@ -0,0 +1,87 @@
+/**
+ * @file llupdatedownloader.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATE_DOWNLOADER_H
+#define LL_UPDATE_DOWNLOADER_H
+
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include "lluri.h"
+
+
+//
+// An asynchronous download service for fetching updates.
+//
+class LLUpdateDownloader
+{
+public:
+ class Client;
+ class Implementation;
+
+ // Returns the path to the download marker file containing details of the
+ // latest download.
+ static std::string downloadMarkerPath(void);
+
+ LLUpdateDownloader(Client & client);
+
+ // Cancel any in progress download; a no op if none is in progress. The
+ // client will not receive a complete or error callback.
+ void cancel(void);
+
+ // Start a new download.
+ void download(LLURI const & uri, std::string const & hash);
+
+ // Returns true if a download is in progress.
+ bool isDownloading(void);
+
+ // Resume a partial download.
+ void resume(void);
+
+private:
+ boost::shared_ptr<Implementation> mImplementation;
+};
+
+
+//
+// An interface to be implemented by clients initiating a update download.
+//
+class LLUpdateDownloader::Client {
+public:
+
+ // The download has completed successfully.
+ // data is a map containing the following items:
+ // url - source (remote) location
+ // hash - the md5 sum that should match the installer file.
+ // path - destination (local) location
+ // size - the size of the installer in bytes
+ virtual void downloadComplete(LLSD const & data) = 0;
+
+ // The download failed.
+ virtual void downloadError(std::string const & message) = 0;
+};
+
+
+#endif
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
new file mode 100644
index 0000000000..6e69bcf28b
--- /dev/null
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -0,0 +1,90 @@
+/**
+ * @file llupdateinstaller.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <apr_file_io.h>
+#include "llapr.h"
+#include "llprocesslauncher.h"
+#include "llupdateinstaller.h"
+#include "lldir.h"
+
+
+namespace {
+ class RelocateError {};
+
+
+ std::string copy_to_temp(std::string const & path)
+ {
+ std::string scriptFile = gDirUtilp->getBaseFileName(path);
+ std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
+ apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
+ if(status != APR_SUCCESS) throw RelocateError();
+
+ return newPath;
+ }
+}
+
+
+int ll_install_update(std::string const & script, std::string const & updatePath, LLInstallScriptMode mode)
+{
+ std::string actualScriptPath;
+ switch(mode) {
+ case LL_COPY_INSTALL_SCRIPT_TO_TEMP:
+ try {
+ actualScriptPath = copy_to_temp(script);
+ }
+ catch (RelocateError &) {
+ return -1;
+ }
+ break;
+ case LL_RUN_INSTALL_SCRIPT_IN_PLACE:
+ actualScriptPath = script;
+ break;
+ default:
+ llassert(!"unpossible copy mode");
+ }
+
+ llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
+ actualScriptPath << LL_ENDL;
+
+ LLProcessLauncher launcher;
+ launcher.setExecutable(actualScriptPath);
+ launcher.addArgument(updatePath);
+ launcher.addArgument(ll_install_failed_marker_path().c_str());
+ int result = launcher.launch();
+ launcher.orphan();
+
+ return result;
+}
+
+
+std::string const & ll_install_failed_marker_path(void)
+{
+ static std::string path;
+ if(path.empty()) {
+ path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeInstallFailed.marker");
+ }
+ return path;
+}
diff --git a/indra/viewer_components/updater/llupdateinstaller.h b/indra/viewer_components/updater/llupdateinstaller.h
new file mode 100644
index 0000000000..6ce08ce6fa
--- /dev/null
+++ b/indra/viewer_components/updater/llupdateinstaller.h
@@ -0,0 +1,57 @@
+/**
+ * @file llupdateinstaller.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATE_INSTALLER_H
+#define LL_UPDATE_INSTALLER_H
+
+
+#include <string>
+
+
+enum LLInstallScriptMode {
+ LL_RUN_INSTALL_SCRIPT_IN_PLACE,
+ LL_COPY_INSTALL_SCRIPT_TO_TEMP
+};
+
+//
+// Launch the installation script.
+//
+// The updater will overwrite the current installation, so it is highly recommended
+// that the current application terminate once this function is called.
+//
+int ll_install_update(
+ std::string const & script, // Script to execute.
+ std::string const & updatePath, // Path to update file.
+ LLInstallScriptMode mode=LL_COPY_INSTALL_SCRIPT_TO_TEMP); // Run in place or copy to temp?
+
+
+//
+// Returns the path which points to the failed install marker file, should it
+// exist.
+//
+std::string const & ll_install_failed_marker_path(void);
+
+
+#endif
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
new file mode 100644
index 0000000000..cc60eaead2
--- /dev/null
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -0,0 +1,519 @@
+/**
+ * @file llupdaterservice.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llupdatedownloader.h"
+#include "llevents.h"
+#include "lltimer.h"
+#include "llupdaterservice.h"
+#include "llupdatechecker.h"
+#include "llupdateinstaller.h"
+#include "llversionviewer.h"
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include "lldir.h"
+#include "llsdserialize.h"
+#include "llfile.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+
+namespace
+{
+ boost::weak_ptr<LLUpdaterServiceImpl> gUpdater;
+
+ const std::string UPDATE_MARKER_FILENAME("SecondLifeUpdateReady.xml");
+ std::string update_marker_path()
+ {
+ return gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+ UPDATE_MARKER_FILENAME);
+ }
+
+ std::string install_script_path(void)
+ {
+#ifdef LL_WINDOWS
+ std::string scriptFile = "update_install.bat";
+#else
+ std::string scriptFile = "update_install";
+#endif
+ return gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, scriptFile);
+ }
+
+ LLInstallScriptMode install_script_mode(void)
+ {
+#ifdef LL_WINDOWS
+ return LL_COPY_INSTALL_SCRIPT_TO_TEMP;
+#else
+ return LL_RUN_INSTALL_SCRIPT_IN_PLACE;
+#endif
+ };
+
+}
+
+class LLUpdaterServiceImpl :
+ public LLUpdateChecker::Client,
+ public LLUpdateDownloader::Client
+{
+ static const std::string sListenerName;
+
+ std::string mProtocolVersion;
+ std::string mUrl;
+ std::string mPath;
+ std::string mChannel;
+ std::string mVersion;
+
+ unsigned int mCheckPeriod;
+ bool mIsChecking;
+ bool mIsDownloading;
+
+ LLUpdateChecker mUpdateChecker;
+ LLUpdateDownloader mUpdateDownloader;
+ LLTimer mTimer;
+
+ LLUpdaterService::app_exit_callback_t mAppExitCallback;
+
+ LOG_CLASS(LLUpdaterServiceImpl);
+
+public:
+ LLUpdaterServiceImpl();
+ virtual ~LLUpdaterServiceImpl();
+
+ void initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version);
+
+ void setCheckPeriod(unsigned int seconds);
+
+ void startChecking(bool install_if_ready);
+ void stopChecking();
+ bool isChecking();
+
+ void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;}
+
+ bool checkForInstall(bool launchInstaller); // Test if a local install is ready.
+ bool checkForResume(); // Test for resumeable d/l.
+
+ // LLUpdateChecker::Client:
+ virtual void error(std::string const & message);
+ virtual void optionalUpdate(std::string const & newVersion,
+ LLURI const & uri,
+ std::string const & hash);
+ virtual void requiredUpdate(std::string const & newVersion,
+ LLURI const & uri,
+ std::string const & hash);
+ virtual void upToDate(void);
+
+ // LLUpdateDownloader::Client
+ void downloadComplete(LLSD const & data);
+ void downloadError(std::string const & message);
+
+ bool onMainLoop(LLSD const & event);
+
+private:
+ void restartTimer(unsigned int seconds);
+ void stopTimer();
+};
+
+const std::string LLUpdaterServiceImpl::sListenerName = "LLUpdaterServiceImpl";
+
+LLUpdaterServiceImpl::LLUpdaterServiceImpl() :
+ mIsChecking(false),
+ mIsDownloading(false),
+ mCheckPeriod(0),
+ mUpdateChecker(*this),
+ mUpdateDownloader(*this)
+{
+}
+
+LLUpdaterServiceImpl::~LLUpdaterServiceImpl()
+{
+ LL_INFOS("UpdaterService") << "shutting down updater service" << LL_ENDL;
+ LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
+}
+
+void LLUpdaterServiceImpl::initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version)
+{
+ if(mIsChecking || mIsDownloading)
+ {
+ throw LLUpdaterService::UsageError("LLUpdaterService::initialize call "
+ "while updater is running.");
+ }
+
+ mProtocolVersion = protocol_version;
+ mUrl = url;
+ mPath = path;
+ mChannel = channel;
+ mVersion = version;
+}
+
+void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds)
+{
+ mCheckPeriod = seconds;
+}
+
+void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
+{
+ if(mUrl.empty() || mChannel.empty() || mVersion.empty())
+ {
+ throw LLUpdaterService::UsageError("Set params before call to "
+ "LLUpdaterService::startCheck().");
+ }
+
+ mIsChecking = true;
+
+ // Check to see if an install is ready.
+ bool has_install = checkForInstall(install_if_ready);
+ if(!has_install)
+ {
+ checkForResume(); // will set mIsDownloading to true if resuming
+
+ if(!mIsDownloading)
+ {
+ // Checking can only occur during the mainloop.
+ // reset the timer to 0 so that the next mainloop event
+ // triggers a check;
+ restartTimer(0);
+ }
+ }
+}
+
+void LLUpdaterServiceImpl::stopChecking()
+{
+ if(mIsChecking)
+ {
+ mIsChecking = false;
+ stopTimer();
+ }
+
+ if(mIsDownloading)
+ {
+ mUpdateDownloader.cancel();
+ mIsDownloading = false;
+ }
+}
+
+bool LLUpdaterServiceImpl::isChecking()
+{
+ return mIsChecking;
+}
+
+bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
+{
+ bool foundInstall = false; // return true if install is found.
+
+ llifstream update_marker(update_marker_path(),
+ std::ios::in | std::ios::binary);
+
+ if(update_marker.is_open())
+ {
+ // Found an update info - now lets see if its valid.
+ LLSD update_info;
+ LLSDSerialize::fromXMLDocument(update_info, update_marker);
+ update_marker.close();
+
+ // Get the path to the installer file.
+ LLSD path = update_info.get("path");
+ if(update_info["current_version"].asString() != ll_get_version())
+ {
+ // This viewer is not the same version as the one that downloaded
+ // the update. Do not install this update.
+ if(!path.asString().empty())
+ {
+ llinfos << "ignoring update dowloaded by different client version" << llendl;
+ LLFile::remove(path.asString());
+ LLFile::remove(update_marker_path());
+ }
+ else
+ {
+ ; // Nothing to clean up.
+ }
+
+ foundInstall = false;
+ }
+ else if(path.isDefined() && !path.asString().empty())
+ {
+ if(launchInstaller)
+ {
+ LLFile::remove(update_marker_path());
+
+ int result = ll_install_update(install_script_path(),
+ update_info["path"].asString(),
+ install_script_mode());
+
+ if((result == 0) && mAppExitCallback)
+ {
+ mAppExitCallback();
+ } else if(result != 0) {
+ llwarns << "failed to run update install script" << LL_ENDL;
+ } else {
+ ; // No op.
+ }
+ }
+
+ foundInstall = true;
+ }
+ }
+ return foundInstall;
+}
+
+bool LLUpdaterServiceImpl::checkForResume()
+{
+ bool result = false;
+ std::string download_marker_path = mUpdateDownloader.downloadMarkerPath();
+ if(LLFile::isfile(download_marker_path))
+ {
+ llifstream download_marker_stream(download_marker_path,
+ std::ios::in | std::ios::binary);
+ if(download_marker_stream.is_open())
+ {
+ LLSD download_info;
+ LLSDSerialize::fromXMLDocument(download_info, download_marker_stream);
+ download_marker_stream.close();
+ if(download_info["current_version"].asString() == ll_get_version())
+ {
+ mIsDownloading = true;
+ mUpdateDownloader.resume();
+ result = true;
+ }
+ else
+ {
+ // The viewer that started this download is not the same as this viewer; ignore.
+ llinfos << "ignoring partial download from different viewer version" << llendl;
+ std::string path = download_info["path"].asString();
+ if(!path.empty()) LLFile::remove(path);
+ LLFile::remove(download_marker_path);
+ }
+ }
+ }
+ return result;
+}
+
+void LLUpdaterServiceImpl::error(std::string const & message)
+{
+ if(mIsChecking)
+ {
+ restartTimer(mCheckPeriod);
+ }
+}
+
+void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion,
+ LLURI const & uri,
+ std::string const & hash)
+{
+ stopTimer();
+ mIsDownloading = true;
+ mUpdateDownloader.download(uri, hash);
+}
+
+void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion,
+ LLURI const & uri,
+ std::string const & hash)
+{
+ stopTimer();
+ mIsDownloading = true;
+ mUpdateDownloader.download(uri, hash);
+}
+
+void LLUpdaterServiceImpl::upToDate(void)
+{
+ if(mIsChecking)
+ {
+ restartTimer(mCheckPeriod);
+ }
+}
+
+void LLUpdaterServiceImpl::downloadComplete(LLSD const & data)
+{
+ mIsDownloading = false;
+
+ // Save out the download data to the SecondLifeUpdateReady
+ // marker file.
+ llofstream update_marker(update_marker_path());
+ LLSDSerialize::toPrettyXML(data, update_marker);
+
+ LLSD event;
+ event["pump"] = LLUpdaterService::pumpName();
+ LLSD payload;
+ payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE);
+ event["payload"] = payload;
+ LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+}
+
+void LLUpdaterServiceImpl::downloadError(std::string const & message)
+{
+ LL_INFOS("UpdaterService") << "Error downloading: " << message << LL_ENDL;
+
+ mIsDownloading = false;
+
+ // Restart the timer on error
+ if(mIsChecking)
+ {
+ restartTimer(mCheckPeriod);
+ }
+
+ LLSD event;
+ event["pump"] = LLUpdaterService::pumpName();
+ LLSD payload;
+ payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_ERROR);
+ payload["message"] = message;
+ event["payload"] = payload;
+ LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+}
+
+void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
+{
+ LL_INFOS("UpdaterService") << "will check for update again in " <<
+ seconds << " seconds" << LL_ENDL;
+ mTimer.start();
+ mTimer.setTimerExpirySec(seconds);
+ LLEventPumps::instance().obtain("mainloop").listen(
+ sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
+}
+
+void LLUpdaterServiceImpl::stopTimer()
+{
+ mTimer.stop();
+ LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
+}
+
+bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
+{
+ if(mTimer.getStarted() && mTimer.hasExpired())
+ {
+ stopTimer();
+
+ // Check for failed install.
+ if(LLFile::isfile(ll_install_failed_marker_path()))
+ {
+ // TODO: notify the user.
+ llinfos << "found marker " << ll_install_failed_marker_path() << llendl;
+ llinfos << "last install attempt failed" << llendl;
+ LLFile::remove(ll_install_failed_marker_path());
+
+ LLSD event;
+ event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR);
+ LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event);
+ }
+ else
+ {
+ mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
+ }
+ }
+ else
+ {
+ // Keep on waiting...
+ }
+
+ return false;
+}
+
+
+//-----------------------------------------------------------------------
+// Facade interface
+
+std::string const & LLUpdaterService::pumpName(void)
+{
+ static std::string name("updater_service");
+ return name;
+}
+
+LLUpdaterService::LLUpdaterService()
+{
+ if(gUpdater.expired())
+ {
+ mImpl =
+ boost::shared_ptr<LLUpdaterServiceImpl>(new LLUpdaterServiceImpl());
+ gUpdater = mImpl;
+ }
+ else
+ {
+ mImpl = gUpdater.lock();
+ }
+}
+
+LLUpdaterService::~LLUpdaterService()
+{
+}
+
+void LLUpdaterService::initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version)
+{
+ mImpl->initialize(protocol_version, url, path, channel, version);
+}
+
+void LLUpdaterService::setCheckPeriod(unsigned int seconds)
+{
+ mImpl->setCheckPeriod(seconds);
+}
+
+void LLUpdaterService::startChecking(bool install_if_ready)
+{
+ mImpl->startChecking(install_if_ready);
+}
+
+void LLUpdaterService::stopChecking()
+{
+ mImpl->stopChecking();
+}
+
+bool LLUpdaterService::isChecking()
+{
+ return mImpl->isChecking();
+}
+
+void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb)
+{
+ return mImpl->setAppExitCallback(aecb);
+}
+
+
+std::string const & ll_get_version(void) {
+ static std::string version("");
+
+ if (version.empty()) {
+ std::ostringstream stream;
+ stream << LL_VERSION_MAJOR << "."
+ << LL_VERSION_MINOR << "."
+ << LL_VERSION_PATCH << "."
+ << LL_VERSION_BUILD;
+ version = stream.str();
+ }
+
+ return version;
+}
+
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
new file mode 100644
index 0000000000..752a6f834b
--- /dev/null
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -0,0 +1,85 @@
+/**
+ * @file llupdaterservice.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATERSERVICE_H
+#define LL_UPDATERSERVICE_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+
+class LLUpdaterServiceImpl;
+
+class LLUpdaterService
+{
+public:
+ class UsageError: public std::runtime_error
+ {
+ public:
+ UsageError(const std::string& msg) : std::runtime_error(msg) {}
+ };
+
+ // Name of the event pump through which update events will be delivered.
+ static std::string const & pumpName(void);
+
+ // Type codes for events posted by this service. Stored the event's 'type' element.
+ enum eUpdateEvent {
+ INVALID,
+ DOWNLOAD_COMPLETE,
+ DOWNLOAD_ERROR,
+ INSTALL_ERROR
+ };
+
+ LLUpdaterService();
+ ~LLUpdaterService();
+
+ void initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version);
+
+ void setCheckPeriod(unsigned int seconds);
+
+ void startChecking(bool install_if_ready = false);
+ void stopChecking();
+ bool isChecking();
+
+ typedef boost::function<void (void)> app_exit_callback_t;
+ template <typename F>
+ void setAppExitCallback(F const &callable)
+ {
+ app_exit_callback_t aecb = callable;
+ setImplAppExitCallback(aecb);
+ }
+
+private:
+ boost::shared_ptr<LLUpdaterServiceImpl> mImpl;
+ void setImplAppExitCallback(app_exit_callback_t aecb);
+};
+
+// Returns the full version as a string.
+std::string const & ll_get_version(void);
+
+#endif // LL_UPDATERSERVICE_H
diff --git a/indra/viewer_components/updater/scripts/darwin/update_install b/indra/viewer_components/updater/scripts/darwin/update_install
new file mode 100755
index 0000000000..b174b3570a
--- /dev/null
+++ b/indra/viewer_components/updater/scripts/darwin/update_install
@@ -0,0 +1,9 @@
+#! /bin/bash
+
+#
+# The first argument contains the path to the installer app. The second a path
+# to a marker file which should be created if the installer fails.q
+#
+
+open ../Resources/mac-updater.app --args -dmg "$1" -name "Second Life Viewer 2" -marker "$2"
+exit 0
diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install
new file mode 100755
index 0000000000..fef5ef7d09
--- /dev/null
+++ b/indra/viewer_components/updater/scripts/linux/update_install
@@ -0,0 +1,10 @@
+#! /bin/bash
+INSTALL_DIR=$(cd "$(dirname $0)/.." ; pwd)
+export LD_LIBRARY_PATH=$INSTALL_DIR/lib
+bin/linux-updater.bin --file "$1" --dest "$INSTALL_DIR" --name "Second Life Viewer 2" --stringsdir "$INSTALL_DIR/skins/default/xui/en" --stringsfile "strings.xml"
+
+if [ $? -ne 0 ]
+ then touch $2
+fi
+
+rm -f $1
diff --git a/indra/viewer_components/updater/scripts/windows/update_install.bat b/indra/viewer_components/updater/scripts/windows/update_install.bat
new file mode 100644
index 0000000000..42e148a707
--- /dev/null
+++ b/indra/viewer_components/updater/scripts/windows/update_install.bat
@@ -0,0 +1,3 @@
+start /WAIT %1 /SKIP_DIALOGS
+IF ERRORLEVEL 1 ECHO %ERRORLEVEL% > %2
+DEL %1
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
new file mode 100644
index 0000000000..04ed4e6364
--- /dev/null
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -0,0 +1,199 @@
+/**
+ * @file llupdaterservice_test.cpp
+ * @brief Tests of llupdaterservice.cpp.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../llupdaterservice.h"
+#include "../llupdatechecker.h"
+#include "../llupdatedownloader.h"
+#include "../llupdateinstaller.h"
+
+#include "../../../test/lltut.h"
+//#define DEBUG_ON
+#include "../../../test/debug.h"
+
+#include "llevents.h"
+#include "lldir.h"
+
+/*****************************************************************************
+* MOCK'd
+*****************************************************************************/
+LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
+{}
+void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,
+ std::string const & servicePath, std::string channel, std::string version)
+{}
+LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
+void LLUpdateDownloader::download(LLURI const & , std::string const &){}
+
+class LLDir_Mock : public LLDir
+{
+ void initAppDirs(const std::string &app_name,
+ const std::string& app_read_only_data_dir = "") {}
+ U32 countFilesInDir(const std::string &dirname, const std::string &mask)
+ {
+ return 0;
+ }
+
+ BOOL getNextFileInDir(const std::string &dirname,
+ const std::string &mask,
+ std::string &fname)
+ {
+ return false;
+ }
+ void getRandomFileInDir(const std::string &dirname,
+ const std::string &mask,
+ std::string &fname) {}
+ std::string getCurPath() { return ""; }
+ BOOL fileExists(const std::string &filename) const { return false; }
+ std::string getLLPluginLauncher() { return ""; }
+ std::string getLLPluginFilename(std::string base_name) { return ""; }
+
+} gDirUtil;
+LLDir* gDirUtilp = &gDirUtil;
+LLDir::LLDir() {}
+LLDir::~LLDir() {}
+S32 LLDir::deleteFilesInDir(const std::string &dirname,
+ const std::string &mask)
+{ return 0; }
+
+void LLDir::setChatLogsDir(const std::string &path){}
+void LLDir::setPerAccountChatLogsDir(const std::string &username){}
+void LLDir::setLindenUserDir(const std::string &username){}
+void LLDir::setSkinFolder(const std::string &skin_folder){}
+bool LLDir::setCacheDir(const std::string &path){ return true; }
+void LLDir::dumpCurrentDirectories() {}
+
+std::string LLDir::getExpandedFilename(ELLPath location,
+ const std::string &filename) const
+{
+ return "";
+}
+
+std::string LLUpdateDownloader::downloadMarkerPath(void)
+{
+ return "";
+}
+
+void LLUpdateDownloader::resume(void) {}
+void LLUpdateDownloader::cancel(void) {}
+
+int ll_install_update(std::string const &, std::string const &, LLInstallScriptMode)
+{
+ return 0;
+}
+
+std::string const & ll_install_failed_marker_path()
+{
+ static std::string wubba;
+ return wubba;
+}
+
+/*
+#pragma warning(disable: 4273)
+llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename,
+ ios_base::openmode _Mode,
+ int _Prot) :
+ std::basic_istream<char,std::char_traits< char > >(NULL,true)
+{}
+
+llus_mock_llifstream::~llus_mock_llifstream() {}
+bool llus_mock_llifstream::is_open() const {return true;}
+void llus_mock_llifstream::close() {}
+*/
+
+/*****************************************************************************
+* TUT
+*****************************************************************************/
+namespace tut
+{
+ struct llupdaterservice_data
+ {
+ llupdaterservice_data() :
+ pumps(LLEventPumps::instance()),
+ test_url("dummy_url"),
+ test_channel("dummy_channel"),
+ test_version("dummy_version")
+ {}
+ LLEventPumps& pumps;
+ std::string test_url;
+ std::string test_channel;
+ std::string test_version;
+ };
+
+ typedef test_group<llupdaterservice_data> llupdaterservice_group;
+ typedef llupdaterservice_group::object llupdaterservice_object;
+ llupdaterservice_group llupdaterservicegrp("LLUpdaterService");
+
+ template<> template<>
+ void llupdaterservice_object::test<1>()
+ {
+ DEBUG;
+ LLUpdaterService updater;
+ bool got_usage_error = false;
+ try
+ {
+ updater.startChecking();
+ }
+ catch(LLUpdaterService::UsageError)
+ {
+ got_usage_error = true;
+ }
+ ensure("Caught start before params", got_usage_error);
+ }
+
+ template<> template<>
+ void llupdaterservice_object::test<2>()
+ {
+ DEBUG;
+ LLUpdaterService updater;
+ bool got_usage_error = false;
+ try
+ {
+ updater.initialize("1.0",test_url, "update" ,test_channel, test_version);
+ updater.startChecking();
+ updater.initialize("1.0", "other_url", "update", test_channel, test_version);
+ }
+ catch(LLUpdaterService::UsageError)
+ {
+ got_usage_error = true;
+ }
+ ensure("Caught params while running", got_usage_error);
+ }
+
+ template<> template<>
+ void llupdaterservice_object::test<3>()
+ {
+ DEBUG;
+ LLUpdaterService updater;
+ updater.initialize("1.0", test_url, "update", test_channel, test_version);
+ updater.startChecking();
+ ensure(updater.isChecking());
+ updater.stopChecking();
+ ensure(!updater.isChecking());
+ }
+}
diff --git a/install.xml b/install.xml
index 391d83b224..98e983299e 100644
--- a/install.xml
+++ b/install.xml
@@ -1408,7 +1408,7 @@ anguage Infrstructure (CLI) international standard</string>
</map>
</map>
</map>
- <key>vivox</key>
+ <key>slvoice</key>
<map>
<key>copyright</key>
<string> </string>
@@ -1419,23 +1419,23 @@ anguage Infrstructure (CLI) international standard</string>
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>aa144917d0e33453d3c2cc2c05c6c47c</string>
+ <string>2f9b3528d4b5f858fb8dcee4b6dd5188</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.8821-darwin-20100529.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-darwin-20101117a.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>98f7945755f3ee8e52f685a3eff4d7be</string>
+ <string>cde4728b8a75a76c72a8785815cb769f</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.8821-linux-20100529.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-linux-20101117a.tar.bz2</uri>
</map>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>e8fdd46cb026c2ec72c4489eb3bf39c1</string>
+ <string>940ac55a6d0141c958bf2b14939d8474</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.8821-windows-20100529.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-windows-20101117a.tar.bz2</uri>
</map>
</map>
</map>
diff --git a/scripts/md5check.py b/scripts/md5check.py
new file mode 100755
index 0000000000..951fe0105c
--- /dev/null
+++ b/scripts/md5check.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+"""\
+@file md5check.py
+@brief Replacement for message template compatibility verifier.
+
+$LicenseInfo:firstyear=20i10&license=viewergpl$
+Copyright (c) 2010, 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$
+"""
+
+import sys
+import hashlib
+
+if len(sys.argv) != 3:
+ print """Usage: %s --create|<hash-digest> <file>
+
+Creates an md5sum hash digest of the specified file content
+and compares it with the given hash digest.
+
+If --create is used instead of a hash digest, it will simply
+print out the hash digest of specified file content.
+""" % sys.argv[0]
+ sys.exit(1)
+
+if sys.argv[2] == '-':
+ fh = sys.stdin
+ filename = "<stdin>"
+else:
+ filename = sys.argv[2]
+ fh = open(filename)
+
+hexdigest = hashlib.md5(fh.read()).hexdigest()
+if sys.argv[1] == '--create':
+ print hexdigest
+elif hexdigest == sys.argv[1]:
+ print "md5sum check passed:", filename
+else:
+ print "md5sum check FAILED:", filename
+ sys.exit(1)