summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt171
-rw-r--r--indra/newview/app_settings/CA.pem19
-rw-r--r--indra/newview/app_settings/cmd_line.xml30
-rw-r--r--indra/newview/app_settings/high_graphics.xml2
-rw-r--r--indra/newview/app_settings/ignorable_dialogs.xml34
-rw-r--r--indra/newview/app_settings/keys.ini357
-rw-r--r--indra/newview/app_settings/keys.xml350
-rw-r--r--indra/newview/app_settings/lindenlab.pem97
-rw-r--r--indra/newview/app_settings/llsd.xsd131
-rw-r--r--indra/newview/app_settings/low_graphics.xml2
-rw-r--r--indra/newview/app_settings/mid_graphics.xml2
-rw-r--r--indra/newview/app_settings/settings.xml1076
-rw-r--r--indra/newview/app_settings/settings_files.xml212
-rw-r--r--indra/newview/app_settings/settings_minimal.xml406
-rw-r--r--indra/newview/app_settings/settings_per_account.xml23
-rw-r--r--indra/newview/app_settings/shaders/shader_hierarchy.txt (renamed from indra/newview/app_settings/shaders/shader_heirarchy.txt)0
-rw-r--r--indra/newview/app_settings/ultra_graphics.xml2
-rw-r--r--indra/newview/character/avatar_lad.xml648
-rw-r--r--indra/newview/featuretable.txt11
-rw-r--r--indra/newview/featuretable_linux.txt7
-rw-r--r--indra/newview/featuretable_mac.txt7
-rw-r--r--indra/newview/featuretable_xp.txt7
-rw-r--r--indra/newview/generate_breakpad_symbols.py63
-rw-r--r--indra/newview/installers/windows/installer_template.nsi55
-rw-r--r--indra/newview/llagent.cpp49
-rw-r--r--indra/newview/llagent.h9
-rw-r--r--indra/newview/llagentcamera.cpp16
-rw-r--r--indra/newview/llagentwearables.cpp5
-rw-r--r--indra/newview/llagentwearables.h2
-rw-r--r--indra/newview/llappearancemgr.cpp64
-rw-r--r--indra/newview/llappviewer.cpp926
-rw-r--r--indra/newview/llappviewer.h26
-rw-r--r--indra/newview/llappviewerlinux.cpp3
-rw-r--r--indra/newview/llassetuploadresponders.cpp1
-rw-r--r--indra/newview/llavataractions.cpp36
-rw-r--r--indra/newview/llavataractions.h2
-rw-r--r--indra/newview/llavatarlist.cpp35
-rw-r--r--indra/newview/llavatarlist.h2
-rw-r--r--indra/newview/llavatarlistitem.cpp11
-rw-r--r--indra/newview/llavatarlistitem.h4
-rw-r--r--indra/newview/llbottomtray.cpp224
-rw-r--r--indra/newview/llbottomtray.h28
-rw-r--r--indra/newview/llbreastmotion.cpp402
-rw-r--r--indra/newview/llbreastmotion.h160
-rw-r--r--indra/newview/llbrowsernotification.cpp14
-rw-r--r--indra/newview/llbuycurrencyhtml.cpp4
-rw-r--r--indra/newview/llcallfloater.cpp21
-rw-r--r--indra/newview/llcallfloater.h1
-rw-r--r--indra/newview/llcapabilityprovider.h2
-rw-r--r--indra/newview/llchathistory.cpp94
-rw-r--r--indra/newview/llchathistory.h2
-rw-r--r--indra/newview/llchatitemscontainerctrl.cpp54
-rw-r--r--indra/newview/llchiclet.cpp8
-rw-r--r--indra/newview/llcolorswatch.cpp52
-rw-r--r--indra/newview/llcolorswatch.h4
-rw-r--r--indra/newview/llcommandhandler.cpp2
-rw-r--r--indra/newview/llcommandlineparser.cpp11
-rw-r--r--indra/newview/llcurrencyuimanager.cpp4
-rw-r--r--indra/newview/lldirpicker.cpp40
-rw-r--r--indra/newview/lldirpicker.h1
-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/lldriverparam.h2
-rw-r--r--indra/newview/lldynamictexture.cpp10
-rw-r--r--indra/newview/llexternaleditor.cpp208
-rw-r--r--indra/newview/llexternaleditor.h105
-rw-r--r--indra/newview/llface.cpp89
-rw-r--r--indra/newview/llface.h1
-rw-r--r--indra/newview/llfasttimerview.cpp75
-rw-r--r--indra/newview/llfasttimerview.h3
-rw-r--r--indra/newview/llfavoritesbar.cpp51
-rw-r--r--indra/newview/llfavoritesbar.h5
-rw-r--r--indra/newview/llfeaturemanager.cpp11
-rw-r--r--indra/newview/llfilepicker.cpp100
-rw-r--r--indra/newview/llfilepicker.h4
-rw-r--r--indra/newview/llfirstuse.cpp16
-rw-r--r--indra/newview/llfirstuse.h4
-rw-r--r--indra/newview/llfloaterabout.cpp6
-rw-r--r--indra/newview/llfloaterauction.cpp4
-rw-r--r--indra/newview/llfloaterbeacons.cpp2
-rw-r--r--indra/newview/llfloaterbuycurrency.cpp6
-rw-r--r--indra/newview/llfloaterbuycurrencyhtml.cpp4
-rw-r--r--indra/newview/llfloatercamera.cpp22
-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/llfloaterhelpbrowser.cpp7
-rw-r--r--indra/newview/llfloaterland.cpp5
-rw-r--r--indra/newview/llfloatermap.cpp86
-rw-r--r--indra/newview/llfloatermap.h5
-rw-r--r--indra/newview/llfloatermediabrowser.cpp28
-rw-r--r--indra/newview/llfloaternotificationsconsole.cpp1
-rw-r--r--indra/newview/llfloaterpostcard.cpp19
-rw-r--r--indra/newview/llfloaterpreference.cpp243
-rw-r--r--indra/newview/llfloaterpreference.h34
-rw-r--r--indra/newview/llfloaterregiondebugconsole.cpp221
-rw-r--r--indra/newview/llfloaterregiondebugconsole.h57
-rw-r--r--indra/newview/llfloatersearch.cpp2
-rw-r--r--indra/newview/llfloatersettingsdebug.cpp2
-rw-r--r--indra/newview/llfloatersidetraytab.cpp6
-rw-r--r--indra/newview/llfloatersidetraytab.h2
-rw-r--r--indra/newview/llfloatersnapshot.cpp43
-rw-r--r--indra/newview/llfloatertools.cpp16
-rw-r--r--indra/newview/llfloatertools.h2
-rw-r--r--indra/newview/llfloatertopobjects.cpp29
-rw-r--r--indra/newview/llfloatertopobjects.h5
-rw-r--r--indra/newview/llfloateruipreview.cpp227
-rw-r--r--indra/newview/llfloaterwebcontent.cpp402
-rw-r--r--indra/newview/llfloaterwebcontent.h82
-rw-r--r--indra/newview/llfloaterworldmap.cpp382
-rw-r--r--indra/newview/llfloaterworldmap.h5
-rw-r--r--indra/newview/llfolderview.cpp65
-rw-r--r--indra/newview/llfolderview.h3
-rw-r--r--indra/newview/llfriendcard.cpp115
-rw-r--r--indra/newview/llfriendcard.h13
-rw-r--r--indra/newview/llgiveinventory.cpp4
-rw-r--r--indra/newview/llglsandbox.cpp94
-rw-r--r--indra/newview/llgroupactions.cpp6
-rw-r--r--indra/newview/llgroupmgr.cpp1
-rw-r--r--indra/newview/llhints.cpp15
-rw-r--r--indra/newview/llhudeffectblob.cpp90
-rw-r--r--indra/newview/llhudeffectblob.h52
-rw-r--r--indra/newview/llhudicon.cpp5
-rw-r--r--indra/newview/llhudicon.h1
-rw-r--r--indra/newview/llhudobject.cpp25
-rw-r--r--indra/newview/llhudobject.h4
-rw-r--r--indra/newview/llhudtext.cpp28
-rw-r--r--indra/newview/llhudtext.h3
-rw-r--r--indra/newview/llimfloater.cpp13
-rw-r--r--indra/newview/llimfloater.h2
-rw-r--r--indra/newview/llimview.cpp144
-rw-r--r--indra/newview/llimview.h6
-rw-r--r--indra/newview/llinspectavatar.cpp93
-rw-r--r--indra/newview/llinspectobject.cpp3
-rw-r--r--indra/newview/llinspecttoast.cpp11
-rw-r--r--indra/newview/llinventorybridge.cpp154
-rw-r--r--indra/newview/llinventoryfilter.cpp18
-rw-r--r--indra/newview/llinventoryfunctions.cpp14
-rw-r--r--indra/newview/llinventoryicon.cpp6
-rw-r--r--indra/newview/llinventoryicon.h4
-rw-r--r--indra/newview/llinventorylistitem.cpp3
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp6
-rw-r--r--indra/newview/llinventoryobserver.cpp4
-rw-r--r--indra/newview/llinventorypanel.cpp92
-rw-r--r--indra/newview/llinventorypanel.h3
-rw-r--r--indra/newview/lllistcontextmenu.cpp28
-rw-r--r--indra/newview/lllistcontextmenu.h3
-rw-r--r--indra/newview/lllocationinputctrl.cpp5
-rw-r--r--indra/newview/lllogchat.cpp87
-rw-r--r--indra/newview/lllogchat.h4
-rw-r--r--indra/newview/lllogininstance.cpp520
-rw-r--r--indra/newview/lllogininstance.h13
-rw-r--r--indra/newview/llmainlooprepeater.cpp88
-rw-r--r--indra/newview/llmainlooprepeater.h65
-rw-r--r--indra/newview/llmaniprotate.cpp36
-rw-r--r--indra/newview/llmaniptranslate.cpp2
-rw-r--r--indra/newview/llmediactrl.cpp326
-rw-r--r--indra/newview/llmediactrl.h10
-rw-r--r--indra/newview/llmemoryview.cpp53
-rw-r--r--indra/newview/llmemoryview.h1
-rw-r--r--indra/newview/llmetricperformancetester.cpp252
-rw-r--r--indra/newview/llmetricperformancetester.h153
-rw-r--r--indra/newview/llmoveview.cpp36
-rw-r--r--indra/newview/llmutelist.cpp25
-rw-r--r--indra/newview/llnamelistctrl.cpp24
-rw-r--r--indra/newview/llnavigationbar.cpp22
-rw-r--r--indra/newview/llnearbychat.cpp13
-rw-r--r--indra/newview/llnearbychat.h1
-rw-r--r--indra/newview/llnearbychatbar.cpp41
-rw-r--r--indra/newview/llnearbychatbar.h6
-rw-r--r--indra/newview/llnearbychathandler.cpp89
-rw-r--r--indra/newview/llnetmap.cpp147
-rw-r--r--indra/newview/llnetmap.h20
-rw-r--r--indra/newview/llnotificationscripthandler.cpp2
-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/llpanelavatar.cpp99
-rw-r--r--indra/newview/llpanelavatar.h8
-rw-r--r--indra/newview/llpaneleditwearable.cpp50
-rw-r--r--indra/newview/llpaneleditwearable.h11
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp3
-rw-r--r--indra/newview/llpanelgrouproles.cpp132
-rw-r--r--indra/newview/llpanelgrouproles.h8
-rw-r--r--indra/newview/llpanellandaudio.cpp15
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp6
-rw-r--r--indra/newview/llpanellandmarks.cpp108
-rw-r--r--indra/newview/llpanellandmarks.h15
-rw-r--r--indra/newview/llpanellandmedia.cpp27
-rw-r--r--indra/newview/llpanellogin.cpp243
-rw-r--r--indra/newview/llpanellogin.h4
-rw-r--r--indra/newview/llpanelmaininventory.cpp121
-rw-r--r--indra/newview/llpanelmaininventory.h7
-rw-r--r--indra/newview/llpanelme.cpp24
-rw-r--r--indra/newview/llpanelnearbymedia.cpp27
-rw-r--r--indra/newview/llpanelobject.cpp4
-rw-r--r--indra/newview/llpanelobjectinventory.cpp20
-rw-r--r--indra/newview/llpaneloutfitedit.cpp74
-rw-r--r--indra/newview/llpaneloutfitedit.h12
-rw-r--r--indra/newview/llpaneloutfitsinventory.cpp20
-rw-r--r--indra/newview/llpaneloutfitsinventory.h1
-rw-r--r--indra/newview/llpanelpeople.cpp151
-rw-r--r--indra/newview/llpanelpeople.h12
-rw-r--r--indra/newview/llpanelpick.cpp3
-rw-r--r--indra/newview/llpanelpicks.cpp236
-rw-r--r--indra/newview/llpanelpicks.h5
-rw-r--r--indra/newview/llpanelplaceinfo.cpp4
-rw-r--r--indra/newview/llpanelplaces.cpp40
-rw-r--r--indra/newview/llpanelplaces.h4
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp121
-rw-r--r--indra/newview/llpanelprimmediacontrols.h16
-rw-r--r--indra/newview/llpanelprofile.cpp217
-rw-r--r--indra/newview/llpanelprofile.h32
-rw-r--r--indra/newview/llpanelteleporthistory.cpp39
-rw-r--r--indra/newview/llpanelteleporthistory.h3
-rw-r--r--indra/newview/llpaneltopinfobar.cpp9
-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/llphysicsmotion.cpp698
-rw-r--r--indra/newview/llphysicsmotion.h124
-rw-r--r--indra/newview/llplacesinventorypanel.cpp18
-rw-r--r--indra/newview/llplacesinventorypanel.h6
-rw-r--r--indra/newview/llpolymesh.cpp54
-rw-r--r--indra/newview/llpolymorph.cpp47
-rw-r--r--indra/newview/llpolymorph.h1
-rw-r--r--indra/newview/llpopupview.cpp73
-rw-r--r--indra/newview/llpopupview.h2
-rw-r--r--indra/newview/llpreview.cpp3
-rw-r--r--indra/newview/llpreviewgesture.cpp2
-rw-r--r--indra/newview/llpreviewscript.cpp313
-rw-r--r--indra/newview/llpreviewscript.h44
-rw-r--r--indra/newview/llpreviewtexture.cpp79
-rw-r--r--indra/newview/llprogressview.cpp6
-rw-r--r--indra/newview/llrecentpeople.cpp58
-rw-r--r--indra/newview/llrecentpeople.h33
-rw-r--r--indra/newview/llremoteparcelrequest.cpp72
-rw-r--r--indra/newview/llremoteparcelrequest.h2
-rw-r--r--indra/newview/llrootview.h22
-rw-r--r--indra/newview/llscreenchannel.cpp72
-rw-r--r--indra/newview/llscreenchannel.h11
-rw-r--r--indra/newview/llscriptfloater.cpp46
-rw-r--r--indra/newview/llscriptfloater.h7
-rw-r--r--indra/newview/llscrollingpanelparam.cpp62
-rw-r--r--indra/newview/llscrollingpanelparam.h11
-rw-r--r--indra/newview/llscrollingpanelparambase.cpp112
-rw-r--r--indra/newview/llscrollingpanelparambase.h62
-rw-r--r--indra/newview/llsearchcombobox.cpp3
-rw-r--r--indra/newview/llselectmgr.cpp98
-rw-r--r--indra/newview/llselectmgr.h13
-rw-r--r--indra/newview/llshareavatarhandler.cpp67
-rw-r--r--indra/newview/llsidepanelappearance.cpp54
-rw-r--r--indra/newview/llsidepanelappearance.h6
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp28
-rw-r--r--indra/newview/llsidepaneliteminfo.h3
-rw-r--r--indra/newview/llsidepaneltaskinfo.cpp12
-rw-r--r--indra/newview/llsidetray.cpp202
-rw-r--r--indra/newview/llsidetray.h50
-rw-r--r--indra/newview/llsimplestat.h152
-rw-r--r--indra/newview/llspatialpartition.cpp73
-rw-r--r--indra/newview/llspatialpartition.h7
-rw-r--r--indra/newview/llspeakbutton.cpp9
-rw-r--r--indra/newview/llspeakingindicatormanager.cpp5
-rw-r--r--indra/newview/llstartup.cpp62
-rw-r--r--indra/newview/llstartup.h1
-rw-r--r--indra/newview/llstatusbar.cpp18
-rw-r--r--indra/newview/llstatusbar.h2
-rw-r--r--indra/newview/llsurface.cpp5
-rw-r--r--indra/newview/lltexturecache.cpp46
-rw-r--r--indra/newview/lltexturectrl.cpp20
-rw-r--r--indra/newview/lltexturefetch.cpp694
-rw-r--r--indra/newview/lltexturefetch.h92
-rw-r--r--indra/newview/lltextureview.cpp8
-rw-r--r--indra/newview/lltoast.cpp165
-rw-r--r--indra/newview/lltoast.h50
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp3
-rw-r--r--indra/newview/lltoastnotifypanel.cpp27
-rw-r--r--indra/newview/lltoastscripttextbox.cpp121
-rw-r--r--indra/newview/lltoastscripttextbox.h59
-rw-r--r--indra/newview/lltool.cpp8
-rw-r--r--indra/newview/lltoolmorph.cpp4
-rw-r--r--indra/newview/lltoolmorph.h2
-rw-r--r--indra/newview/lltoolpie.cpp387
-rw-r--r--indra/newview/lltoolpie.h30
-rw-r--r--indra/newview/lltracker.cpp4
-rw-r--r--indra/newview/lltracker.h2
-rw-r--r--indra/newview/lltransientfloatermgr.cpp7
-rw-r--r--indra/newview/lltranslate.cpp62
-rw-r--r--indra/newview/lltranslate.h48
-rw-r--r--indra/newview/llurldispatcher.cpp2
-rw-r--r--indra/newview/llversioninfo.cpp37
-rw-r--r--indra/newview/llversioninfo.h7
-rw-r--r--indra/newview/llviewerassetstats.cpp613
-rw-r--r--indra/newview/llviewerassetstats.h328
-rw-r--r--indra/newview/llviewerassetstorage.cpp129
-rw-r--r--indra/newview/llviewerassetstorage.h11
-rw-r--r--indra/newview/llviewerchat.cpp42
-rw-r--r--indra/newview/llviewerchat.h4
-rw-r--r--indra/newview/llviewercontrol.cpp47
-rw-r--r--indra/newview/llviewercontrol.h2
-rw-r--r--indra/newview/llviewerdisplay.cpp68
-rw-r--r--indra/newview/llviewerdisplay.h1
-rw-r--r--indra/newview/llviewerfloaterreg.cpp4
-rw-r--r--indra/newview/llviewerinventory.cpp117
-rw-r--r--indra/newview/llviewerinventory.h1
-rw-r--r--indra/newview/llviewerjoint.cpp2
-rw-r--r--indra/newview/llviewerjointmesh.cpp27
-rw-r--r--indra/newview/llviewerkeyboard.cpp183
-rw-r--r--indra/newview/llviewerkeyboard.h37
-rw-r--r--indra/newview/llviewermedia.cpp191
-rw-r--r--indra/newview/llviewermedia.h16
-rw-r--r--indra/newview/llviewermenu.cpp437
-rw-r--r--indra/newview/llviewermenu.h2
-rw-r--r--indra/newview/llviewermenufile.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp138
-rw-r--r--indra/newview/llviewermessage.h1
-rw-r--r--indra/newview/llviewernetwork.cpp4
-rw-r--r--indra/newview/llviewerobject.cpp285
-rw-r--r--indra/newview/llviewerobject.h59
-rw-r--r--indra/newview/llviewerobjectlist.cpp231
-rw-r--r--indra/newview/llviewerobjectlist.h8
-rw-r--r--indra/newview/llviewerparcelmedia.cpp12
-rw-r--r--indra/newview/llviewerparcelmgr.cpp5
-rw-r--r--indra/newview/llviewerparceloverlay.cpp29
-rw-r--r--indra/newview/llviewerparceloverlay.h7
-rw-r--r--indra/newview/llviewerregion.cpp92
-rw-r--r--indra/newview/llviewerregion.h27
-rw-r--r--indra/newview/llviewershadermgr.cpp4
-rw-r--r--indra/newview/llviewerstats.cpp7
-rw-r--r--indra/newview/llviewerstats.h2
-rw-r--r--indra/newview/llviewerstatsrecorder.cpp258
-rw-r--r--indra/newview/llviewerstatsrecorder.h97
-rw-r--r--indra/newview/llviewertexture.cpp178
-rw-r--r--indra/newview/llviewertexture.h11
-rw-r--r--indra/newview/llviewertexturelist.cpp100
-rw-r--r--indra/newview/llviewerthrottle.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp312
-rw-r--r--indra/newview/llviewerwindow.h10
-rw-r--r--indra/newview/llviewerwindowlistener.cpp3
-rw-r--r--indra/newview/llvoavatar.cpp71
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvoavatarself.cpp34
-rw-r--r--indra/newview/llvoavatarself.h2
-rw-r--r--indra/newview/llvocache.cpp413
-rw-r--r--indra/newview/llvocache.h18
-rw-r--r--indra/newview/llvoicecallhandler.cpp69
-rw-r--r--indra/newview/llvoicechannel.cpp24
-rw-r--r--indra/newview/llvoicechannel.h7
-rw-r--r--indra/newview/llvoiceclient.cpp138
-rw-r--r--indra/newview/llvoiceclient.h34
-rw-r--r--indra/newview/llvoicevivox.cpp177
-rw-r--r--indra/newview/llvoicevivox.h32
-rw-r--r--indra/newview/llvosky.cpp35
-rw-r--r--indra/newview/llvosky.h44
-rw-r--r--indra/newview/llvosurfacepatch.cpp2
-rw-r--r--indra/newview/llvovolume.cpp44
-rw-r--r--indra/newview/llvovolume.h1
-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/llwearableitemslist.cpp9
-rw-r--r--indra/newview/llwearabletype.cpp81
-rw-r--r--indra/newview/llwearabletype.h5
-rw-r--r--indra/newview/llweb.cpp32
-rw-r--r--indra/newview/llweb.h5
-rw-r--r--indra/newview/llwlparammanager.cpp4
-rw-r--r--indra/newview/llworld.cpp403
-rw-r--r--indra/newview/llworld.h3
-rw-r--r--indra/newview/llworldmapview.cpp6
-rw-r--r--indra/newview/llworldmipmap.cpp3
-rw-r--r--indra/newview/pipeline.cpp368
-rw-r--r--indra/newview/pipeline.h10
-rw-r--r--indra/newview/res/toolbuy.curbin4286 -> 4286 bytes
-rw-r--r--indra/newview/res/toolopen.curbin4286 -> 4286 bytes
-rw-r--r--indra/newview/res/toolsit.curbin4286 -> 4286 bytes
-rw-r--r--indra/newview/skins/default/colors.xml15
-rw-r--r--indra/newview/skins/default/textures/arrow_keys.pngbin0 -> 6558 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/ChatBarHandle.pngbin0 -> 2808 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Physics.pngbin0 -> 616 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Web_Profile_Off.pngbin0 -> 2961 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml16
-rw-r--r--indra/newview/skins/default/textures/widgets/ProgressBar.pngbin220 -> 316 bytes
-rw-r--r--indra/newview/skins/default/textures/world/CameraDragDot.pngbin0 -> 3101 bytes
-rw-r--r--indra/newview/skins/default/xui/en/menu_avatar_self.xml12
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_physics.xml124
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_wearable.xml18
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml42
-rw-r--r--indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml24
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml50
-rw-r--r--indra/newview/skins/minimal/colors.xml6
-rw-r--r--indra/newview/skins/minimal/textures/arrow_keys.pngbin0 -> 6558 bytes
-rw-r--r--indra/newview/skins/minimal/textures/bottomtray/button_separator.pngbin0 -> 153 bytes
-rw-r--r--indra/newview/skins/minimal/textures/bottomtray/close_off.pngbin0 -> 3184 bytes
-rw-r--r--indra/newview/skins/minimal/textures/bottomtray/close_over.pngbin0 -> 3173 bytes
-rw-r--r--indra/newview/skins/minimal/textures/bottomtray/close_press.pngbin0 -> 3259 bytes
-rw-r--r--indra/newview/skins/minimal/textures/textures.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/floater_camera.xml65
-rw-r--r--indra/newview/skins/minimal/xui/de/floater_help_browser.xml9
-rw-r--r--indra/newview/skins/minimal/xui/de/floater_media_browser.xml30
-rw-r--r--indra/newview/skins/minimal/xui/de/floater_nearby_chat.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/floater_web_content.xml14
-rw-r--r--indra/newview/skins/minimal/xui/de/inspect_avatar.xml25
-rw-r--r--indra/newview/skins/minimal/xui/de/inspect_object.xml48
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_add_wearable_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_attachment_other.xml17
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_attachment_self.xml16
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_avatar_other.xml16
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_avatar_self.xml31
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_bottomtray.xml17
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_cof_attachment.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_cof_body_part.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_cof_clothing.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_cof_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_edit.xml12
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_favorites.xml10
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_hide_navbar.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_im_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_imchiclet_adhoc.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inspect_object_gear.xml18
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inv_offer_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inventory.xml86
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inventory_add.xml33
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_inventory_gear_default.xml16
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_land.xml9
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_landmark.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_login.xml25
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_mini_map.xml11
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_navbar.xml11
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_notification_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_object.xml29
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_outfit_gear.xml27
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_outfit_tab.xml9
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_participant_list.xml21
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_friends_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_groups.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_nearby.xml13
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_nearby_multiselect.xml10
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_picks.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_place.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_profile_overflow.xml12
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_save_outfit.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_script_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_slurl.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_topinfobar.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_http.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_map.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_viewer.xml14
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_wearable_list_item.xml14
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_wearing_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/de/menu_wearing_tab.xml6
-rw-r--r--indra/newview/skins/minimal/xui/de/notifications.xml19
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_bottomtray.xml39
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_group_control_panel.xml11
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml30
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_login.xml40
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_navigation_bar.xml18
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_people.xml70
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_side_tray_tab_caption.xml7
-rw-r--r--indra/newview/skins/minimal/xui/de/panel_status_bar.xml33
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_camera.xml284
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_help_browser.xml52
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_media_browser.xml242
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_nearby_chat.xml52
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_side_bar_tab.xml10
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_web_content.xml189
-rw-r--r--indra/newview/skins/minimal/xui/en/inspect_avatar.xml206
-rw-r--r--indra/newview/skins/minimal/xui/en/inspect_object.xml144
-rw-r--r--indra/newview/skins/minimal/xui/en/main_view.xml268
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_add_wearable_gear.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_attachment_other.xml76
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_attachment_self.xml26
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_avatar_icon.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_avatar_other.xml75
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_avatar_self.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_bottomtray.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_cof_attachment.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_cof_body_part.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_cof_clothing.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_cof_gear.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_edit.xml90
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_favorites.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_gesture_gear.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_group_plus.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_hide_navbar.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_im_well_button.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_imchiclet_adhoc.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_imchiclet_group.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_imchiclet_p2p.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inspect_avatar_gear.xml116
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inspect_object_gear.xml50
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inspect_self_gear.xml49
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inv_offer_chiclet.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inventory.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inventory_add.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_inventory_gear_default.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_land.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_landmark.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_login.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_mini_map.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_navbar.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_nearby_chat.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_notification_well_button.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_object.xml40
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_object_icon.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_outfit_gear.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_outfit_tab.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_participant_list.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_friends_view_sort.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_groups.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_groups_view_sort.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_nearby.xml61
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_nearby_multiselect.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_nearby_view_sort.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_people_recent_view_sort.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_picks.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_picks_plus.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_place.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_place_add_button.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_places_gear_folder.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_places_gear_landmark.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_profile_overflow.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_save_outfit.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_script_chiclet.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_slurl.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_teleport_history_gear.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_teleport_history_item.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_teleport_history_tab.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_text_editor.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_topinfobar.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_agent.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_group.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_http.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_inventory.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_map.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_objectim.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_parcel.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_slapp.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_slurl.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_url_teleport.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_viewer.xml71
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_wearable_list_item.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_wearing_gear.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/menu_wearing_tab.xml2
-rw-r--r--indra/newview/skins/minimal/xui/en/notification_visibility.xml29
-rw-r--r--indra/newview/skins/minimal/xui/en/notifications.xml44
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_adhoc_control_panel.xml46
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_bottomtray.xml483
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_group_control_panel.xml79
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml27
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_login.xml206
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml76
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_people.xml550
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_side_tray_tab_caption.xml11
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_status_bar.xml62
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_volume_pulldown.xml34
-rw-r--r--indra/newview/skins/minimal/xui/en/widgets/location_input.xml131
-rw-r--r--indra/newview/skins/minimal/xui/es/floater_camera.xml65
-rw-r--r--indra/newview/skins/minimal/xui/es/floater_help_browser.xml9
-rw-r--r--indra/newview/skins/minimal/xui/es/floater_media_browser.xml30
-rw-r--r--indra/newview/skins/minimal/xui/es/floater_nearby_chat.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/floater_web_content.xml14
-rw-r--r--indra/newview/skins/minimal/xui/es/inspect_avatar.xml24
-rw-r--r--indra/newview/skins/minimal/xui/es/inspect_object.xml41
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_add_wearable_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_attachment_other.xml17
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_attachment_self.xml16
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_avatar_other.xml16
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_avatar_self.xml31
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_bottomtray.xml17
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_cof_attachment.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_cof_body_part.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_cof_clothing.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_cof_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_edit.xml12
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_favorites.xml10
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_hide_navbar.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_im_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_imchiclet_adhoc.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inspect_object_gear.xml18
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inv_offer_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inventory.xml86
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inventory_add.xml33
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_inventory_gear_default.xml16
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_land.xml9
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_landmark.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_login.xml24
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_mini_map.xml11
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_navbar.xml11
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_notification_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_object.xml29
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_outfit_gear.xml27
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_outfit_tab.xml9
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_participant_list.xml21
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_friends_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_groups.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_nearby.xml13
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_nearby_multiselect.xml10
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_picks.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_place.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_profile_overflow.xml12
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_save_outfit.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_script_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_slurl.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_topinfobar.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_http.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_map.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_viewer.xml14
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_wearable_list_item.xml14
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_wearing_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/es/menu_wearing_tab.xml6
-rw-r--r--indra/newview/skins/minimal/xui/es/notifications.xml19
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_bottomtray.xml39
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_group_control_panel.xml11
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_im_control_panel.xml29
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_login.xml40
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_navigation_bar.xml18
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_people.xml71
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_side_tray_tab_caption.xml7
-rw-r--r--indra/newview/skins/minimal/xui/es/panel_status_bar.xml33
-rw-r--r--indra/newview/skins/minimal/xui/fr/floater_camera.xml65
-rw-r--r--indra/newview/skins/minimal/xui/fr/floater_help_browser.xml9
-rw-r--r--indra/newview/skins/minimal/xui/fr/floater_media_browser.xml30
-rw-r--r--indra/newview/skins/minimal/xui/fr/floater_nearby_chat.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/floater_web_content.xml14
-rw-r--r--indra/newview/skins/minimal/xui/fr/inspect_avatar.xml25
-rw-r--r--indra/newview/skins/minimal/xui/fr/inspect_object.xml48
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_add_wearable_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_attachment_other.xml17
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_attachment_self.xml16
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_avatar_other.xml16
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_avatar_self.xml31
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_bottomtray.xml17
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_cof_attachment.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_cof_body_part.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_cof_clothing.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_cof_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_edit.xml12
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_favorites.xml10
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_hide_navbar.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_im_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_imchiclet_adhoc.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inspect_object_gear.xml18
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inv_offer_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inventory.xml86
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inventory_add.xml33
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_inventory_gear_default.xml16
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_land.xml9
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_landmark.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_login.xml25
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_mini_map.xml11
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_navbar.xml11
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_notification_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_object.xml29
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_outfit_gear.xml27
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_outfit_tab.xml9
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_participant_list.xml21
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_friends_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_groups.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_nearby.xml13
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_nearby_multiselect.xml10
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_picks.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_place.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_profile_overflow.xml12
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_save_outfit.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_script_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_slurl.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_topinfobar.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_http.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_map.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_viewer.xml14
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_wearable_list_item.xml14
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_wearing_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/fr/menu_wearing_tab.xml6
-rw-r--r--indra/newview/skins/minimal/xui/fr/notifications.xml19
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_bottomtray.xml39
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_group_control_panel.xml11
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_im_control_panel.xml30
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_login.xml40
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_navigation_bar.xml18
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_people.xml71
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_side_tray_tab_caption.xml7
-rw-r--r--indra/newview/skins/minimal/xui/fr/panel_status_bar.xml33
-rw-r--r--indra/newview/skins/minimal/xui/pt/floater_camera.xml65
-rw-r--r--indra/newview/skins/minimal/xui/pt/floater_help_browser.xml9
-rw-r--r--indra/newview/skins/minimal/xui/pt/floater_media_browser.xml30
-rw-r--r--indra/newview/skins/minimal/xui/pt/floater_nearby_chat.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/floater_web_content.xml14
-rw-r--r--indra/newview/skins/minimal/xui/pt/inspect_avatar.xml24
-rw-r--r--indra/newview/skins/minimal/xui/pt/inspect_object.xml41
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_add_wearable_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_attachment_other.xml17
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_attachment_self.xml16
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_avatar_icon.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_avatar_other.xml16
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_avatar_self.xml31
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_bottomtray.xml17
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_cof_attachment.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_cof_body_part.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_cof_clothing.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_cof_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_edit.xml12
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_favorites.xml10
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_group_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_hide_navbar.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_im_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_imchiclet_adhoc.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_imchiclet_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_imchiclet_p2p.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inspect_avatar_gear.xml17
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inspect_object_gear.xml18
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inspect_self_gear.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inv_offer_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inventory.xml86
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inventory_add.xml33
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_inventory_gear_default.xml16
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_land.xml9
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_landmark.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_login.xml24
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_mini_map.xml11
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_navbar.xml11
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_nearby_chat.xml9
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_notification_well_button.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_object.xml29
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_object_icon.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_outfit_gear.xml27
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_outfit_tab.xml9
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_participant_list.xml21
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_friends_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_groups.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_groups_view_sort.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_nearby.xml13
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_nearby_multiselect.xml10
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_nearby_view_sort.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_people_recent_view_sort.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_picks.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_picks_plus.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_place.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_place_add_button.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_places_gear_folder.xml15
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_places_gear_landmark.xml18
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_profile_overflow.xml12
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_save_outfit.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_script_chiclet.xml4
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_slurl.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_teleport_history_gear.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_teleport_history_tab.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_text_editor.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_topinfobar.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_agent.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_group.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_http.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_inventory.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_map.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_objectim.xml8
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_parcel.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_slapp.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_url_teleport.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_viewer.xml14
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_wearable_list_item.xml14
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_wearing_gear.xml5
-rw-r--r--indra/newview/skins/minimal/xui/pt/menu_wearing_tab.xml6
-rw-r--r--indra/newview/skins/minimal/xui/pt/notifications.xml19
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_adhoc_control_panel.xml14
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_bottomtray.xml39
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_group_control_panel.xml11
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_im_control_panel.xml29
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_login.xml40
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_navigation_bar.xml18
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_people.xml71
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_side_tray_tab_caption.xml7
-rw-r--r--indra/newview/skins/minimal/xui/pt/panel_status_bar.xml33
-rw-r--r--indra/newview/tests/llcapabilitylistener_test.cpp2
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp56
-rw-r--r--indra/newview/tests/llremoteparcelrequest_test.cpp136
-rw-r--r--indra/newview/tests/llsimplestat_test.cpp580
-rw-r--r--indra/newview/tests/llversioninfo_test.cpp114
-rw-r--r--indra/newview/tests/llviewerassetstats_test.cpp984
-rw-r--r--indra/newview/tests/llviewerhelputil_test.cpp17
-rw-r--r--indra/newview/tests/llworldmap_test.cpp42
-rw-r--r--indra/newview/tests/llworldmipmap_test.cpp27
-rw-r--r--indra/newview/tests/test_llxmlrpc_peer.py2
-rw-r--r--indra/newview/viewer_manifest.py260
893 files changed, 30707 insertions, 6853 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index bf885e5934..32d3a31786 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -9,7 +9,7 @@ include(DBusGlib)
include(DirectX)
include(OpenSSL)
include(DragDrop)
-include(ELFIO)
+include(EXPAT)
include(FMOD)
include(OPENAL)
include(FindOpenGL)
@@ -44,12 +44,13 @@ include(CMakeCopyIfDifferent)
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
- ${ELFIO_INCLUDE_DIR}
${JSONCPP_INCLUDE_DIRS}
${LLAUDIO_INCLUDE_DIRS}
${LLCHARACTER_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
+ ${FMOD_INCLUDE_DIR}
${LLIMAGE_INCLUDE_DIRS}
+ ${LLKDU_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
@@ -64,6 +65,8 @@ include_directories(
${LSCRIPT_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
${LLLOGIN_INCLUDE_DIRS}
+ ${UPDATER_INCLUDE_DIRS}
+ ${OPENAL_LIB_INCLUDE_DIRS}
)
set(viewer_SOURCE_FILES
@@ -143,6 +146,7 @@ set(viewer_SOURCE_FILES
lleventnotifier.cpp
lleventpoll.cpp
llexpandabletextbox.cpp
+ llexternaleditor.cpp
llface.cpp
llfasttimerview.cpp
llfavoritesbar.cpp
@@ -200,6 +204,7 @@ set(viewer_SOURCE_FILES
llfloaterpostprocess.cpp
llfloaterpreference.cpp
llfloaterproperties.cpp
+ llfloaterregiondebugconsole.cpp
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
@@ -219,6 +224,7 @@ set(viewer_SOURCE_FILES
llfloaterurlentry.cpp
llfloatervoiceeffect.cpp
llfloaterwater.cpp
+ llfloaterwebcontent.cpp
llfloaterwhitelistentry.cpp
llfloaterwindlight.cpp
llfloaterwindowsize.cpp
@@ -241,6 +247,7 @@ set(viewer_SOURCE_FILES
llhudeffectlookat.cpp
llhudeffectpointat.cpp
llhudeffecttrail.cpp
+ llhudeffectblob.cpp
llhudicon.cpp
llhudmanager.cpp
llhudnametag.cpp
@@ -282,6 +289,7 @@ set(viewer_SOURCE_FILES
llloginhandler.cpp
lllogininstance.cpp
llmachineid.cpp
+ llmainlooprepeater.cpp
llmanip.cpp
llmaniprotate.cpp
llmanipscale.cpp
@@ -290,7 +298,6 @@ set(viewer_SOURCE_FILES
llmediadataclient.cpp
llmemoryview.cpp
llmenucommands.cpp
- llmetricperformancetester.cpp
llmimetypes.cpp
llmorphview.cpp
llmoveview.cpp
@@ -373,6 +380,7 @@ set(viewer_SOURCE_FILES
llparcelselection.cpp
llparticipantlist.cpp
llpatchvertexarray.cpp
+ llphysicsmotion.cpp
llplacesinventorybridge.cpp
llplacesinventorypanel.cpp
llpopupview.cpp
@@ -395,11 +403,13 @@ set(viewer_SOURCE_FILES
llscreenchannel.cpp
llscriptfloater.cpp
llscrollingpanelparam.cpp
+ llscrollingpanelparambase.cpp
llsearchcombobox.cpp
llsearchhistory.cpp
llsecapi.cpp
llsechandler_basic.cpp
llselectmgr.cpp
+ llshareavatarhandler.cpp
llsidepanelappearance.cpp
llsidepanelinventory.cpp
llsidepanelinventorysubpanel.cpp
@@ -444,6 +454,7 @@ set(viewer_SOURCE_FILES
lltoastimpanel.cpp
lltoastnotifypanel.cpp
lltoastpanel.cpp
+ lltoastscripttextbox.cpp
lltool.cpp
lltoolbrush.cpp
lltoolcomp.cpp
@@ -477,6 +488,7 @@ set(viewer_SOURCE_FILES
llvectorperfoptions.cpp
llversioninfo.cpp
llviewchildren.cpp
+ llviewerassetstats.cpp
llviewerassetstorage.cpp
llviewerassettype.cpp
llviewerattachmenu.cpp
@@ -522,6 +534,7 @@ set(viewer_SOURCE_FILES
llviewerregion.cpp
llviewershadermgr.cpp
llviewerstats.cpp
+ llviewerstatsrecorder.cpp
llviewertexteditor.cpp
llviewertexture.cpp
llviewertextureanim.cpp
@@ -539,6 +552,7 @@ set(viewer_SOURCE_FILES
llvoclouds.cpp
llvograss.cpp
llvoground.cpp
+ llvoicecallhandler.cpp
llvoicechannel.cpp
llvoiceclient.cpp
llvoicevisualizer.cpp
@@ -675,6 +689,7 @@ set(viewer_HEADER_FILES
lleventnotifier.h
lleventpoll.h
llexpandabletextbox.h
+ llexternaleditor.h
llface.h
llfasttimerview.h
llfavoritesbar.h
@@ -732,6 +747,7 @@ set(viewer_HEADER_FILES
llfloaterpostprocess.h
llfloaterpreference.h
llfloaterproperties.h
+ llfloaterregiondebugconsole.h
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h
@@ -751,6 +767,7 @@ set(viewer_HEADER_FILES
llfloaterurlentry.h
llfloatervoiceeffect.h
llfloaterwater.h
+ llfloaterwebcontent.h
llfloaterwhitelistentry.h
llfloaterwindlight.h
llfloaterwindowsize.h
@@ -773,6 +790,7 @@ set(viewer_HEADER_FILES
llhudeffectlookat.h
llhudeffectpointat.h
llhudeffecttrail.h
+ llhudeffectblob.h
llhudicon.h
llhudmanager.h
llhudnametag.h
@@ -814,6 +832,7 @@ set(viewer_HEADER_FILES
llloginhandler.h
lllogininstance.h
llmachineid.h
+ llmainlooprepeater.h
llmanip.h
llmaniprotate.h
llmanipscale.h
@@ -822,7 +841,6 @@ set(viewer_HEADER_FILES
llmediadataclient.h
llmemoryview.h
llmenucommands.h
- llmetricperformancetester.h
llmimetypes.h
llmorphview.h
llmoveview.h
@@ -899,6 +917,7 @@ set(viewer_HEADER_FILES
llparcelselection.h
llparticipantlist.h
llpatchvertexarray.h
+ llphysicsmotion.h
llplacesinventorybridge.h
llplacesinventorypanel.h
llpolymesh.h
@@ -923,6 +942,7 @@ set(viewer_HEADER_FILES
llscreenchannel.h
llscriptfloater.h
llscrollingpanelparam.h
+ llscrollingpanelparambase.h
llsearchcombobox.h
llsearchhistory.h
llsecapi.h
@@ -973,6 +993,7 @@ set(viewer_HEADER_FILES
lltoastimpanel.h
lltoastnotifypanel.h
lltoastpanel.h
+ lltoastscripttextbox.h
lltool.h
lltoolbrush.h
lltoolcomp.h
@@ -1007,6 +1028,7 @@ set(viewer_HEADER_FILES
llvectorperfoptions.h
llversioninfo.h
llviewchildren.h
+ llviewerassetstats.h
llviewerassetstorage.h
llviewerassettype.h
llviewerattachmenu.h
@@ -1049,6 +1071,7 @@ set(viewer_HEADER_FILES
llviewerregion.h
llviewershadermgr.h
llviewerstats.h
+ llviewerstatsrecorder.h
llviewertexteditor.h
llviewertexture.h
llviewertextureanim.h
@@ -1273,8 +1296,6 @@ if (WINDOWS)
if (INTEL_MEMOPS_LIBRARY)
list(APPEND viewer_LIBRARIES ${INTEL_MEMOPS_LIBRARY})
endif (INTEL_MEMOPS_LIBRARY)
-
- use_prebuilt_binary(dbghelp)
endif (WINDOWS)
# Add the xui files. This is handy for searching for xui elements
@@ -1282,22 +1303,20 @@ endif (WINDOWS)
set(viewer_XUI_FILES
skins/default/colors.xml
skins/default/textures/textures.xml
+ skins/minimal/colors.xml
+ skins/minimal/textures/textures.xml
)
file(GLOB DEFAULT_XUI_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/*.xml)
+ ${CMAKE_CURRENT_SOURCE_DIR}/skins/*/xui/en/*.xml)
list(APPEND viewer_XUI_FILES ${DEFAULT_XUI_FILE_GLOB_LIST})
file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml)
+ ${CMAKE_CURRENT_SOURCE_DIR}/skins/*/xui/en/widgets/*.xml)
list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST})
-file(GLOB SILVER_XUI_FILE_GLOB_LIST
- ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/*.xml)
-list(APPEND viewer_XUI_FILES ${SILVER_XUI_FILE_GLOB_LIST})
-
# Cannot append empty lists in CMake, wait until we have files here.
#file(GLOB SILVER_WIDGET_FILE_GLOB_LIST
# ${CMAKE_CURRENT_SOURCE_DIR}/skins/silver/xui/en-us/widgets/*.xml)
@@ -1318,7 +1337,7 @@ set(viewer_APPSETTINGS_FILES
app_settings/grass.xml
app_settings/high_graphics.xml
app_settings/ignorable_dialogs.xml
- app_settings/keys.ini
+ app_settings/keys.xml
app_settings/keywords.ini
app_settings/logcontrol.xml
app_settings/low_graphics.xml
@@ -1327,6 +1346,7 @@ set(viewer_APPSETTINGS_FILES
app_settings/settings_crash_behavior.xml
app_settings/settings_files.xml
app_settings/settings_per_account.xml
+ app_settings/settings_minimal.xml
app_settings/std_bump.ini
app_settings/trees.xml
app_settings/ultra_graphics.xml
@@ -1417,19 +1437,13 @@ set(PACKAGE ON CACHE BOOL
"Add a package target that builds an installer package.")
if (WINDOWS)
- if(MSVC71)
- set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map /MAPINFO:LINES")
- else(MSVC71)
- set(release_flags "/MAP:Release/${VIEWER_BINARY_NAME}.map")
- endif(MSVC71)
-
set_target_properties(${VIEWER_BINARY_NAME}
PROPERTIES
# *TODO -reenable this once we get server usage sorted out
#LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\""
LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS"
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
- LINK_FLAGS_RELEASE ${release_flags}
+ LINK_FLAGS_RELEASE ""
)
if(USE_PRECOMPILED_HEADERS)
set_target_properties(
@@ -1446,11 +1460,6 @@ if (WINDOWS)
# In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py
# and have the build deps get tracked *please* tell me about it.
- if(LLKDU_LIBRARY)
- # Configure a var for llkdu which may not exist for all builds.
- set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll)
- endif(LLKDU_LIBRARY)
-
if(USE_GOOGLE_PERFTOOLS)
# Configure a var for tcmalloc location, if used.
# Note the need to specify multiple names explicitly.
@@ -1467,7 +1476,6 @@ if (WINDOWS)
#${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll
${CMAKE_SOURCE_DIR}/../etc/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
- ${LLKDU_DLL_SOURCE}
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll
@@ -1478,15 +1486,12 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
${SHARED_LIB_STAGING_DIR}/Debug/fmod.dll
- ${SHARED_LIB_STAGING_DIR}/Release/msvcr80.dll
- ${SHARED_LIB_STAGING_DIR}/Release/msvcp80.dll
- ${SHARED_LIB_STAGING_DIR}/Release/Microsoft.VC80.CRT.manifest
- ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcr80.dll
- ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcp80.dll
- ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/Microsoft.VC80.CRT.manifest
- ${SHARED_LIB_STAGING_DIR}/Debug/msvcr80d.dll
- ${SHARED_LIB_STAGING_DIR}/Debug/msvcp80d.dll
- ${SHARED_LIB_STAGING_DIR}/Debug/Microsoft.VC80.DebugCRT.manifest
+ ${SHARED_LIB_STAGING_DIR}/Release/msvcr100.dll
+ ${SHARED_LIB_STAGING_DIR}/Release/msvcp100.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcr100.dll
+ ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/msvcp100.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/msvcr100d.dll
+ ${SHARED_LIB_STAGING_DIR}/Debug/msvcp100d.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/SLVoice.exe
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/ortp.dll
@@ -1498,7 +1503,6 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/licenses-win32.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable_xp.txt
- ${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll
${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtcore4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtgui4.dll
@@ -1637,16 +1641,20 @@ if (WINDOWS)
# sorted out on the parabuild cluster...
#${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2)
- check_message_template(package)
-
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}
- ${LLIMAGEJ2COJ_LIBRARIES}
${LLINVENTORY_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLPLUGIN_LIBRARIES}
@@ -1674,14 +1682,25 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${SMARTHEAP_LIBRARY}
${UI_LIBRARIES}
${WINDOWS_LIBRARIES}
+ ${EXPAT_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
- ${ELFIO_LIBRARIES}
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARIES}
${LLLOGIN_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
+if (USE_KDU)
+ target_link_libraries(${VIEWER_BINARY_NAME}
+ ${LLKDU_LIBRARIES}
+ ${KDU_LIBRARY}
+ )
+else (USE_KDU)
+ target_link_libraries(${VIEWER_BINARY_NAME}
+ ${LLIMAGEJ2COJ_LIBRARIES}
+ )
+endif (USE_KDU)
+
build_version(viewer)
set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
@@ -1691,6 +1710,17 @@ set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
if (LINUX)
set(product SecondLife-${ARCH}-${viewer_VERSION})
+ # These are the generated targets that are copied to package/
+ set(COPY_INPUT_DEPENDENCIES
+ ${VIEWER_BINARY_NAME}
+ linux-crash-logger
+ linux-updater
+ SLPlugin
+ media_plugin_webkit
+ media_plugin_gstreamer010
+ llcommon
+ )
+
add_custom_command(
OUTPUT ${product}.tar.bz2
COMMAND ${PYTHON_EXECUTABLE}
@@ -1708,18 +1738,11 @@ if (LINUX)
--login_channel=${VIEWER_LOGIN_CHANNEL}
--source=${CMAKE_CURRENT_SOURCE_DIR}
--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched
- DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
+ ${COPY_INPUT_DEPENDENCIES}
)
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit)
-
- if (PACKAGE)
- add_custom_target(package ALL DEPENDS ${product}.tar.bz2)
- add_dependencies(package linux-crash-logger-target)
- add_dependencies(package linux-updater-target)
- check_message_template(package)
- endif (PACKAGE)
-
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched
COMMAND ${PYTHON_EXECUTABLE}
@@ -1741,7 +1764,13 @@ if (LINUX)
)
add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched)
- add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}" linux-crash-logger-target linux-updater-target)
+
+ if (PACKAGE)
+ add_custom_target(package ALL DEPENDS ${product}.tar.bz2)
+ # Make sure we don't run two instances of viewer_manifest.py at the same time.
+ add_dependencies(package copy_l_viewer_manifest)
+ check_message_template(package)
+ endif (PACKAGE)
endif (LINUX)
if (DARWIN)
@@ -1780,7 +1809,6 @@ if (DARWIN)
if (PACKAGE)
add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME})
- check_message_template(package)
add_custom_command(
TARGET package POST_BUILD
@@ -1811,7 +1839,9 @@ if (PACKAGE)
if (WINDOWS)
set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows.tar.bz2")
- set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe")
+ # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad
+ # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe")
+ set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}")
set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest)
endif (WINDOWS)
@@ -1829,21 +1859,31 @@ if (PACKAGE)
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
endif (LINUX)
+ if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
+ 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}"
- "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms"
+ "${AUTOBUILD_INSTALL_DIR}/bin/dump_syms"
"${VIEWER_SYMBOL_FILE}"
DEPENDS generate_breakpad_symbols.py
- VERBATIM
- )
- add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}")
+ VERBATIM)
+
+ 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(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
endif (PACKAGE)
if (LL_TESTS)
@@ -1855,7 +1895,11 @@ if (LL_TESTS)
lldateutil.cpp
llmediadataclient.cpp
lllogininstance.cpp
+ llremoteparcelrequest.cpp
llviewerhelputil.cpp
+ llversioninfo.cpp
+ llworldmap.cpp
+ llworldmipmap.cpp
)
##################################################
@@ -1931,14 +1975,23 @@ if (LL_TESTS)
"${test_libs}"
)
+ LL_ADD_INTEGRATION_TEST(llsimplestat
+ ""
+ "${test_libs}"
+ )
+
+ LL_ADD_INTEGRATION_TEST(llviewerassetstats
+ llviewerassetstats.cpp
+ "${test_libs}"
+ )
+
#ADD_VIEWER_BUILD_TEST(llmemoryview viewer)
#ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
- #ADD_VIEWER_BUILD_TEST(llworldmap viewer)
- #ADD_VIEWER_BUILD_TEST(llworldmipmap viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfo viewer)
#ADD_VIEWER_BUILD_TEST(lltextureinfodetails viewer)
#ADD_VIEWER_BUILD_TEST(lltexturestatsuploader viewer)
endif (LL_TESTS)
+check_message_template(${VIEWER_BINARY_NAME})
diff --git a/indra/newview/app_settings/CA.pem b/indra/newview/app_settings/CA.pem
index 11825bf906..7cebbf48b2 100644
--- a/indra/newview/app_settings/CA.pem
+++ b/indra/newview/app_settings/CA.pem
@@ -3895,3 +3895,22 @@ xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9
e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu
glmQ1A==
-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
+UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
+dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
+MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
+dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
+BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
+cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
+AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
+aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
+ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
+IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
+MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
+A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
+7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
+1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
+-----END CERTIFICATE-----
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 00d69f805e..89e5949fbe 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>
@@ -259,6 +261,24 @@
<!-- Special case. Mapped to settings procedurally. -->
</map>
+ <key>sessionsettings</key>
+ <map>
+ <key>desc</key>
+ <string>Specify the filename of a configuration file that contains temporary per-session configuration overrides.</string>
+ <key>count</key>
+ <integer>1</integer>
+ <!-- Special case. Mapped to settings procedurally. -->
+ </map>
+
+ <key>usersessionsettings</key>
+ <map>
+ <key>desc</key>
+ <string>Specify the filename of a configuration file that contains temporary per-session configuration user overrides.</string>
+ <key>count</key>
+ <integer>1</integer>
+ <!-- Special case. Mapped to settings procedurally. -->
+ </map>
+
<key>login</key>
<map>
<key>desc</key>
@@ -361,8 +381,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 +410,12 @@
<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/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml
index 4da2b0fd00..4e137d971a 100644
--- a/indra/newview/app_settings/high_graphics.xml
+++ b/indra/newview/app_settings/high_graphics.xml
@@ -4,6 +4,8 @@
<RenderAvatarCloth value="FALSE"/>
<!--Default for now-->
<RenderAvatarLODFactor value="1.0"/>
+ <!--Default for now-->
+ <RenderAvatarPhysicsLODFactor value="0.9"/>
<!--NO SHADERS-->
<RenderAvatarVP value="TRUE"/>
<!--Short Range-->
diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml
index 9ddf007ce7..17d3d3c9c5 100644
--- a/indra/newview/app_settings/ignorable_dialogs.xml
+++ b/indra/newview/app_settings/ignorable_dialogs.xml
@@ -23,6 +23,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>FirstNotUseAvatarPicker</key>
+ <map>
+ <key>Comment</key>
+ <string>Shows hint when resident doesn't activate avatar picker</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>FirstNotUseSidePanel</key>
<map>
<key>Comment</key>
@@ -56,6 +67,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>FirstViewPopup</key>
+ <map>
+ <key>Comment</key>
+ <string>Shows hint when resident opens view popup</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>FirstReceiveLindens</key>
<map>
<key>Comment</key>
@@ -100,7 +122,17 @@
<key>Value</key>
<integer>1</integer>
</map>
-
+ <key>FirstSpeak</key>
+ <map>
+ <key>Comment</key>
+ <string>Shows hint for Speak button</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>FirstSit</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/keys.ini b/indra/newview/app_settings/keys.ini
deleted file mode 100644
index b79e5bf508..0000000000
--- a/indra/newview/app_settings/keys.ini
+++ /dev/null
@@ -1,357 +0,0 @@
-# keys.ini
-#
-# keyboard binding initialization
-#
-# comments must have # in the first column
-# blank lines OK
-#
-# Format:
-# mode key mask function
-#
-# mode must be one of FIRST_PERSON, THIRD_PERSON, EDIT, EDIT_AVATAR, or CONVERSATION
-# key must be upper case, or SPACE, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN,
-# or one of ,.;'[]
-# mask must be NONE, SHIFT, ALT, ALT_SHIFT.
-# Control is reserved for user commands.
-# function must be a function named in llkeyboard.cpp
-
-FIRST_PERSON A NONE slide_left
-FIRST_PERSON D NONE slide_right
-FIRST_PERSON W NONE push_forward
-FIRST_PERSON S NONE push_backward
-FIRST_PERSON E NONE jump
-FIRST_PERSON C NONE push_down
-FIRST_PERSON F NONE toggle_fly
-
-FIRST_PERSON LEFT NONE slide_left
-FIRST_PERSON RIGHT NONE slide_right
-FIRST_PERSON UP NONE push_forward
-FIRST_PERSON DOWN NONE push_backward
-FIRST_PERSON PGUP NONE jump
-FIRST_PERSON PGDN NONE push_down
-FIRST_PERSON HOME NONE toggle_fly
-
-FIRST_PERSON PAD_LEFT NONE slide_left
-FIRST_PERSON PAD_RIGHT NONE slide_right
-FIRST_PERSON PAD_UP NONE push_forward
-FIRST_PERSON PAD_DOWN NONE push_backward
-FIRST_PERSON PAD_PGUP NONE jump
-FIRST_PERSON PAD_PGDN NONE push_down
-FIRST_PERSON PAD_HOME NONE toggle_fly
-FIRST_PERSON PAD_CENTER NONE stop_moving
-FIRST_PERSON PAD_ENTER NONE start_chat
-FIRST_PERSON PAD_DIVIDE NONE start_gesture
-
-FIRST_PERSON A SHIFT slide_left
-FIRST_PERSON D SHIFT slide_right
-FIRST_PERSON W SHIFT push_forward
-FIRST_PERSON S SHIFT push_backward
-FIRST_PERSON E SHIFT jump
-FIRST_PERSON C SHIFT push_down
-FIRST_PERSON F SHIFT toggle_fly
-
-FIRST_PERSON SPACE NONE stop_moving
-FIRST_PERSON ENTER NONE start_chat
-FIRST_PERSON DIVIDE NONE start_gesture
-
-FIRST_PERSON LEFT SHIFT slide_left
-FIRST_PERSON RIGHT SHIFT slide_right
-FIRST_PERSON UP SHIFT push_forward
-FIRST_PERSON DOWN SHIFT push_backward
-FIRST_PERSON PGUP SHIFT jump
-FIRST_PERSON PGDN SHIFT push_down
-
-FIRST_PERSON PAD_LEFT SHIFT slide_left
-FIRST_PERSON PAD_RIGHT SHIFT slide_right
-FIRST_PERSON PAD_UP SHIFT push_forward
-FIRST_PERSON PAD_DOWN SHIFT push_backward
-FIRST_PERSON PAD_PGUP SHIFT jump
-FIRST_PERSON PAD_PGDN SHIFT push_down
-FIRST_PERSON PAD_HOME SHIFT toggle_fly
-FIRST_PERSON PAD_ENTER SHIFT start_chat
-FIRST_PERSON PAD_DIVIDE SHIFT start_gesture
-
-THIRD_PERSON A NONE turn_left
-THIRD_PERSON D NONE turn_right
-THIRD_PERSON A SHIFT slide_left
-THIRD_PERSON D SHIFT slide_right
-THIRD_PERSON W NONE push_forward
-THIRD_PERSON S NONE push_backward
-THIRD_PERSON W SHIFT push_forward
-THIRD_PERSON S SHIFT push_backward
-THIRD_PERSON E NONE jump
-THIRD_PERSON C NONE push_down
-THIRD_PERSON E SHIFT jump
-THIRD_PERSON C SHIFT push_down
-
-THIRD_PERSON F NONE toggle_fly
-THIRD_PERSON F SHIFT toggle_fly
-
-THIRD_PERSON SPACE NONE stop_moving
-THIRD_PERSON ENTER NONE start_chat
-THIRD_PERSON DIVIDE NONE start_gesture
-
-THIRD_PERSON LEFT NONE turn_left
-THIRD_PERSON LEFT SHIFT slide_left
-THIRD_PERSON RIGHT NONE turn_right
-THIRD_PERSON RIGHT SHIFT slide_right
-THIRD_PERSON UP NONE push_forward
-THIRD_PERSON DOWN NONE push_backward
-THIRD_PERSON UP SHIFT push_forward
-THIRD_PERSON DOWN SHIFT push_backward
-THIRD_PERSON PGUP NONE jump
-THIRD_PERSON PGDN NONE push_down
-THIRD_PERSON PGUP SHIFT jump
-THIRD_PERSON PGDN SHIFT push_down
-THIRD_PERSON HOME SHIFT toggle_fly
-THIRD_PERSON HOME NONE toggle_fly
-
-THIRD_PERSON PAD_LEFT NONE turn_left
-THIRD_PERSON PAD_LEFT SHIFT slide_left
-THIRD_PERSON PAD_RIGHT NONE turn_right
-THIRD_PERSON PAD_RIGHT SHIFT slide_right
-THIRD_PERSON PAD_UP NONE push_forward
-THIRD_PERSON PAD_DOWN NONE push_backward
-THIRD_PERSON PAD_UP SHIFT push_forward
-THIRD_PERSON PAD_DOWN SHIFT push_backward
-THIRD_PERSON PAD_PGUP NONE jump
-THIRD_PERSON PAD_PGDN NONE push_down
-THIRD_PERSON PAD_PGUP SHIFT jump
-THIRD_PERSON PAD_PGDN SHIFT push_down
-THIRD_PERSON PAD_HOME NONE toggle_fly
-THIRD_PERSON PAD_HOME SHIFT toggle_fly
-THIRD_PERSON PAD_CENTER NONE stop_moving
-THIRD_PERSON PAD_CENTER SHIFT stop_moving
-THIRD_PERSON PAD_ENTER NONE start_chat
-THIRD_PERSON PAD_ENTER SHIFT start_chat
-THIRD_PERSON PAD_DIVIDE NONE start_gesture
-THIRD_PERSON PAD_DIVIDE SHIFT start_gesture
-
-# Camera controls in third person on Alt
-THIRD_PERSON LEFT ALT spin_around_cw
-THIRD_PERSON RIGHT ALT spin_around_ccw
-THIRD_PERSON UP ALT move_forward
-THIRD_PERSON DOWN ALT move_backward
-THIRD_PERSON PGUP ALT spin_over
-THIRD_PERSON PGDN ALT spin_under
-
-THIRD_PERSON A ALT spin_around_cw
-THIRD_PERSON D ALT spin_around_ccw
-THIRD_PERSON W ALT move_forward
-THIRD_PERSON S ALT move_backward
-THIRD_PERSON E ALT spin_over
-THIRD_PERSON C ALT spin_under
-
-THIRD_PERSON PAD_LEFT ALT spin_around_cw
-THIRD_PERSON PAD_RIGHT ALT spin_around_ccw
-THIRD_PERSON PAD_UP ALT move_forward
-THIRD_PERSON PAD_DOWN ALT move_backward
-THIRD_PERSON PAD_PGUP ALT spin_over
-THIRD_PERSON PAD_PGDN ALT spin_under
-THIRD_PERSON PAD_ENTER ALT start_chat
-THIRD_PERSON PAD_DIVIDE ALT start_gesture
-
-# mimic alt zoom behavior with keyboard only
-THIRD_PERSON A CTL_ALT spin_around_cw
-THIRD_PERSON D CTL_ALT spin_around_ccw
-THIRD_PERSON W CTL_ALT spin_over
-THIRD_PERSON S CTL_ALT spin_under
-THIRD_PERSON E CTL_ALT spin_over
-THIRD_PERSON C CTL_ALT spin_under
-
-THIRD_PERSON LEFT CTL_ALT spin_around_cw
-THIRD_PERSON RIGHT CTL_ALT spin_around_ccw
-THIRD_PERSON UP CTL_ALT spin_over
-THIRD_PERSON DOWN CTL_ALT spin_under
-THIRD_PERSON PGUP CTL_ALT spin_over
-THIRD_PERSON PGDN CTL_ALT spin_under
-
-THIRD_PERSON PAD_LEFT CTL_ALT spin_around_cw
-THIRD_PERSON PAD_RIGHT CTL_ALT spin_around_ccw
-THIRD_PERSON PAD_UP CTL_ALT spin_over
-THIRD_PERSON PAD_DOWN CTL_ALT spin_under
-THIRD_PERSON PAD_PGUP CTL_ALT spin_over
-THIRD_PERSON PAD_PGDN CTL_ALT spin_under
-THIRD_PERSON PAD_ENTER CTL_ALT start_chat
-THIRD_PERSON PAD_DIVIDE CTL_ALT start_gesture
-
-# Therefore pan on Alt-Shift
-THIRD_PERSON A CTL_ALT_SHIFT pan_left
-THIRD_PERSON D CTL_ALT_SHIFT pan_right
-THIRD_PERSON W CTL_ALT_SHIFT pan_up
-THIRD_PERSON S CTL_ALT_SHIFT pan_down
-
-THIRD_PERSON LEFT CTL_ALT_SHIFT pan_left
-THIRD_PERSON RIGHT CTL_ALT_SHIFT pan_right
-THIRD_PERSON UP CTL_ALT_SHIFT pan_up
-THIRD_PERSON DOWN CTL_ALT_SHIFT pan_down
-
-THIRD_PERSON PAD_LEFT CTL_ALT_SHIFT pan_left
-THIRD_PERSON PAD_RIGHT CTL_ALT_SHIFT pan_right
-THIRD_PERSON PAD_UP CTL_ALT_SHIFT pan_up
-THIRD_PERSON PAD_DOWN CTL_ALT_SHIFT pan_down
-THIRD_PERSON PAD_ENTER CTL_ALT_SHIFT start_chat
-THIRD_PERSON PAD_DIVIDE CTL_ALT_SHIFT start_gesture
-
-# Basic editing camera control
-EDIT A NONE spin_around_cw
-EDIT D NONE spin_around_ccw
-EDIT W NONE move_forward
-EDIT S NONE move_backward
-EDIT E NONE spin_over
-EDIT C NONE spin_under
-EDIT ENTER NONE start_chat
-EDIT DIVIDE NONE start_gesture
-EDIT PAD_ENTER NONE start_chat
-EDIT PAD_DIVIDE NONE start_gesture
-
-EDIT LEFT NONE spin_around_cw
-EDIT RIGHT NONE spin_around_ccw
-EDIT UP NONE move_forward
-EDIT DOWN NONE move_backward
-EDIT PGUP NONE spin_over
-EDIT PGDN NONE spin_under
-
-EDIT A SHIFT pan_left
-EDIT D SHIFT pan_right
-EDIT W SHIFT pan_up
-EDIT S SHIFT pan_down
-
-EDIT LEFT SHIFT pan_left
-EDIT RIGHT SHIFT pan_right
-EDIT UP SHIFT pan_up
-EDIT DOWN SHIFT pan_down
-
-# Walking works with ALT held down.
-EDIT A ALT slide_left
-EDIT D ALT slide_right
-EDIT W ALT push_forward
-EDIT S ALT push_backward
-EDIT E ALT jump
-EDIT C ALT push_down
-
-EDIT LEFT ALT slide_left
-EDIT RIGHT ALT slide_right
-EDIT UP ALT push_forward
-EDIT DOWN ALT push_backward
-EDIT PGUP ALT jump
-EDIT PGDN ALT push_down
-EDIT HOME ALT toggle_fly
-
-EDIT PAD_LEFT ALT slide_left
-EDIT PAD_RIGHT ALT slide_right
-EDIT PAD_UP ALT push_forward
-EDIT PAD_DOWN ALT push_backward
-EDIT PAD_PGUP ALT jump
-EDIT PAD_PGDN ALT push_down
-EDIT PAD_ENTER ALT start_chat
-EDIT PAD_DIVIDE ALT start_gesture
-
-SITTING A ALT spin_around_cw
-SITTING D ALT spin_around_ccw
-SITTING W ALT move_forward
-SITTING S ALT move_backward
-SITTING E ALT spin_over_sitting
-SITTING C ALT spin_under_sitting
-
-SITTING LEFT ALT spin_around_cw
-SITTING RIGHT ALT spin_around_ccw
-SITTING UP ALT move_forward
-SITTING DOWN ALT move_backward
-SITTING PGUP ALT spin_over
-SITTING PGDN ALT spin_under
-
-SITTING A CTL_ALT spin_around_cw
-SITTING D CTL_ALT spin_around_ccw
-SITTING W CTL_ALT spin_over
-SITTING S CTL_ALT spin_under
-SITTING E CTL_ALT spin_over
-SITTING C CTL_ALT spin_under
-
-SITTING LEFT CTL_ALT spin_around_cw
-SITTING RIGHT CTL_ALT spin_around_ccw
-SITTING UP CTL_ALT spin_over
-SITTING DOWN CTL_ALT spin_under
-SITTING PGUP CTL_ALT spin_over
-SITTING PGDN CTL_ALT spin_under
-
-
-SITTING A NONE spin_around_cw_sitting
-SITTING D NONE spin_around_ccw_sitting
-SITTING W NONE move_forward_sitting
-SITTING S NONE move_backward_sitting
-SITTING E NONE spin_over_sitting
-SITTING C NONE spin_under_sitting
-
-SITTING LEFT NONE spin_around_cw_sitting
-SITTING RIGHT NONE spin_around_ccw_sitting
-SITTING UP NONE move_forward_sitting
-SITTING DOWN NONE move_backward_sitting
-SITTING PGUP NONE spin_over_sitting
-SITTING PGDN NONE spin_under_sitting
-
-SITTING PAD_LEFT NONE spin_around_cw_sitting
-SITTING PAD_RIGHT NONE spin_around_ccw_sitting
-SITTING PAD_UP NONE move_forward_sitting
-SITTING PAD_DOWN NONE move_backward_sitting
-SITTING PAD_PGUP NONE spin_over_sitting
-SITTING PAD_PGDN NONE spin_under_sitting
-SITTING PAD_CENTER NONE stop_moving
-SITTING PAD_ENTER NONE start_chat
-SITTING PAD_DIVIDE NONE start_gesture
-
-# these are for passing controls when sitting on vehicles
-SITTING A SHIFT slide_left
-SITTING D SHIFT slide_right
-SITTING LEFT SHIFT slide_left
-SITTING RIGHT SHIFT slide_right
-
-SITTING PAD_LEFT SHIFT slide_left
-SITTING PAD_RIGHT SHIFT slide_right
-SITTING PAD_ENTER SHIFT start_chat
-SITTING PAD_DIVIDE SHIFT start_gesture
-
-# pan on Alt-Shift
-SITTING A CTL_ALT_SHIFT pan_left
-SITTING D CTL_ALT_SHIFT pan_right
-SITTING W CTL_ALT_SHIFT pan_up
-SITTING S CTL_ALT_SHIFT pan_down
-
-SITTING LEFT CTL_ALT_SHIFT pan_left
-SITTING RIGHT CTL_ALT_SHIFT pan_right
-SITTING UP CTL_ALT_SHIFT pan_up
-SITTING DOWN CTL_ALT_SHIFT pan_down
-
-SITTING PAD_LEFT CTL_ALT_SHIFT pan_left
-SITTING PAD_RIGHT CTL_ALT_SHIFT pan_right
-SITTING PAD_UP CTL_ALT_SHIFT pan_up
-SITTING PAD_DOWN CTL_ALT_SHIFT pan_down
-SITTING PAD_ENTER CTL_ALT_SHIFT start_chat
-SITTING PAD_DIVIDE CTL_ALT_SHIFT start_gesture
-
-SITTING ENTER NONE start_chat
-SITTING DIVIDE NONE start_gesture
-
-# Avatar editing camera controls
-EDIT_AVATAR A NONE edit_avatar_spin_cw
-EDIT_AVATAR D NONE edit_avatar_spin_ccw
-EDIT_AVATAR W NONE edit_avatar_move_forward
-EDIT_AVATAR S NONE edit_avatar_move_backward
-EDIT_AVATAR E NONE edit_avatar_spin_over
-EDIT_AVATAR C NONE edit_avatar_spin_under
-EDIT_AVATAR LEFT NONE edit_avatar_spin_cw
-EDIT_AVATAR RIGHT NONE edit_avatar_spin_ccw
-EDIT_AVATAR UP NONE edit_avatar_move_forward
-EDIT_AVATAR DOWN NONE edit_avatar_move_backward
-EDIT_AVATAR PGUP NONE edit_avatar_spin_over
-EDIT_AVATAR PGDN NONE edit_avatar_spin_under
-EDIT_AVATAR ENTER NONE start_chat
-EDIT_AVATAR DIVIDE NONE start_gesture
-EDIT_AVATAR PAD_LEFT NONE edit_avatar_spin_cw
-EDIT_AVATAR PAD_RIGHT NONE edit_avatar_spin_ccw
-EDIT_AVATAR PAD_UP NONE edit_avatar_move_forward
-EDIT_AVATAR PAD_DOWN NONE edit_avatar_move_backward
-EDIT_AVATAR PAD_PGUP NONE edit_avatar_spin_over
-EDIT_AVATAR PAD_PGDN NONE edit_avatar_spin_under
-EDIT_AVATAR PAD_ENTER NONE start_chat
-EDIT_AVATAR PAD_DIVIDE NONE start_gesture
diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml
new file mode 100644
index 0000000000..d085475c6c
--- /dev/null
+++ b/indra/newview/app_settings/keys.xml
@@ -0,0 +1,350 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<keys>
+ <first_person>
+ <binding key="A" mask="NONE" command="slide_left"/>
+ <binding key="D" mask="NONE" command="slide_right"/>
+ <binding key="W" mask="NONE" command="push_forward"/>
+ <binding key="S" mask="NONE" command="push_backward"/>
+ <binding key="E" mask="NONE" command="jump"/>
+ <binding key="C" mask="NONE" command="push_down"/>
+ <binding key="F" mask="NONE" command="toggle_fly"/>
+
+ <binding key="LEFT" mask="NONE" command="slide_left"/>
+ <binding key="RIGHT" mask="NONE" command="slide_right"/>
+ <binding key="UP" mask="NONE" command="push_forward"/>
+ <binding key="DOWN" mask="NONE" command="push_backward"/>
+ <binding key="PGUP" mask="NONE" command="jump"/>
+ <binding key="PGDN" mask="NONE" command="push_down"/>
+ <binding key="HOME" mask="NONE" command="toggle_fly"/>
+
+ <binding key="PAD_LEFT" mask="NONE" command="slide_left"/>
+ <binding key="PAD_RIGHT" mask="NONE" command="slide_right"/>
+ <binding key="PAD_UP" mask="NONE" command="push_forward"/>
+ <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
+ <binding key="PAD_PGUP" mask="NONE" command="jump"/>
+ <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
+ <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
+ <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
+ <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
+
+ <binding key="A" mask="SHIFT" command="slide_left"/>
+ <binding key="D" mask="SHIFT" command="slide_right"/>
+ <binding key="W" mask="SHIFT" command="push_forward"/>
+ <binding key="S" mask="SHIFT" command="push_backward"/>
+ <binding key="E" mask="SHIFT" command="jump"/>
+ <binding key="C" mask="SHIFT" command="push_down"/>
+ <binding key="F" mask="SHIFT" command="toggle_fly"/>
+
+ <binding key="SPACE" mask="NONE" command="stop_moving"/>
+ <binding key="ENTER" mask="NONE" command="start_chat"/>
+ <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+
+ <binding key="LEFT" mask="SHIFT" command="slide_left"/>
+ <binding key="RIGHT" mask="SHIFT" command="slide_right"/>
+ <binding key="UP" mask="SHIFT" command="push_forward"/>
+ <binding key="DOWN" mask="SHIFT" command="push_backward"/>
+ <binding key="PGUP" mask="SHIFT" command="jump"/>
+ <binding key="PGDN" mask="SHIFT" command="push_down"/>
+
+ <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
+ <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
+ <binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
+ <binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
+ <binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
+ <binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
+ <binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
+ <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
+ </first_person>
+ <third_person>
+ <binding key="A" mask="NONE" command="turn_left"/>
+ <binding key="D" mask="NONE" command="turn_right"/>
+ <binding key="A" mask="SHIFT" command="slide_left"/>
+ <binding key="D" mask="SHIFT" command="slide_right"/>
+ <binding key="W" mask="NONE" command="push_forward"/>
+ <binding key="S" mask="NONE" command="push_backward"/>
+ <binding key="W" mask="SHIFT" command="push_forward"/>
+ <binding key="S" mask="SHIFT" command="push_backward"/>
+ <binding key="E" mask="NONE" command="jump"/>
+ <binding key="C" mask="NONE" command="push_down"/>
+ <binding key="E" mask="SHIFT" command="jump"/>
+ <binding key="C" mask="SHIFT" command="push_down"/>
+
+ <binding key="F" mask="NONE" command="toggle_fly"/>
+ <binding key="F" mask="SHIFT" command="toggle_fly"/>
+
+ <binding key="SPACE" mask="NONE" command="stop_moving"/>
+ <binding key="ENTER" mask="NONE" command="start_chat"/>
+ <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+
+ <binding key="LEFT" mask="NONE" command="turn_left"/>
+ <binding key="LEFT" mask="SHIFT" command="slide_left"/>
+ <binding key="RIGHT" mask="NONE" command="turn_right"/>
+ <binding key="RIGHT" mask="SHIFT" command="slide_right"/>
+ <binding key="UP" mask="NONE" command="push_forward"/>
+ <binding key="DOWN" mask="NONE" command="push_backward"/>
+ <binding key="UP" mask="SHIFT" command="push_forward"/>
+ <binding key="DOWN" mask="SHIFT" command="push_backward"/>
+ <binding key="PGUP" mask="NONE" command="jump"/>
+ <binding key="PGDN" mask="NONE" command="push_down"/>
+ <binding key="PGUP" mask="SHIFT" command="jump"/>
+ <binding key="PGDN" mask="SHIFT" command="push_down"/>
+ <binding key="HOME" mask="SHIFT" command="toggle_fly"/>
+ <binding key="HOME" mask="NONE" command="toggle_fly"/>
+
+ <binding key="PAD_LEFT" mask="NONE" command="turn_left"/>
+ <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
+ <binding key="PAD_RIGHT" mask="NONE" command="turn_right"/>
+ <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
+ <binding key="PAD_UP" mask="NONE" command="push_forward"/>
+ <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
+ <binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
+ <binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
+ <binding key="PAD_PGUP" mask="NONE" command="jump"/>
+ <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
+ <binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
+ <binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
+ <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
+ <binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
+ <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
+ <binding key="PAD_CENTER" mask="SHIFT" command="stop_moving"/>
+ <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
+ <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
+ <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
+
+ <!--Camera controls in third person on Alt-->
+ <binding key="LEFT" mask="ALT" command="spin_around_cw"/>
+ <binding key="RIGHT" mask="ALT" command="spin_around_ccw"/>
+ <binding key="UP" mask="ALT" command="move_forward"/>
+ <binding key="DOWN" mask="ALT" command="move_backward"/>
+ <binding key="PGUP" mask="ALT" command="spin_over"/>
+ <binding key="PGDN" mask="ALT" command="spin_under"/>
+
+ <binding key="A" mask="ALT" command="spin_around_cw"/>
+ <binding key="D" mask="ALT" command="spin_around_ccw"/>
+ <binding key="W" mask="ALT" command="move_forward"/>
+ <binding key="S" mask="ALT" command="move_backward"/>
+ <binding key="E" mask="ALT" command="spin_over"/>
+ <binding key="C" mask="ALT" command="spin_under"/>
+
+ <binding key="PAD_LEFT" mask="ALT" command="spin_around_cw"/>
+ <binding key="PAD_RIGHT" mask="ALT" command="spin_around_ccw"/>
+ <binding key="PAD_UP" mask="ALT" command="move_forward"/>
+ <binding key="PAD_DOWN" mask="ALT" command="move_backward"/>
+ <binding key="PAD_PGUP" mask="ALT" command="spin_over"/>
+ <binding key="PAD_PGDN" mask="ALT" command="spin_under"/>
+ <binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
+
+ <!--mimic alt zoom behavior with keyboard only-->
+ <binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
+ <binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
+ <binding key="W" mask="CTL_ALT" command="spin_over"/>
+ <binding key="S" mask="CTL_ALT" command="spin_under"/>
+ <binding key="E" mask="CTL_ALT" command="spin_over"/>
+ <binding key="C" mask="CTL_ALT" command="spin_under"/>
+
+ <binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
+ <binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
+ <binding key="UP" mask="CTL_ALT" command="spin_over"/>
+ <binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
+ <binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
+ <binding key="PGDN" mask="CTL_ALT" command="spin_under"/>
+
+ <binding key="PAD_LEFT" mask="CTL_ALT" command="spin_around_cw"/>
+ <binding key="PAD_RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
+ <binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/>
+ <binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/>
+ <binding key="PAD_PGUP" mask="CTL_ALT" command="spin_over"/>
+ <binding key="PAD_PGDN" mask="CTL_ALT" command="spin_under"/>
+ <binding key="PAD_ENTER" mask="CTL_ALT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="CTL_ALT" command="start_gesture"/>
+
+ <!--Therefore pan on Alt-Shift-->
+ <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
+ <binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/>
+ <binding key="W" mask="CTL_ALT_SHIFT" command="pan_up"/>
+ <binding key="S" mask="CTL_ALT_SHIFT" command="pan_down"/>
+
+ <binding key="LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
+ <binding key="RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
+ <binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
+ <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
+
+ <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
+ <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
+ <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
+ <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
+ <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
+ </third_person>
+
+ # Basic editing camera control
+ <edit>
+ <binding key="A" mask="NONE" command="spin_around_cw"/>
+ <binding key="D" mask="NONE" command="spin_around_ccw"/>
+ <binding key="W" mask="NONE" command="move_forward"/>
+ <binding key="S" mask="NONE" command="move_backward"/>
+ <binding key="E" mask="NONE" command="spin_over"/>
+ <binding key="C" mask="NONE" command="spin_under"/>
+ <binding key="ENTER" mask="NONE" command="start_chat"/>
+ <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+ <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
+
+ <binding key="LEFT" mask="NONE" command="spin_around_cw"/>
+ <binding key="RIGHT" mask="NONE" command="spin_around_ccw"/>
+ <binding key="UP" mask="NONE" command="move_forward"/>
+ <binding key="DOWN" mask="NONE" command="move_backward"/>
+ <binding key="PGUP" mask="NONE" command="spin_over"/>
+ <binding key="PGDN" mask="NONE" command="spin_under"/>
+
+ <binding key="A" mask="SHIFT" command="pan_left"/>
+ <binding key="D" mask="SHIFT" command="pan_right"/>
+ <binding key="W" mask="SHIFT" command="pan_up"/>
+ <binding key="S" mask="SHIFT" command="pan_down"/>
+
+ <binding key="LEFT" mask="SHIFT" command="pan_left"/>
+ <binding key="RIGHT" mask="SHIFT" command="pan_right"/>
+ <binding key="UP" mask="SHIFT" command="pan_up"/>
+ <binding key="DOWN" mask="SHIFT" command="pan_down"/>
+
+ <!--Walking works with ALT held down.-->
+ <binding key="A" mask="ALT" command="slide_left"/>
+ <binding key="D" mask="ALT" command="slide_right"/>
+ <binding key="W" mask="ALT" command="push_forward"/>
+ <binding key="S" mask="ALT" command="push_backward"/>
+ <binding key="E" mask="ALT" command="jump"/>
+ <binding key="C" mask="ALT" command="push_down"/>
+
+ <binding key="LEFT" mask="ALT" command="slide_left"/>
+ <binding key="RIGHT" mask="ALT" command="slide_right"/>
+ <binding key="UP" mask="ALT" command="push_forward"/>
+ <binding key="DOWN" mask="ALT" command="push_backward"/>
+ <binding key="PGUP" mask="ALT" command="jump"/>
+ <binding key="PGDN" mask="ALT" command="push_down"/>
+ <binding key="HOME" mask="ALT" command="toggle_fly"/>
+
+ <binding key="PAD_LEFT" mask="ALT" command="slide_left"/>
+ <binding key="PAD_RIGHT" mask="ALT" command="slide_right"/>
+ <binding key="PAD_UP" mask="ALT" command="push_forward"/>
+ <binding key="PAD_DOWN" mask="ALT" command="push_backward"/>
+ <binding key="PAD_PGUP" mask="ALT" command="jump"/>
+ <binding key="PAD_PGDN" mask="ALT" command="push_down"/>
+ <binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
+ </edit>
+ <sitting>
+ <binding key="A" mask="ALT" command="spin_around_cw"/>
+ <binding key="D" mask="ALT" command="spin_around_ccw"/>
+ <binding key="W" mask="ALT" command="move_forward"/>
+ <binding key="S" mask="ALT" command="move_backward"/>
+ <binding key="E" mask="ALT" command="spin_over_sitting"/>
+ <binding key="C" mask="ALT" command="spin_under_sitting"/>
+
+ <binding key="LEFT" mask="ALT" command="spin_around_cw"/>
+ <binding key="RIGHT" mask="ALT" command="spin_around_ccw"/>
+ <binding key="UP" mask="ALT" command="move_forward"/>
+ <binding key="DOWN" mask="ALT" command="move_backward"/>
+ <binding key="PGUP" mask="ALT" command="spin_over"/>
+ <binding key="PGDN" mask="ALT" command="spin_under"/>
+
+ <binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
+ <binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
+ <binding key="W" mask="CTL_ALT" command="spin_over"/>
+ <binding key="S" mask="CTL_ALT" command="spin_under"/>
+ <binding key="E" mask="CTL_ALT" command="spin_over"/>
+ <binding key="C" mask="CTL_ALT" command="spin_under"/>
+
+ <binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
+ <binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
+ <binding key="UP" mask="CTL_ALT" command="spin_over"/>
+ <binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
+ <binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
+ <binding key="PGDN" mask="CTL_ALT" command="spin_under"/>
+
+
+ <binding key="A" mask="NONE" command="spin_around_cw_sitting"/>
+ <binding key="D" mask="NONE" command="spin_around_ccw_sitting"/>
+ <binding key="W" mask="NONE" command="move_forward_sitting"/>
+ <binding key="S" mask="NONE" command="move_backward_sitting"/>
+ <binding key="E" mask="NONE" command="spin_over_sitting"/>
+ <binding key="C" mask="NONE" command="spin_under_sitting"/>
+
+ <binding key="LEFT" mask="NONE" command="spin_around_cw_sitting"/>
+ <binding key="RIGHT" mask="NONE" command="spin_around_ccw_sitting"/>
+ <binding key="UP" mask="NONE" command="move_forward_sitting"/>
+ <binding key="DOWN" mask="NONE" command="move_backward_sitting"/>
+ <binding key="PGUP" mask="NONE" command="spin_over_sitting"/>
+ <binding key="PGDN" mask="NONE" command="spin_under_sitting"/>
+
+ <binding key="PAD_LEFT" mask="NONE" command="spin_around_cw_sitting"/>
+ <binding key="PAD_RIGHT" mask="NONE" command="spin_around_ccw_sitting"/>
+ <binding key="PAD_UP" mask="NONE" command="move_forward_sitting"/>
+ <binding key="PAD_DOWN" mask="NONE" command="move_backward_sitting"/>
+ <binding key="PAD_PGUP" mask="NONE" command="spin_over_sitting"/>
+ <binding key="PAD_PGDN" mask="NONE" command="spin_under_sitting"/>
+ <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
+ <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
+
+ <!--these are for passing controls when sitting on vehicles-->
+ <binding key="A" mask="SHIFT" command="slide_left"/>
+ <binding key="D" mask="SHIFT" command="slide_right"/>
+ <binding key="LEFT" mask="SHIFT" command="slide_left"/>
+ <binding key="RIGHT" mask="SHIFT" command="slide_right"/>
+
+ <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
+ <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
+ <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
+
+ <!--pan on Alt-Shift-->
+ <binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
+ <binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/>
+ <binding key="W" mask="CTL_ALT_SHIFT" command="pan_up"/>
+ <binding key="S" mask="CTL_ALT_SHIFT" command="pan_down"/>
+
+ <binding key="LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
+ <binding key="RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
+ <binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
+ <binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
+
+ <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
+ <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
+ <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
+ <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
+ <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
+
+ <binding key="ENTER" mask="NONE" command="start_chat"/>
+ <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+ </sitting>
+ <edit_avatar>
+ <!--Avatar editing camera controls-->
+ <binding key="A" mask="NONE" command="edit_avatar_spin_cw"/>
+ <binding key="D" mask="NONE" command="edit_avatar_spin_ccw"/>
+ <binding key="W" mask="NONE" command="edit_avatar_move_forward"/>
+ <binding key="S" mask="NONE" command="edit_avatar_move_backward"/>
+ <binding key="E" mask="NONE" command="edit_avatar_spin_over"/>
+ <binding key="C" mask="NONE" command="edit_avatar_spin_under"/>
+ <binding key="LEFT" mask="NONE" command="edit_avatar_spin_cw"/>
+ <binding key="RIGHT" mask="NONE" command="edit_avatar_spin_ccw"/>
+ <binding key="UP" mask="NONE" command="edit_avatar_move_forward"/>
+ <binding key="DOWN" mask="NONE" command="edit_avatar_move_backward"/>
+ <binding key="PGUP" mask="NONE" command="edit_avatar_spin_over"/>
+ <binding key="PGDN" mask="NONE" command="edit_avatar_spin_under"/>
+ <binding key="ENTER" mask="NONE" command="start_chat"/>
+ <binding key="DIVIDE" mask="NONE" command="start_gesture"/>
+ <binding key="PAD_LEFT" mask="NONE" command="edit_avatar_spin_cw"/>
+ <binding key="PAD_RIGHT" mask="NONE" command="edit_avatar_spin_ccw"/>
+ <binding key="PAD_UP" mask="NONE" command="edit_avatar_move_forward"/>
+ <binding key="PAD_DOWN" mask="NONE" command="edit_avatar_move_backward"/>
+ <binding key="PAD_PGUP" mask="NONE" command="edit_avatar_spin_over"/>
+ <binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/>
+ <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
+ <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
+ </edit_avatar>
+</keys> \ No newline at end of file
diff --git a/indra/newview/app_settings/lindenlab.pem b/indra/newview/app_settings/lindenlab.pem
new file mode 100644
index 0000000000..eddae0426d
--- /dev/null
+++ b/indra/newview/app_settings/lindenlab.pem
@@ -0,0 +1,97 @@
+-----BEGIN CERTIFICATE-----
+MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j
+aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu
+IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg
+Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s
+YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
+c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g
+TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD
+ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh
+Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO
+rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF
+oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk
+8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f
+1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG
+yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW
+MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j
+LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn
+BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI
+hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu
+xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9
+e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu
+glmQ1A==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEkDCCA3igAwIBAgICTSUwDQYJKoZIhvcNAQEFBQAwQDELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDkdlb1RydXN0LCBJbmMuMRgwFgYDVQQDEw9HZW9UcnVzdCBTU0wg
+Q0EwHhcNMTAxMjIwMTkxMTI2WhcNMTIwMjIxMTI1NDAzWjCBnzEpMCcGA1UEBRMg
+UkMteW9jbXIwdXRmRTdOMVBlaHJHQXdqL0lNc2hJZS0xCzAJBgNVBAYTAlVTMRMw
+EQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMR0wGwYD
+VQQKExRMaW5kZW4gUmVzZWFyY2ggSW5jLjEZMBcGA1UEAwwQKi5zZWNvbmRsaWZl
+LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN/VCCu1SZ5x4vNp
+XZZ8r3lzqeLwjxVZfMSQCKM4lV5DFbqiZMMBto4Y/ib7i0audzuTDnImCLsfzlTu
+7iZLoJNy42/43Rq4xtaDZ7joxALFmzXUKEipgHiTTbAbLQNCS4wPXts3tScODVZY
+/mhlmXdlLuGxJbqoyOEP6NEQbgXWDCKDERnAEG/FJBVHKyBfg3abrrIuQNwYCKCS
+2OZ5Z5MveGmY4tSKUOOi/c0vV9HsanQn/ymybZjxR5Kmb1CvQr7VVtbpR1MhlGkc
+sfJz1NFIFxdXkUggIny+XSG1dAAJRFFumyRM+X/eh0NHNmAI14JJ43hB6Zw3dzzl
+An9BSeECAwEAAaOCATIwggEuMB8GA1UdIwQYMBaAFEJ5VBthzVUrPmPVPEhX9Z/7
+Rc5KMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH
+AwIwKwYDVR0RBCQwIoIQKi5zZWNvbmRsaWZlLmNvbYIOc2Vjb25kbGlmZS5jb20w
+PQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2d0c3NsLWNybC5nZW90cnVzdC5jb20v
+Y3Jscy9ndHNzbC5jcmwwHQYDVR0OBBYEFK9UTMkc4Fh/Ug4fVs6UVhxP6my0MAwG
+A1UdEwEB/wQCMAAwQwYIKwYBBQUHAQEENzA1MDMGCCsGAQUFBzAChidodHRwOi8v
+Z3Rzc2wtYWlhLmdlb3RydXN0LmNvbS9ndHNzbC5jcnQwDQYJKoZIhvcNAQEFBQAD
+ggEBACIR9yggGHDcZ60AMNdFmZ8XJeahTuv6q2X/It2JxqSQp5BVQUei0NGIYYOt
+yg0JFBZn5KqXiQ5Zz84K4hdvh/6grCEAn4v37sozSbkeZ92Lec8NOZR42HfYIOCo
+Hx9q7CNRxdhv6ehV4LekaRBxrtp5etVsIDaWvRZEswCWl46VuLrfjcpauj6DAdOQ
+FfPVAW+4nPgLr8KapZMnXYnabIwrj9DQLQ88w/D7durenu/SYJEahWW9mb++n9is
+eMjyuyzYW0PTUBTaDsj+2ZmHJtoR1tBiLqh0Q62UQnmDgsf5SK5PTb8jnta/1SvN
+3pirsuvjMPV19zuH6b9NpJfXfd0=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
+MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
+aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw
+WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE
+AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m
+OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu
+T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c
+JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR
+Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz
+PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm
+aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM
+TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g
+LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO
+BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv
+dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB
+AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL
+NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W
+b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIID2TCCAsGgAwIBAgIDAjbQMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMTAwMjE5MjIzOTI2WhcNMjAwMjE4MjIzOTI2WjBAMQswCQYDVQQG
+EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xGDAWBgNVBAMTD0dlb1RydXN0
+IFNTTCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJCzgMHk5Uat
+cGA9uuUU3Z6KXot1WubKbUGlI+g5hSZ6p1V3mkihkn46HhrxJ6ujTDnMyz1Hr4Gu
+FmpcN+9FQf37mpc8oEOdxt8XIdGKolbCA0mEEoE+yQpUYGa5jFTk+eb5lPHgX3UR
+8im55IaisYmtph6DKWOy8FQchQt65+EuDa+kvc3nsVrXjAVaDktzKIt1XTTYdwvh
+dGLicTBi2LyKBeUxY0pUiWozeKdOVSQdl+8a5BLGDzAYtDRN4dgjOyFbLTAZJQ50
+96QhS6CkIMlszZhWwPKoXz4mdaAN+DaIiixafWcwqQ/RmXAueOFRJq9VeiS+jDkN
+d53eAsMMvR8CAwEAAaOB2TCB1jAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFEJ5
+VBthzVUrPmPVPEhX9Z/7Rc5KMB8GA1UdIwQYMBaAFMB6mGiNifurBWQMEX2qfWW4
+ysxOMBIGA1UdEwEB/wQIMAYBAf8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDov
+L2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwNAYIKwYBBQUHAQEE
+KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nZW90cnVzdC5jb20wDQYJKoZI
+hvcNAQEFBQADggEBANTvU4ToGr2hiwTAqfVfoRB4RV2yV2pOJMtlTjGXkZrUJPji
+J2ZwMZzBYlQG55cdOprApClICq8kx6jEmlTBfEx4TCtoLF0XplR4TEbigMMfOHES
+0tdT41SFULgCy+5jOvhWiU1Vuy7AyBh3hjELC3DwfjWDpCoTZFZnNF0WX3OsewYk
+2k9QbSqr0E1TQcKOu3EDSSmGGM8hQkx0YlEVxW+o78Qn5Rsz3VqI138S0adhJR/V
+4NwdzxoQ2KDLX4z6DOW/cf/lXUQdpj6HR/oaToODEj+IZpWYeZqF6wJHzSXj8gYE
+TpnKXKBuervdo5AaRTPvvz7SBMS24CqFZUE+ENQ=
+-----END CERTIFICATE-----
diff --git a/indra/newview/app_settings/llsd.xsd b/indra/newview/app_settings/llsd.xsd
new file mode 100644
index 0000000000..34612d9faa
--- /dev/null
+++ b/indra/newview/app_settings/llsd.xsd
@@ -0,0 +1,131 @@
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <!-- LLSD document has exactly one value -->
+ <xsd:element name="llsd">
+ <xsd:complexType>
+ <xsd:group ref="llsd-value" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Value is one of undef, boolean, integer, real,
+ uuid, string, date, binary, array, or map -->
+ <xsd:group name="llsd-value">
+ <xsd:choice>
+ <xsd:element ref="undef"/>
+ <xsd:element ref="boolean"/>
+ <xsd:element ref="integer"/>
+ <xsd:element ref="real"/>
+ <xsd:element ref="uuid"/>
+ <xsd:element ref="string"/>
+ <xsd:element ref="date"/>
+ <xsd:element ref="uri"/>
+ <xsd:element ref="binary"/>
+ <xsd:element ref="array"/>
+ <xsd:element ref="map"/>
+ </xsd:choice>
+ </xsd:group>
+
+ <!-- Undefined is an empty eleemnt -->
+ <xsd:element name="undef">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:length value="0" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- Boolean is true or false -->
+ <xsd:element name="boolean">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="true" />
+ <xsd:enumeration value="false" />
+
+ <!-- In practice, these other serializations are seen: -->
+ <xsd:enumeration value="" />
+ <xsd:enumeration value="1" />
+ <xsd:enumeration value="0" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- Integer is restricted to 32-bit signed values -->
+ <xsd:element name="integer">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:int" />
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- Real is an IEEE 754 "double" value, including Infinities and NaN -->
+ <xsd:element name="real">
+ <xsd:simpleType>
+ <!-- TODO: xsd:double uses "INF", "-INF", and "NaN",
+ whereas LLSD prefers "Infinity", "-Infinity" and "NaN" -->
+ <xsd:restriction base="xsd:double" />
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- UUID per RFC 4122 -->
+ <xsd:element name="uuid">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- String is any sequence of Unicode characters -->
+ <xsd:element name="string">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string" />
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- Date is ISO 8601 in UTC -->
+ <xsd:element name="date">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:dateTime">
+ <!-- Restrict to UTC (Z) times -->
+ <xsd:pattern value="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?Z" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- URI per RFC 3986 -->
+ <xsd:element name="uri">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:anyURI" />
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- Binary data is base64 encoded -->
+ <xsd:element name="binary">
+ <xsd:simpleType>
+ <!-- TODO: Require encoding attribute? -->
+ <xsd:restriction base="xsd:base64Binary" />
+ </xsd:simpleType>
+ </xsd:element>
+
+ <!-- Array is a sequence of zero or more values -->
+ <xsd:element name="array">
+ <xsd:complexType>
+ <xsd:group minOccurs="0" maxOccurs="unbounded" ref="llsd-value" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- Map is a sequence of zero or more key/value pairs -->
+ <xsd:element name="map">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="key">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string" />
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:group ref="llsd-value" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml
index 136087f69b..79463b475c 100644
--- a/indra/newview/app_settings/low_graphics.xml
+++ b/indra/newview/app_settings/low_graphics.xml
@@ -5,6 +5,8 @@
<!--Default for now-->
<RenderAvatarLODFactor value="0.5"/>
<!--Default for now-->
+ <RenderAvatarPhysicsLODFactor value="0.0"/>
+ <!--Default for now-->
<RenderAvatarMaxVisible value="3"/>
<!--NO SHADERS-->
<RenderAvatarVP value="FALSE"/>
diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml
index c150a87cdf..ab1e2a2e1c 100644
--- a/indra/newview/app_settings/mid_graphics.xml
+++ b/indra/newview/app_settings/mid_graphics.xml
@@ -4,6 +4,8 @@
<RenderAvatarCloth value="FALSE"/>
<!--Default for now-->
<RenderAvatarLODFactor value="0.5"/>
+ <!--Default for now-->
+ <RenderAvatarPhysicsLODFactor value="0.75"/>
<!--NO SHADERS-->
<RenderAvatarVP value="TRUE"/>
<!--Short Range-->
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index ee01ee7833..dd85c5cb86 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" ?>
-<llsd>
+<llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="llsd.xsd">
<map>
<key>CrashHostUrl</key>
<map>
@@ -24,6 +25,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>
@@ -585,6 +608,17 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>AvatarPickerURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Avatar picker contents</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>AvatarBakedTextureUploadTimeout</key>
<map>
<key>Comment</key>
@@ -607,7 +641,28 @@
<key>Value</key>
<integer>10</integer>
</map>
-
+ <key>AvatarPhysics</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable avatar physics.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>AvatarPhysicsTest</key>
+ <map>
+ <key>Comment</key>
+ <string>Simulate continuous physics behavior on all nearby avatars.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>AvatarSex</key>
<map>
<key>Comment</key>
@@ -619,6 +674,7 @@
<key>Value</key>
<integer>0</integer>
</map>
+
<key>BackgroundYieldTime</key>
<map>
<key>Comment</key>
@@ -652,6 +708,17 @@
<key>Value</key>
<string>http://www.secondlife.com</string>
</map>
+ <key>BrowserIgnoreSSLCertErrors</key>
+ <map>
+ <key>Comment</key>
+ <string>FOR TESTING ONLY: Tell the built-in web browser to ignore SSL cert errors.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>BlockAvatarAppearanceMessages</key>
<map>
<key>Comment</key>
@@ -883,39 +950,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>BulkChangeIncludeAnimations</key>
- <map>
- <key>Comment</key>
- <string>Bulk permission changes affect animations</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>BulkChangeIncludeAnimations</key>
- <map>
- <key>Comment</key>
- <string>Bulk permission changes affect animations</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>BulkChangeIncludeAnimations</key>
- <map>
- <key>Comment</key>
- <string>Bulk permission changes affect animations</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>BulkChangeIncludeBodyParts</key>
<map>
<key>Comment</key>
@@ -1128,18 +1162,7 @@
<key>CacheLocationTopFolder</key>
<map>
<key>Comment</key>
- <string>Controls the top folder location of the local disk cache</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string />
- </map>
- <key>CacheLocationTopFolder</key>
- <map>
- <key>Comment</key>
- <string>Controls the location of the local disk cache</string>
+ <string>Controls the top folder location of the the local disk cache</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -1156,7 +1179,7 @@
<key>Type</key>
<string>U32</string>
<key>Value</key>
- <integer>20000</integer>
+ <integer>128</integer>
</map>
<key>CacheSize</key>
<map>
@@ -1343,6 +1366,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>
@@ -1818,6 +1852,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DebugShowMemory</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Total Allocated Memory</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DebugShowRenderInfo</key>
<map>
<key>Comment</key>
@@ -1840,10 +1885,21 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DebugShowTextureInfo</key>
+ <map>
+ <key>Comment</key>
+ <string>Show inertested texture info</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DebugShowTime</key>
<map>
<key>Comment</key>
- <string>Show depth buffer contents</string>
+ <string>Show time info</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -2523,7 +2579,18 @@
<key>Value</key>
<integer>10</integer>
</map>
- <key>DisableCameraConstraints</key>
+ <key>DestinationGuideURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Destination guide contents</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
+ <key>DisableCameraConstraints</key>
<map>
<key>Comment</key>
<string>Disable the normal bounds put on the camera by avatar position</string>
@@ -2545,6 +2612,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DisableExternalBrowser</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable opening an external browser.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DisableRendering</key>
<map>
<key>Comment</key>
@@ -2556,6 +2634,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DisableTextHyperlinkActions</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable highlighting and linking of URLs in XUI text boxes</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DisableVerticalSync</key>
<map>
<key>Comment</key>
@@ -2567,6 +2656,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>
@@ -2677,6 +2788,28 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>ClickActionBuyEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable click to buy actions in tool pie menu</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ClickActionPayEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable click to pay actions in tool pie menu</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>DoubleClickAutoPilot</key>
<map>
<key>Comment</key>
@@ -2699,6 +2832,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DoubleClickShowWorldMap</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable double-click to show world map from mini map</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>DragAndDropToolTipDelay</key>
<map>
<key>Comment</key>
@@ -2820,6 +2964,39 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>EnableGrab</key>
+ <map>
+ <key>Comment</key>
+ <string>Use Ctrl+mouse to grab and manipulate objects</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableAltZoom</key>
+ <map>
+ <key>Comment</key>
+ <string>Use Alt+mouse to look at and zoom in on objects</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableMouselook</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow first person perspective and mouse control of camera</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>EnableRippleWater</key>
<map>
<key>Comment</key>
@@ -2931,17 +3108,6 @@
<string>http://viewer-settings.secondlife.com</string>
</map>
<key>FPSLogFrequency</key>
- <map>
- <key>Comment</key>
- <string>Seconds between display of FPS in log (0 for never)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>60.0</real>
- </map>
- <key>FPSLogFrequency</key>
<map>
<key>Comment</key>
<string>Seconds between display of FPS in log (0 for never)</string>
@@ -3054,7 +3220,7 @@
<key>FirstRunThisInstall</key>
<map>
<key>Comment</key>
- <string>Specifies that you have not run the viewer since you installed the latest update</string>
+ <string>Specifies that you have not run the viewer since you performed a clean install</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -3062,7 +3228,18 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>FirstSelectedDisabledPopups</key>
+ <key>FirstLoginThisInstall</key>
+ <map>
+ <key>Comment</key>
+ <string>Specifies that you have not logged in with the viewer since you performed a clean install</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>FirstSelectedDisabledPopups</key>
<map>
<key>Comment</key>
<string>Return false if there is not disabled popup selected in the list of floater preferences popups</string>
@@ -3513,72 +3690,6 @@
<key>Value</key>
<real>0.5</real>
</map>
- <key>FontMonospace</key>
- <map>
- <key>Comment</key>
- <string>Name of monospace font that definitely exists (Truetype file name)</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>DejaVuSansMono.ttf</string>
- </map>
- <key>FontSansSerif</key>
- <map>
- <key>Comment</key>
- <string>Name of primary sans-serif font that definitely exists (Truetype file name)</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>MtBkLfRg.ttf</string>
- </map>
- <key>FontSansSerifBundledFallback</key>
- <map>
- <key>Comment</key>
- <string>Name of secondary sans-serif font that definitely exists (Truetype file name)</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>DejaVuSansCondensed.ttf</string>
- </map>
- <key>FontSansSerifBold</key>
- <map>
- <key>Comment</key>
- <string>Name of bold font (Truetype file name)</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>MtBdLfRg.ttf</string>
- </map>
- <key>FontSansSerifFallback</key>
- <map>
- <key>Comment</key>
- <string>Name of sans-serif font (Truetype file name)</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string />
- </map>
- <key>FontSansSerifFallbackScale</key>
- <map>
- <key>Comment</key>
- <string>Scale of fallback font relative to huge font (fraction of huge font size)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>1.0</real>
- </map>
<key>FontScreenDPI</key>
<map>
<key>Comment</key>
@@ -3590,61 +3701,6 @@
<key>Value</key>
<real>96.0</real>
</map>
- <key>FontSizeHuge</key>
- <map>
- <key>Comment</key>
- <string>Size of huge font (points, or 1/72 of an inch)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>16.0</real>
- </map>
- <key>FontSizeLarge</key>
- <map>
- <key>Comment</key>
- <string>Size of large font (points, or 1/72 of an inch)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>12.0</real>
- </map>
- <key>FontSizeMedium</key>
- <map>
- <key>Comment</key>
- <string>Size of medium font (points, or 1/72 of an inch)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>10.0</real>
- </map>
- <key>FontSizeMonospace</key>
- <map>
- <key>Comment</key>
- <string>Size of monospaced font (points, or 1/72 of an inch)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>8.1</real>
- </map>
- <key>FontSizeSmall</key>
- <map>
- <key>Comment</key>
- <string>Size of small font (points, or 1/72 of an inch)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>9.0</real>
- </map>
<key>ForceAssetFail</key>
<map>
<key>Comment</key>
@@ -3837,7 +3893,7 @@
<key>Comment</key>
<string>URL pattern for help page; arguments will be encoded; see llviewerhelp.cpp:buildHelpURL for arguments</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
@@ -3865,6 +3921,28 @@
<key>Value</key>
<string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
</map>
+ <key>WebProfileURL</key>
+ <map>
+ <key>Comment</key>
+ <string>URL for Web Profiles</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>https://my.secondlife.com/[AGENT_NAME]</string>
+ </map>
+ <key>WebProfileNonProductionURL</key>
+ <map>
+ <key>Comment</key>
+ <string>URL for Web Profiles on Non-Production grids</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>https://my-demo.secondlife.com/[AGENT_NAME]</string>
+ </map>
<key>HighResSnapshot</key>
<map>
<key>Comment</key>
@@ -3887,6 +3965,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>HostID</key>
+ <map>
+ <key>Comment</key>
+ <string>Machine identifier for hosted Second Life instances</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>HtmlHelpLastPage</key>
<map>
<key>Comment</key>
@@ -3925,7 +4014,7 @@
<key>Comment</key>
<string>Ignore all notifications so we never need user input on them.</string>
<key>Persist</key>
- <integer>0</integer>
+ <integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
@@ -3953,6 +4042,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>
@@ -4548,6 +4648,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>LocalFileSystemBrowsingEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable/disable access to the local file system via the file picker</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>LoginSRVTimeout</key>
<map>
<key>Comment</key>
@@ -4581,6 +4692,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>
@@ -4669,6 +4791,17 @@
<key>Value</key>
<string>http://map.secondlife.com.s3.amazonaws.com/</string>
</map>
+ <key>CurrentMapServerURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Current Session World map URL</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>MapShowEvents</key>
<map>
<key>Comment</key>
@@ -5164,61 +5297,6 @@
<key>Value</key>
<real>60.0</real>
</map>
- <key>MeanCollisionBump</key>
- <map>
- <key>Comment</key>
- <string>You have experienced an abuse of being bumped by an object or avatar</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>MeanCollisionPhysical</key>
- <map>
- <key>Comment</key>
- <string>You have experienced an abuse from a physical object</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>MeanCollisionPushObject</key>
- <map>
- <key>Comment</key>
- <string>You have experienced an abuse of being pushed by a scripted object</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>MeanCollisionScripted</key>
- <map>
- <key>Comment</key>
- <string>You have experienced an abuse from a scripted object</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>MeanCollisionSelected</key>
- <map>
- <key>Comment</key>
- <string>You have experienced an abuse of being pushed via a selected object</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>MediaControlFadeTime</key>
<map>
<key>Comment</key>
@@ -5893,6 +5971,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>
@@ -5995,17 +6084,6 @@
<key>OutBandwidth</key>
<map>
<key>Comment</key>
- <string>Expand render stats display</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
- <key>OutBandwidth</key>
- <map>
- <key>Comment</key>
<string>Outgoing bandwidth throttle (bps)</string>
<key>Persist</key>
<integer>1</integer>
@@ -6480,6 +6558,28 @@
<key>Value</key>
<real>0.0</real>
</map>
+ <key>QuitAfterSecondsOfAFK</key>
+ <map>
+ <key>Comment</key>
+ <string>The duration allowed after being AFK before quitting.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
+ <key>QuitOnLoginActivated</key>
+ <map>
+ <key>Comment</key>
+ <string>Quit if login page is activated (used when auto login is on and users must not be able to login manually)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RadioLandBrushAction</key>
<map>
<key>Comment</key>
@@ -6516,7 +6616,18 @@
<key>MediaBrowserWindowLimit</key>
<map>
<key>Comment</key>
- <string>Maximum number of media brower windows that can be open at once (0 for no limit)</string>
+ <string>Maximum number of media brower windows that can be open at once in the media browser floater (0 for no limit)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>WebContentWindowLimit</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum number of web brower windows that can be open at once in the Web content floater (0 for no limit)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6711,6 +6822,17 @@
<key>Value</key>
<integer>12</integer>
</map>
+ <key>RenderAvatarPhysicsLODFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Controls level of detail of avatar physics (such as breast physics).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <integer>1.0</integer>
+ </map>
<key>RenderAvatarVP</key>
<map>
<key>Comment</key>
@@ -7737,17 +7859,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>RenderFastUI</key>
- <map>
- <key>Comment</key>
- <string>[NOT USED]</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>RenderFlexTimeFactor</key>
<map>
<key>Comment</key>
@@ -8263,6 +8374,28 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>RenderTrackerBeacon</key>
+ <map>
+ <key>Comment</key>
+ <string>Display tracking arrow and beacon to target avatar, teleport destination</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </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>
@@ -8384,6 +8517,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RenderVBOMappingDisable</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable VBO glMapBufferARB</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RenderUseStreamVBO</key>
<map>
<key>Comment</key>
@@ -8439,6 +8583,17 @@
<key>Value</key>
<integer>512</integer>
</map>
+ <key>RenderParcelSelection</key>
+ <map>
+ <key>Comment</key>
+ <string>Display selected parcel outline</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RotateRight</key>
<map>
<key>Comment</key>
@@ -8527,6 +8682,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>ScriptsCanShowUI</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow LSL calls (such as LLMapDestination) to spawn viewer UI</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>SecondLifeEnterprise</key>
<map>
<key>Comment</key>
@@ -9891,6 +10057,17 @@
<key>Value</key>
<real>500.0</real>
</map>
+ <key>UpdaterMaximumBandwidth</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum allowable downstream bandwidth for updater service (kilo bits per second)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>500.0</real>
+ </map>
<key>ToolTipDelay</key>
<map>
<key>Comment</key>
@@ -10991,7 +11168,62 @@
<key>Value</key>
<integer>15</integer>
</map>
- <key>UploadBakedTexOld</key>
+ <key>UpdaterServiceSetting</key>
+ <map>
+ <key>Comment</key>
+ <string>Configure updater service.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>3</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 +11377,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>
@@ -11220,8 +11463,6 @@
<key>Type</key>
<string>LLSD</string>
<key>Value</key>
- <map>
- </map>
</map>
<key>VFSOldSize</key>
<map>
@@ -11300,32 +11541,32 @@
<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</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</integer>
</map>
- <key>VertexShaderEnable</key>
+ <key>VerboseLogs</key>
<map>
<key>Comment</key>
- <string>Enable/disable all GLSL shaders (debug)</string>
+ <string>Display source file and line number for each log item for debugging purposes</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -11333,10 +11574,10 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>VivoxAutoPostCrashDumps</key>
+ <key>VertexShaderEnable</key>
<map>
<key>Comment</key>
- <string>If true, SLVoice will automatically send crash dumps directly to Vivox.</string>
+ <string>Enable/disable all GLSL shaders (debug)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -11344,27 +11585,27 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>VivoxDebugLevel</key>
+ <key>VivoxAutoPostCrashDumps</key>
<map>
<key>Comment</key>
- <string>Logging level to use when launching the vivox daemon</string>
+ <string>If true, SLVoice will automatically send crash dumps directly to Vivox.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
- <string>String</string>
+ <string>Boolean</string>
<key>Value</key>
- <string>-1</string>
+ <integer>0</integer>
</map>
- <key>VivoxDebugSIPURIHostName</key>
+ <key>VivoxDebugLevel</key>
<map>
<key>Comment</key>
- <string>Hostname portion of vivox SIP URIs (empty string for the default).</string>
+ <string>Logging level to use when launching the vivox daemon</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string></string>
+ <string>-1</string>
</map>
<key>VivoxDebugSIPURIHostName</key>
<map>
@@ -11421,6 +11662,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>VoiceCallsRejectAll</key>
+ <map>
+ <key>Comment</key>
+ <string>Silently reject all incoming voice calls.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>VoiceDisableMic</key>
+ <map>
+ <key>Comment</key>
+ <string>Completely disable the ability to open the mic.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>VoiceEffectExpiryWarningTime</key>
<map>
<key>Comment</key>
@@ -11729,6 +11992,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>WindowFullScreen</key>
+ <map>
+ <key>Comment</key>
+ <string>SL viewer window full screen</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>WindowHeight</key>
<map>
<key>Comment</key>
@@ -11795,10 +12069,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>
@@ -11861,6 +12135,17 @@
<key>Value</key>
<real>0.40000000596</real>
</map>
+ <key>moapbeacon</key>
+ <map>
+ <key>Comment</key>
+ <string>Beacon / Highlight media on a prim sources</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>particlesbeacon</key>
<map>
<key>Comment</key>
@@ -12026,6 +12311,7 @@
<key>Comment</key>
<string>Maximum texture width for user uploaded textures</string>
<key>Persist</key>
+ <integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
@@ -12065,6 +12351,7 @@
<key>Value</key>
<array>
<string>snapshot</string>
+ <string>postcard</string>
<string>mini_map</string>
</array>
</map>
@@ -12132,7 +12419,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>600.0</real>
+ <real>1200.0</real>
</map>
<key>SidePanelHintTimeout</key>
<map>
@@ -12145,5 +12432,214 @@
<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>
+ <key>SessionSettingsFile</key>
+ <map>
+ <key>Comment</key>
+ <string>Settings that are a applied per session (not saved).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
+ <key>UserSessionSettingsFile</key>
+ <map>
+ <key>Comment</key>
+ <string>User settings that are a applied per session (not saved).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
+ <key>OpenSidePanelsInFloaters</key>
+ <map>
+ <key>Comment</key>
+ <string>If true, will always open side panel contents in a floater.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>AvatarInspectorTooltipDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Seconds before displaying avatar inspector tooltip</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.35</real>
+ </map>
+ <key>ObjectInspectorTooltipDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Seconds before displaying object inspector tooltip</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.35</real>
+ </map>
+ <key>SLURLTeleportDirectly</key>
+ <map>
+ <key>Comment</key>
+ <string>Clicking on a slurl will teleport you directly instead of opening places panel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableClassifieds</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable creation of new classified ads from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableGroupInfo</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable viewing and editing of group info from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnablePicks</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable editing of picks from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableWorldMap</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable opening world map from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableAvatarPay</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable paying other avatars from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableVoiceCall</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable voice calls from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableAvatarShare</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable sharing from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>SearchFromAddressBar</key>
+ <map>
+ <key>Comment</key>
+ <string>Can enter search queries into navigation address bar</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>LogInventoryDecline</key>
+ <map>
+ <key>Comment</key>
+ <string>Log in system chat whenever an inventory offer is declined</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>UseHTTPInventory</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow use of http inventory transfers instead of UDP</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ClickToWalk</key>
+ <map>
+ <key>Comment</key>
+ <string>Click in world to walk to location</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ShowOfferedInventory</key>
+ <map>
+ <key>Comment</key>
+ <string>Show inventory window with last inventory offer selected when receiving inventory from other users.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml
index aa5b301959..079a54f957 100644
--- a/indra/newview/app_settings/settings_files.xml
+++ b/indra/newview/app_settings/settings_files.xml
@@ -1,148 +1,64 @@
-<llsd>
- <map>
- <key>Locations</key>
- <map>
- <!--
- The Locations LLSD block specifies the usage pattern of
- the settings file types
- Each location is represented by a LLSD containing the following values:
- PathIndex = hard coded path indicies.
- Files = map of files to load
- Each file can have:
- Requirement = level of necessity for loading.
- 0 ( or Req. no key) = do not load
- 1 = required, fail if not found
- NameFromSetting = Use the given setting to specify the name. Not valid for
- "Default"
- -->
- <key>Comment</key>
- <string>List location from which to load files, and the rules about loading those files.</string>
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>LLSD</string>
- <key>Value</key>
- <map>
- <key>Default</key>
- <map>
- <key>PathIndex</key>
- <integer>2</integer>
- <key>Files</key>
- <map>
- <key>Global</key>
- <map>
- <key>Name</key>
- <string>settings.xml</string>
- <key>Requirement</key>
- <integer>1</integer>
- </map>
- <key>PerAccount</key>
- <map>
- <key>Name</key>
- <string>settings_per_account.xml</string>
- <key>Requirement</key>
- <integer>1</integer>
- </map>
- <key>CrashSettings</key>
- <map>
- <key>Name</key>
- <string>settings_crash_behavior.xml</string>
- <key>Requirement</key>
- <integer>1</integer>
- </map>
- <key>Warnings</key>
- <map>
- <key>Name</key>
- <string>ignorable_dialogs.xml</string>
- <key>Requirement</key>
- <integer>1</integer>
- </map>
- </map>
- </map>
- <key>User</key>
- <map>
- <key>PathIndex</key>
- <integer>1</integer>
- <key>Files</key>
- <map>
- <key>Global</key>
- <map>
- <key>Name</key>
- <string>settings.xml</string>
- <key>NameFromSetting</key>
- <string>ClientSettingsFile</string>
- </map>
- <key>CrashSettings</key>
- <map>
- <key>Name</key>
- <string>settings_crash_behavior.xml</string>
- </map>
- <key>Warnings</key>
- <map>
- <key>Name</key>
- <string>ignorable_dialogs.xml</string>
- <key>NameFromSetting</key>
- <string>WarningSettingsFile</string>
- </map>
- </map>
- </map>
- <key>Account</key>
- <map>
- <key>PathIndex</key>
- <integer>3</integer>
- <key>Files</key>
- <map>
- <key>PerAccount</key>
- <map>
- <key>Name</key>
- <string>settings_per_account.xml</string>
- <key>NameFromSetting</key>
- <string>PerAccountSettingsFile</string>
- </map>
- </map>
- </map>
- <key>DefaultSkin</key>
- <map>
- <key>PathIndex</key>
- <integer>17</integer>
- <key>Files</key>
- <map>
- <key>Skinning</key>
- <map>
- <key>Name</key>
- <string>colors.xml</string>
- </map>
- </map>
- </map>
- <key>CurrentSkin</key>
- <map>
- <key>PathIndex</key>
- <integer>10</integer>
- <key>Files</key>
- <map>
- <key>Skinning</key>
- <map>
- <key>Name</key>
- <string>colors.xml</string>
- </map>
- </map>
- </map>
- <key>UserSkin</key>
- <map>
- <key>PathIndex</key>
- <integer>14</integer>
- <key>Files</key>
- <map>
- <key>Skinning</key>
- <map>
- <key>Name</key>
- <string>colors.xml</string>
- <key>NameFromSetting</key>
- <string>SkinningSettingsFile</string>
- </map>
- </map>
- </map>
- </map>
- </map>
- </map>
-</llsd>
+<settings_files>
+ <group name="Default"
+ path_index="2">
+ <file name="Global"
+ file_name="settings.xml"
+ required="true"/>
+ <file name="PerAccount"
+ file_name="settings_per_account.xml"
+ required="true"/>
+ <file name="CrashSettings"
+ file_name="settings_crash_behavior.xml"
+ required="true"/>
+ <file name="Warnings"
+ file_name="ignorable_dialogs.xml"
+ required="true"/>
+ </group>
+ <group name="User"
+ path_index="1">
+ <file name="Global"
+ file_name="settings.xml"
+ file_name_setting="ClientSettingsFile"/>
+ <file name="CrashSettings"
+ file_name="settings_crash_behavior"/>
+ <file name="Warnings"
+ file_name="ignorable_dialogs.xml"
+ file_name_setting="WarningSettingsFile"/>
+ </group>
+ <group name="Account"
+ path_index="3">
+ <file name="PerAccount"
+ file_name="settings_per_account.xml"
+ file_name_setting="PerAccountSettingsFile"/>
+ </group>
+ <group name="Session"
+ path_index="2">
+ <file name="Global"
+ file_name="session.xml"
+ file_name_setting="SessionSettingsFile"
+ persistent="false"/>
+ </group>
+ <group name="UserSession"
+ path_index="1">
+ <file name="Global"
+ file_name="session.xml"
+ file_name_setting="UserSessionSettingsFile"
+ persistent="false"/>
+ </group>
+ <group name="DefaultSkin"
+ path_index="17">
+ <file name="Skinning"
+ file_name="colors.xml"/>
+ </group>
+ <group name="CurrentSkin"
+ path_index="10">
+ <file name="Skinning"
+ file_name="colors.xml"/>
+ </group>
+ <group name="UserSkin"
+ path_index="14">
+ <file name="Skinning"
+ file_name="colors.xml"
+ file_name_setting="SkinningSettingsFile"/>
+ </group>
+</settings_files> \ No newline at end of file
diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml
new file mode 100644
index 0000000000..03656f2a53
--- /dev/null
+++ b/indra/newview/app_settings/settings_minimal.xml
@@ -0,0 +1,406 @@
+<llsd>
+ <map>
+ <key>ChannelBottomPanelMargin</key>
+ <map>
+ <key>Comment</key>
+ <string>Space from a lower toast to the Bottom Tray</string>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>2</integer>
+ </map>
+ <key>ClickActionBuyEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable click to buy actions in tool pie menu</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ClickActionPayEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable click to pay actions in tool pie menu</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableGrab</key>
+ <map>
+ <key>Comment</key>
+ <string>Use Ctrl+mouse to grab and manipulate objects</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableMouselook</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow first person perspective and mouse control of camera</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableVoiceChat</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable talking to other residents with a microphone</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>HelpURLFormat</key>
+ <map>
+ <key>Comment</key>
+ <string>URL pattern for help page; arguments will be encoded; see llviewerhelp.cpp:buildHelpURL for arguments</string>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/damballah/howto/index.html?topic=[TOPIC]</string>
+ </map>
+ <key>PreferredMaturity</key>
+ <map>
+ <key>Comment</key>
+ <string>Setting for the user&apos;s preferred maturity level (consts in indra_constants.h)</string>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>21</integer>
+ </map>
+ <key>RenderTrackerBeacon</key>
+ <map>
+ <key>Comment</key>
+ <string>Display tracking arrow and beacon to target avatar, teleport destination</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ShowScriptErrors</key>
+ <map>
+ <key>Comment</key>
+ <string>Show script errors</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ShowScriptErrorsLocation</key>
+ <map>
+ <key>Comment</key>
+ <string>Show script error in chat or window</string>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>SkinCurrent</key>
+ <map>
+ <key>Comment</key>
+ <string>The currently selected skin.</string>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>minimal</string>
+ </map>
+ <key>UseExternalBrowser</key>
+ <map>
+ <key>Comment</key>
+ <string>Use default browser when opening web pages instead of in-world browser.</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>VoiceCallsRejectAll</key>
+ <map>
+ <key>Comment</key>
+ <string>Silently reject all incoming voice calls.</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>VoiceDisableMic</key>
+ <map>
+ <key>Comment</key>
+ <string>Completely disable the ability to open the mic.</string>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ScriptsCanShowUI</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow LSL calls (such as LLMapDestination) to spawn viewer UI</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ChatFontSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Size of chat text in chat console (0 = small, 1 = big, 2 = extra large)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>AvatarPickerHintTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of seconds to wait before telling resident about avatar picker.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.0</real>
+ </map>
+ <key>RenderShowGroupTitleAll</key>
+ <map>
+ <key>Comment</key>
+ <string>Show group titles in name labels</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>OpenSidePanelsInFloaters</key>
+ <map>
+ <key>Comment</key>
+ <string>If true, will always open side panel contents in a floater.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>AvatarInspectorTooltipDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Seconds before displaying avatar inspector tooltip</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
+ <key>AFKTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>
+ Time before automatically setting AFK (away from keyboard) mode (seconds, 0=never).
+ Valid values are: 0, 120, 300, 600, 1800
+ </string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <real>0</real>
+ </map>
+ <key>SLURLTeleportDirectly</key>
+ <map>
+ <key>Comment</key>
+ <string>Clicking on a slurl will teleport you directly instead of opening places panel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>EnableClassifieds</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable creation of new classified ads</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableGroupInfo</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable viewing and editing of group info.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnablePicks</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable editing of picks</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableWorldMap</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable opening world map from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableAvatarPay</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable paying other avatars from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableVoiceCall</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable voice calls from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>EnableAvatarShare</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable sharing from web link</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>DoubleClickShowWorldMap</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable double-click to show world map from mini map</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</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>0</integer>
+ </map>
+ <key>SearchFromAddressBar</key>
+ <map>
+ <key>Comment</key>
+ <string>Can enter search queries into navigation address bar</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>DestinationGuideURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Destination guide contents</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/damballah/guide.html</string>
+ </map>
+ <key>AvatarPickerURL</key>
+ <map>
+ <key>Comment</key>
+ <string>Avatar picker contents</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/damballah/avatars.html</string>
+ </map>
+ <key>LogInventoryDecline</key>
+ <map>
+ <key>Comment</key>
+ <string>Log in system chat whenever an inventory offer is declined</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>UseHTTPInventory</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow use of http inventory transfers instead of UDP</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ClickToWalk</key>
+ <map>
+ <key>Comment</key>
+ <string>Click in world to walk to location</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowOfferedInventory</key>
+ <map>
+ <key>Comment</key>
+ <string>Show inventory window with last inventory offer selected when receiving inventory from other users.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ </map>
+</llsd>
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index dc76a4e518..8efec1cff0 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
@@ -150,6 +160,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>ShowFavoritesOnLogin</key>
+ <map>
+ <key>Comment</key>
+ <string>Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<!-- End of back compatibility settings -->
</map>
</llsd>
diff --git a/indra/newview/app_settings/shaders/shader_heirarchy.txt b/indra/newview/app_settings/shaders/shader_hierarchy.txt
index d8bbf69b38..d8bbf69b38 100644
--- a/indra/newview/app_settings/shaders/shader_heirarchy.txt
+++ b/indra/newview/app_settings/shaders/shader_hierarchy.txt
diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml
index e7dce3b989..e1f3ca5769 100644
--- a/indra/newview/app_settings/ultra_graphics.xml
+++ b/indra/newview/app_settings/ultra_graphics.xml
@@ -4,6 +4,8 @@
<RenderAvatarCloth value="TRUE"/>
<!--Default for now-->
<RenderAvatarLODFactor value="1.0"/>
+ <!--Default for now-->
+ <RenderAvatarPhysicsLODFactor value="1.0"/>
<!--NO SHADERS-->
<RenderAvatarVP value="TRUE"/>
<!--Short Range-->
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index a9b4ff02c5..4585ba658c 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -612,7 +612,7 @@
id="36"
group="0"
name="Shoulders"
- label="Shoulders"
+ label="Shoulders"
wearable="shape"
edit_group="shape_torso"
edit_group_order="4"
@@ -4040,26 +4040,6 @@
scale="0.0 0.0 0.01"
pos="0 0 -0.01"/>
</param_morph>
-
- </param>
-
- <param
- id="507"
- group="0"
- sex="female"
- name="Breast_Gravity"
- label="Breast Buoyancy"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="7"
- label_min="Less Gravity"
- label_max="More Gravity"
- value_default="0"
- value_min="-1.5"
- value_max="2"
- camera_elevation=".3"
- camera_distance=".8">
- <param_morph />
</param>
<param
@@ -4113,25 +4093,6 @@
</param>
<param
- id="684"
- group="0"
- sex="female"
- name="Breast_Female_Cleavage"
- label="Breast Cleavage"
- wearable="shape"
- edit_group="shape_torso"
- edit_group_order="8"
- label_min="Separate"
- label_max="Join"
- value_default="0"
- value_min="-.3"
- value_max="1.3"
- camera_elevation=".3"
- camera_distance=".8">
- <param_morph />
- </param>
-
- <param
id="685"
group="0"
sex="male"
@@ -4328,8 +4289,52 @@
</param>
<!--
+ #############
+ # physics morphs (not user controlled)
+ #############
+ -->
+ <param
+ id="1200"
+ group="1"
+ sex="female"
+ name="Breast_Gravity"
+ wearable="shape"
+ edit_group="driven"
+ value_default="0"
+ value_min="-1.5"
+ value_max="2">
+ <param_morph />
+ </param>
+
+ <param
+ id="1201"
+ group="1"
+ sex="female"
+ name="Breast_Female_Cleavage"
+ wearable="shape"
+ edit_group="driven"
+ value_default="0"
+ value_min="-.3"
+ value_max="1.3">
+ <param_morph />
+ </param>
+
+ <param
+ id="1204"
+ group="1"
+ name="Belly_Physics_Torso_UpDown_Driven"
+ wearable="physics"
+ edit_group="driven"
+ value_default="0"
+ value_min="-1"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <!--
#end morph targets
-->
+
</mesh>
<mesh
@@ -4390,6 +4395,7 @@
<param_morph />
</param>
+
<param
id="151"
group="1"
@@ -4829,8 +4835,49 @@
</param>
<!--
+ #############
+ # physics morphs (not user controlled)
+ #############
+ -->
+ <param
+ id="1202"
+ group="1"
+ name="Belly_Physics_Legs_UpDown_Driven"
+ wearable="physics"
+ edit_group="driven"
+ value_min="-1"
+ value_max="1">
+ <param_morph />
+ </param>
+
+
+ <param
+ id="1205"
+ group="1"
+ name="Butt_Physics_UpDown_Driven"
+ wearable="physics"
+ edit_group="driven"
+ value_default="0">
+ <param_morph />
+ </param>
+
+ <param
+ id="1206"
+ group="1"
+ name="Butt_Physics_LeftRight_Driven"
+ wearable="physics"
+ edit_group="driven"
+ value_default="0"
+ value_min="-2"
+ value_max="2">
+ <param_morph />
+ </param>
+
+
+ <!--
#end morph targets
-->
+
</mesh>
<mesh
@@ -9074,12 +9121,13 @@ render_pass="bump">
<!-- =========================================================== -->
<driver_parameters>
+
<param
id="828"
group="0"
name="Loose Upper Clothing"
label="Shirt Fit"
- show_simple="true"
+ show_simple="true"
wearable="shirt"
edit_group="shirt"
edit_group_order="4"
@@ -11631,6 +11679,524 @@ render_pass="bump">
</param_driver>
</param>
+ <!-- ==PHYSICS PARAMETERS======================================= -->
+
+ <param
+ id="507"
+ group="0"
+ sex="female"
+ name="Breast_Physics_UpDown_Controller"
+ label="Breast Physics UpDown Controller"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="7"
+ value_default="0"
+ value_min="-1.5"
+ value_max="2"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver>
+ <driven
+ id="1200" />
+ </param_driver>
+ </param>
+
+ <param
+ id="684"
+ group="0"
+ sex="female"
+ name="Breast_Physics_InOut_Controller"
+ label="Breast Physics InOut Controller"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="8"
+ value_default="0"
+ value_min="-.3"
+ value_max="1.3">
+ <param_driver>
+ <driven
+ id="1201" />
+ </param_driver>
+ </param>
+
+ <param
+ id="1120"
+ group="1"
+ wearable="physics"
+ name="Belly_Physics_UpDown_Controller"
+ label="Belly Physics UpDown Controller"
+ value_min="-1"
+ value_max="1"
+ value_default="0">
+ <param_driver>
+ <driven
+ id="1202" />
+ <driven
+ id="1203" />
+ <driven
+ id="1204" />
+ </param_driver>
+ </param>
+
+ <param
+ id="1100"
+ group="1"
+ wearable="shape"
+ name="Butt_Physics_UpDown_Controller"
+ label="Butt Physics UpDown Controller"
+ value_min="-1"
+ value_max="1"
+ value_default="0">
+ <param_driver>
+ <driven
+ id="1205" />
+ </param_driver>
+ </param>
+
+ <param
+ id="1101"
+ group="1"
+ wearable="shape"
+ name="Butt_Physics_LeftRight_Controller"
+ label="Butt Physics LeftRight Controller"
+ value_min="-1"
+ value_max="1"
+ value_default="0">
+ <param_driver>
+ <driven
+ id="1206" />
+ </param_driver>
+ </param>
+
+ <param
+ id="1110"
+ group="0"
+ sex="female"
+ name="Breast_Physics_Mass"
+ label="Breast Physics Mass"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".1"
+ value_min=".1"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1111"
+ group="0"
+ sex="female"
+ name="Breast_Physics_Smoothing"
+ label="Breast Physics Smoothing"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default="2"
+ value_min="1"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1112"
+ group="0"
+ sex="female"
+ name="Breast_Physics_Gravity"
+ label="Breast Physics Gravity"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default="0"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+
+ <param
+ id="1113"
+ group="0"
+ sex="female"
+ name="Breast_Physics_UpDown_Max_Velocity"
+ label="Breast Physics UpDown Max Speed"
+ wearable="physics"
+ edit_group="physics_breasts_updown"
+ value_default="0"
+ value_min="0"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1114"
+ group="0"
+ sex="female"
+ name="Breast_Physics_UpDown_Spring"
+ label="Breast Physics UpDown Spring"
+ wearable="physics"
+ edit_group="physics_breasts_updown"
+ value_default=".1"
+ value_min="0"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1115"
+ group="0"
+ sex="female"
+ name="Breast_Physics_UpDown_Gain"
+ label="Breast Physics UpDown Gain"
+ wearable="physics"
+ edit_group="physics_breasts_updown"
+ value_default="10"
+ value_min="1"
+ value_max="100">
+ <param_driver />
+ </param>
+ <param
+ id="1116"
+ group="0"
+ sex="female"
+ name="Breast_Physics_UpDown_Damping"
+ label="Breast Physics UpDown Damping"
+ wearable="physics"
+ edit_group="physics_breasts_updown"
+ value_default=".05"
+ value_min="0"
+ value_max=".1"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+ <param
+ id="1117"
+ group="0"
+ sex="female"
+ name="Breast_Physics_UpDown_Drag"
+ label="Breast Physics UpDown Drag"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".15"
+ value_min="0"
+ value_max=".5">
+ <param_driver />
+ </param>
+
+ <param
+ id="1118"
+ group="0"
+ sex="female"
+ name="Breast_Physics_InOut_Max_Velocity"
+ label="Breast Physics InOut Max Speed"
+ wearable="physics"
+ edit_group="physics_breasts_inout"
+ value_default="0"
+ value_min="0"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1119"
+ group="0"
+ sex="female"
+ name="Breast_Physics_InOut_Spring"
+ label="Breast Physics InOut Spring"
+ wearable="physics"
+ edit_group="physics_breasts_inout"
+ value_default=".1"
+ value_min="0"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1120"
+ group="0"
+ sex="female"
+ name="Breast_Physics_InOut_Gain"
+ label="Breast Physics InOut Gain"
+ wearable="physics"
+ edit_group="physics_breasts_inout"
+ value_default="10"
+ value_min="1"
+ value_max="100">
+ <param_driver />
+ </param>
+ <param
+ id="1121"
+ group="0"
+ sex="female"
+ name="Breast_Physics_InOut_Damping"
+ label="Breast Physics InOut Damping"
+ wearable="physics"
+ edit_group="physics_breasts_inout"
+ value_default=".05"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+ <param
+ id="1122"
+ group="0"
+ sex="female"
+ name="Breast_Physics_InOut_Drag"
+ label="Breast Physics InOut Drag"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".15"
+ value_min="0"
+ value_max=".5">
+ <param_driver />
+ </param>
+
+ <param
+ id="1130"
+ group="0"
+ name="Belly_Physics_Mass"
+ label="Belly Physics Mass"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".1"
+ value_min=".1"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1131"
+ group="0"
+ name="Belly_Physics_Smoothing"
+ label="Belly Physics Smoothing"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default="2"
+ value_min="1"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1132"
+ group="0"
+ name="Belly_Physics_Gravity"
+ label="Belly Physics Gravity"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default="0"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+ <param
+ id="1133"
+ group="0"
+ name="Belly_Physics_UpDown_Max_Velocity"
+ label="Belly Physics UpDown Max Speed"
+ wearable="physics"
+ edit_group="physics_belly_updown"
+ value_default="0"
+ value_min="0"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1134"
+ group="0"
+ name="Belly_Physics_UpDown_Spring"
+ label="Belly Physics UpDown Spring"
+ wearable="physics"
+ edit_group="physics_belly_updown"
+ value_default=".1"
+ value_min="0"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1135"
+ group="0"
+ name="Belly_Physics_UpDown_Gain"
+ label="Belly Physics UpDown Gain"
+ wearable="physics"
+ edit_group="physics_belly_updown"
+ value_default="10"
+ value_min="1"
+ value_max="100">
+ <param_driver />
+ </param>
+ <param
+ id="1136"
+ group="0"
+ name="Belly_Physics_UpDown_Damping"
+ label="Belly Physics UpDown Damping"
+ wearable="physics"
+ edit_group="physics_belly_updown"
+ value_default=".05"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+ <param
+ id="1137"
+ group="0"
+ name="Belly_Physics_UpDown_Drag"
+ label="Belly Physics UpDown Drag"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".15"
+ value_min="0"
+ value_max=".5">
+ <param_driver />
+ </param>
+
+ <param
+ id="1140"
+ group="0"
+ name="Butt_Physics_Mass"
+ label="Butt Physics Mass"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".1"
+ value_min=".1"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1141"
+ group="0"
+ name="Butt_Physics_Smoothing"
+ label="Butt Physics Smoothing"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default="2"
+ value_min="1"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1142"
+ group="0"
+ name="Butt_Physics_Gravity"
+ label="Butt Physics Gravity"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default="0"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+ <param
+ id="1143"
+ group="0"
+ name="Butt_Physics_UpDown_Max_Velocity"
+ label="Butt Physics UpDown Max Speed"
+ wearable="physics"
+ edit_group="physics_butt_updown"
+ value_default="0"
+ value_min="0"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1144"
+ group="0"
+ name="Butt_Physics_UpDown_Spring"
+ label="Butt Physics UpDown Spring"
+ wearable="physics"
+ edit_group="physics_butt_updown"
+ value_default=".1"
+ value_min="0"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1145"
+ group="0"
+ name="Butt_Physics_UpDown_Gain"
+ label="Butt Physics UpDown Gain"
+ wearable="physics"
+ edit_group="physics_butt_updown"
+ value_default="10"
+ value_min="1"
+ value_max="100">
+ <param_driver />
+ </param>
+ <param
+ id="1146"
+ group="0"
+ name="Butt_Physics_UpDown_Damping"
+ label="Butt Physics UpDown Damping"
+ wearable="physics"
+ edit_group="physics_butt_updown"
+ value_default=".05"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+ <param
+ id="1147"
+ group="0"
+ name="Butt_Physics_UpDown_Drag"
+ label="Butt Physics UpDown Drag"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".15"
+ value_min="0"
+ value_max=".5">
+ <param_driver />
+ </param>
+
+ <param
+ id="1148"
+ group="0"
+ name="Butt_Physics_LeftRight_Max_Velocity"
+ label="Butt Physics LeftRight Max Speed"
+ wearable="physics"
+ edit_group="physics_butt_leftright"
+ value_default="0"
+ value_min="0"
+ value_max="10">
+ <param_driver />
+ </param>
+ <param
+ id="1149"
+ group="0"
+ name="Butt_Physics_LeftRight_Spring"
+ label="Butt Physics LeftRight Spring"
+ wearable="physics"
+ edit_group="physics_butt_leftright"
+ value_default=".1"
+ value_min="0"
+ value_max="1">
+ <param_driver />
+ </param>
+ <param
+ id="1150"
+ group="0"
+ name="Butt_Physics_LeftRight_Gain"
+ label="Butt Physics LeftRight Gain"
+ wearable="physics"
+ edit_group="physics_butt_leftright"
+ value_default="10"
+ value_min="1"
+ value_max="100">
+ <param_driver />
+ </param>
+ <param
+ id="1151"
+ group="0"
+ name="Butt_Physics_LeftRight_Damping"
+ label="Butt Physics LeftRight Damping"
+ wearable="physics"
+ edit_group="physics_butt_leftright"
+ value_default=".05"
+ value_min="0"
+ value_max=".1">
+ <param_driver />
+ </param>
+ <param
+ id="1152"
+ group="0"
+ name="Butt_Physics_LeftRight_Drag"
+ label="Butt Physics LeftRight Drag"
+ wearable="physics"
+ edit_group="physics_advanced"
+ value_default=".15"
+ value_min="0"
+ value_max=".5">
+ <param_driver />
+ </param>
+
</driver_parameters>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index d69842d5f1..15ad330418 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -26,6 +26,7 @@ list all
RenderAnisotropic 1 1
RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
+RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxVisible 1 12
RenderAvatarVP 1 1
RenderCubeMap 1 1
@@ -42,6 +43,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
@@ -70,6 +72,7 @@ list Low
RenderAnisotropic 1 0
RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0
+RenderAvatarPhysicsLODFactor 1 0
RenderAvatarMaxVisible 1 3
RenderAvatarVP 1 0
RenderFarClip 1 64
@@ -80,6 +83,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
@@ -99,6 +103,7 @@ list Mid
RenderAnisotropic 1 0
RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0.5
+RenderAvatarPhysicsLODFactor 1 0.75
RenderAvatarVP 1 1
RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
@@ -108,6 +113,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
@@ -126,15 +132,17 @@ list High
RenderAnisotropic 1 1
RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
+RenderAvatarPhysicsLODFactor 1 0.9
RenderAvatarVP 1 1
RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
+RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderUseImpostors 1 1
RenderVolumeLODFactor 1 1.125
@@ -162,6 +170,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..a2cd4b834c 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
@@ -131,9 +134,10 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
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..3ad7f4e892 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
@@ -130,9 +133,10 @@ RenderGlowResolutionPow 1 9
RenderLightingDetail 1 1
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
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..38e6bb1e5e 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
@@ -132,9 +135,10 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
RenderObjectBump 1 1
-RenderReflectionDetail 1 2
+RenderReflectionDetail 1 0
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..5ebec1563e 100644
--- a/indra/newview/generate_breakpad_symbols.py
+++ b/indra/newview/generate_breakpad_symbols.py
@@ -1,29 +1,31 @@
#!/usr/bin/env python
-# @file generate_breakpad_symbols.py
-# @author Brad Kittenbrink <brad@lindenlab.com>
-# @brief Simple tool for generating google_breakpad symbol information
-# for the crash reporter.
-#
-# $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$
+"""\
+@file generate_breakpad_symbols.py
+@author Brad Kittenbrink <brad@lindenlab.com>
+@brief Simple tool for generating google_breakpad symbol information
+ for the crash reporter.
+
+$LicenseInfo:firstyear=2010&license=viewerlgpl$
+Second Life Viewer Source Code
+Copyright (C) 2010-2011, Linden Research, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation;
+version 2.1 of the License only.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+$/LicenseInfo$
+"""
import collections
@@ -31,6 +33,7 @@ import fnmatch
import itertools
import operator
import os
+import re
import sys
import shlex
import subprocess
@@ -45,8 +48,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 +129,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..7d908df5ce 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -56,14 +56,15 @@
#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"
#include "lltoolmgr.h"
#include "lltrans.h"
+#include "llurlentry.h"
#include "llviewercontrol.h"
#include "llviewerdisplay.h"
#include "llviewerjoystick.h"
@@ -218,7 +219,10 @@ LLAgent::LLAgent() :
mFirstLogin(FALSE),
mGenderChosen(FALSE),
- mAppearanceSerialNum(0)
+ mAppearanceSerialNum(0),
+
+ mMouselookModeInSignal(NULL),
+ mMouselookModeOutSignal(NULL)
{
for (U32 i = 0; i < TOTAL_CONTROLS; i++)
{
@@ -269,6 +273,9 @@ LLAgent::~LLAgent()
{
cleanup();
+ delete mMouselookModeInSignal;
+ delete mMouselookModeOutSignal;
+
// *Note: this is where LLViewerCamera::getInstance() used to be deleted.
}
@@ -637,9 +644,16 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
// Update all of the regions.
LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal);
}
+
+ // Pass new region along to metrics components that care about this level of detail.
+ LLAppViewer::metricsUpdateRegion(regionp->getHandle());
}
mRegionp = regionp;
+ // Pass the region host to LLUrlEntryParcel to resolve parcel name
+ // with a server request.
+ LLUrlEntryParcel::setRegionHost(getRegionHost());
+
// Must shift hole-covering water object locations because local
// coordinate frame changed.
LLWorld::getInstance()->updateWaterObjects();
@@ -1726,15 +1740,17 @@ void LLAgent::endAnimationUpdateUI()
LLBottomTray::getInstance()->onMouselookModeOut();
- LLSideTray::getInstance()->getButtonsPanel()->setVisible(TRUE);
- LLSideTray::getInstance()->updateSidetrayVisibility();
-
LLPanelStandStopFlying::getInstance()->setVisible(TRUE);
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
LLFloaterCamera::onLeavingMouseLook();
+ if (mMouselookModeOutSignal)
+ {
+ (*mMouselookModeOutSignal)();
+ }
+
// Only pop if we have pushed...
if (TRUE == mViewsPushed)
{
@@ -1828,9 +1844,6 @@ void LLAgent::endAnimationUpdateUI()
LLBottomTray::getInstance()->onMouselookModeIn();
- LLSideTray::getInstance()->getButtonsPanel()->setVisible(FALSE);
- LLSideTray::getInstance()->updateSidetrayVisibility();
-
LLPanelStandStopFlying::getInstance()->setVisible(FALSE);
// clear out camera lag effect
@@ -1843,6 +1856,11 @@ void LLAgent::endAnimationUpdateUI()
mViewsPushed = TRUE;
+ if (mMouselookModeInSignal)
+ {
+ (*mMouselookModeInSignal)();
+ }
+
// hide all floaters except the mini map
#if 0 // Use this once all floaters are registered
@@ -1902,7 +1920,6 @@ void LLAgent::endAnimationUpdateUI()
}
}
}
-
}
else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
{
@@ -1934,6 +1951,18 @@ void LLAgent::endAnimationUpdateUI()
gAgentCamera.updateLastCamera();
}
+boost::signals2::connection LLAgent::setMouselookModeInCallback( const camera_signal_t::slot_type& cb )
+{
+ if (!mMouselookModeInSignal) mMouselookModeInSignal = new camera_signal_t();
+ return mMouselookModeInSignal->connect(cb);
+}
+
+boost::signals2::connection LLAgent::setMouselookModeOutCallback( const camera_signal_t::slot_type& cb )
+{
+ if (!mMouselookModeOutSignal) mMouselookModeOutSignal = new camera_signal_t();
+ return mMouselookModeOutSignal->connect(cb);
+}
+
//-----------------------------------------------------------------------------
// heardChat()
//-----------------------------------------------------------------------------
@@ -2452,7 +2481,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..896408c0dd 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -33,11 +33,14 @@
#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"
#include "llslurl.h"
+#include <boost/signals2.hpp>
+
extern const BOOL ANIMATE;
extern const U8 AGENT_STATE_TYPING; // Typing indication
extern const U8 AGENT_STATE_EDITING; // Set when agent has objects selected
@@ -409,7 +412,13 @@ public:
BOOL getCustomAnim() const { return mCustomAnim; }
void setCustomAnim(BOOL anim) { mCustomAnim = anim; }
+ typedef boost::signals2::signal<void ()> camera_signal_t;
+ boost::signals2::connection setMouselookModeInCallback( const camera_signal_t::slot_type& cb );
+ boost::signals2::connection setMouselookModeOutCallback( const camera_signal_t::slot_type& cb );
+
private:
+ camera_signal_t* mMouselookModeInSignal;
+ camera_signal_t* mMouselookModeOutSignal;
BOOL mCustomAnim; // Current animation is ANIM_AGENT_CUSTOMIZE ?
LLAnimPauseRequest mPauseRequest;
BOOL mViewsPushed; // Keep track of whether or not we have pushed views
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 68e408d3e4..f01d5ff1f5 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"))
@@ -2038,7 +2041,7 @@ void LLAgentCamera::resetCamera()
//-----------------------------------------------------------------------------
void LLAgentCamera::changeCameraToMouselook(BOOL animate)
{
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ if (!gSavedSettings.getBOOL("EnableMouselook") || LLViewerJoystick::getInstance()->getOverrideCamera())
{
return;
}
@@ -2692,6 +2695,9 @@ void LLAgentCamera::lookAtLastChat()
new_camera_pos -= delta_pos * 0.4f;
new_camera_pos += left * 0.3f;
new_camera_pos += up * 0.2f;
+
+ setFocusOnAvatar(FALSE, FALSE);
+
if (chatter_av->mHeadp)
{
setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter());
@@ -2702,7 +2708,6 @@ void LLAgentCamera::lookAtLastChat()
setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter());
mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
}
- setFocusOnAvatar(FALSE, TRUE);
}
else
{
@@ -2722,9 +2727,10 @@ void LLAgentCamera::lookAtLastChat()
new_camera_pos += left * 0.3f;
new_camera_pos += up * 0.2f;
+ setFocusOnAvatar(FALSE, FALSE);
+
setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter());
mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
- setFocusOnAvatar(FALSE, TRUE);
}
}
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 055be4cae2..d426afb17c 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -821,7 +821,7 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index)
}
}
-U32 LLAgentWearables::getWearableIndex(LLWearable *wearable)
+U32 LLAgentWearables::getWearableIndex(const LLWearable *wearable) const
{
if (wearable == NULL)
{
@@ -2045,8 +2045,9 @@ void LLAgentWearables::editWearable(const LLUUID& item_id)
return;
}
+ const BOOL disable_camera_switch = LLWearableType::getDisableCameraSwitch(wearable->getType());
LLPanel* panel = LLSideTray::getInstance()->getPanel("sidepanel_appearance");
- LLSidepanelAppearance::editWearable(wearable, panel);
+ LLSidepanelAppearance::editWearable(wearable, panel, disable_camera_switch);
}
// Request editing the item after it gets worn.
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index d7e77a5a5b..3ef50f14da 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -124,7 +124,7 @@ public:
void setWearableOutfit(const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove);
void setWearableName(const LLUUID& item_id, const std::string& new_name);
void addLocalTextureObject(const LLWearableType::EType wearable_type, const LLVOAvatarDefines::ETextureIndex texture_type, U32 wearable_index);
- U32 getWearableIndex(LLWearable *wearable);
+ U32 getWearableIndex(const LLWearable *wearable) const;
protected:
void setWearableFinal(LLInventoryItem* new_item, LLWearable* new_wearable, bool do_append = false);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index ed5e8ceee3..1cf552e42c 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1300,8 +1300,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
return false;
}
- // Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes).
- return getCanMakeFolderIntoOutfit(outfit_cat_id);
+ // Check whether the outfit contains any wearables we aren't wearing already (STORM-702).
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true);
+ gInventory.collectDescendentsIf(outfit_cat_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_worn);
+ return items.size() > 0;
}
void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
@@ -2204,12 +2212,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 +2255,6 @@ void LLAppearanceMgr::updateIsDirty()
return;
}
}
-
- mOutfitIsDirty = false;
}
}
@@ -2440,6 +2445,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 +2646,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();
@@ -2943,3 +2955,35 @@ void wear_multiple(const uuid_vec_t& ids, bool replace)
}
}
+// SLapp for easy-wearing of a stock (library) avatar
+//
+class LLWearFolderHandler : public LLCommandHandler
+{
+public:
+ // not allowed from outside the app
+ LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { }
+
+ bool handle(const LLSD& tokens, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ LLPointer<LLInventoryCategory> category = new LLInventoryCategory(query_map["folder_id"],
+ LLUUID::null,
+ LLFolderType::FT_CLOTHING,
+ "Quick Appearance");
+ LLSD::UUID folder_uuid = query_map["folder_id"].asUUID();
+ if ( gInventory.getCategory( folder_uuid ) != NULL )
+ {
+ LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false);
+
+ // *TODOw: This may not be necessary if initial outfit is chosen already -- josh
+ gAgent.setGenderChosen(TRUE);
+ }
+
+ // release avatar picker keyboard focus
+ gFocusMgr.setKeyboardFocus( NULL );
+
+ return true;
+ }
+};
+
+LLWearFolderHandler gWearFolderHandler;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ba14c248aa..cfb5853cfd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1,4 +1,4 @@
-/**
+ /**
* @file llappviewer.cpp
* @brief The LLAppViewer class definitions
*
@@ -30,6 +30,7 @@
// Viewer includes
#include "llversioninfo.h"
+#include "llversionviewer.h"
#include "llfeaturemanager.h"
#include "lluictrlfactory.h"
#include "lltexteditor.h"
@@ -43,6 +44,7 @@
#include "llagentwearables.h"
#include "llwindow.h"
#include "llviewerstats.h"
+#include "llviewerstatsrecorder.h"
#include "llmd5.h"
#include "llpumpio.h"
#include "llmimetypes.h"
@@ -79,9 +81,12 @@
#include "llfeaturemanager.h"
#include "llurlmatch.h"
#include "lltextutil.h"
+#include "lllogininstance.h"
+#include "llprogressview.h"
#include "llweb.h"
#include "llsecondlifeurls.h"
+#include "llupdaterservice.h"
// Linden library includes
#include "llavatarnamecache.h"
@@ -89,6 +94,7 @@
#include "llmemory.h"
#include "llprimitive.h"
#include "llurlaction.h"
+#include "llurlentry.h"
#include "llvfile.h"
#include "llvfsthread.h"
#include "llvolumemgr.h"
@@ -190,11 +196,14 @@
#include "llparcel.h"
#include "llavatariconctrl.h"
#include "llgroupiconctrl.h"
+#include "llviewerassetstats.h"
// Include for security api initialization
#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
@@ -328,10 +337,58 @@ void init_default_trans_args()
const char *VFS_DATA_FILE_BASE = "data.db2.x.";
const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
+
+struct SettingsFile : public LLInitParam::Block<SettingsFile>
+{
+ Mandatory<std::string> name;
+ Optional<std::string> file_name;
+ Optional<bool> required,
+ persistent;
+ Optional<std::string> file_name_setting;
+
+ SettingsFile()
+ : name("name"),
+ file_name("file_name"),
+ required("required", false),
+ persistent("persistent", true),
+ file_name_setting("file_name_setting")
+ {}
+};
+
+struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
+{
+ Mandatory<std::string> name;
+ Mandatory<S32> path_index;
+ Multiple<SettingsFile> files;
+
+ SettingsGroup()
+ : name("name"),
+ path_index("path_index"),
+ files("file")
+ {}
+};
+
+struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
+{
+ Multiple<SettingsGroup> groups;
+
+ SettingsFiles()
+ : groups("group")
+ {}
+};
+
static std::string gWindowTitle;
LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
+//----------------------------------------------------------------------------
+// Metrics logging control constants
+//----------------------------------------------------------------------------
+static const F32 METRICS_INTERVAL_DEFAULT = 600.0;
+static const F32 METRICS_INTERVAL_QA = 30.0;
+static F32 app_metrics_interval = METRICS_INTERVAL_DEFAULT;
+static bool app_metrics_qa_mode = false;
+
void idle_afk_check()
{
// check idle timers
@@ -441,6 +498,7 @@ static void settings_to_globals()
LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor");
+ LLVOAvatar::sPhysicsLODFactor = gSavedSettings.getF32("RenderAvatarPhysicsLODFactor");
LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
// clamp auto-open time to some minimum usable value
@@ -456,8 +514,6 @@ static void settings_to_globals()
gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
-
- LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
}
static void settings_modify()
@@ -501,6 +557,9 @@ static void settings_modify()
gSavedSettings.setBOOL("VectorizeEnable", FALSE );
gSavedSettings.setU32("VectorizeProcessor", 0 );
gSavedSettings.setBOOL("VectorizeSkin", FALSE);
+
+ // disable fullscreen mode, unsupported
+ gSavedSettings.setBOOL("WindowFullScreen", FALSE);
#endif
}
@@ -509,16 +568,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 +587,7 @@ public:
os.close();
}
+
};
//virtual
@@ -580,7 +634,9 @@ 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()),
+ mSettingsLocationList(NULL)
{
if(NULL != sInstance)
{
@@ -590,10 +646,16 @@ LLAppViewer::LLAppViewer() :
setupErrorHandling();
sInstance = this;
gLoggedInTime.stop();
+
+ LLLoginInstance::instance().setUpdaterService(mUpdater.get());
}
LLAppViewer::~LLAppViewer()
{
+ delete mSettingsLocationList;
+
+ LLLoginInstance::instance().setUpdaterService(0);
+
destroyMainloopTimeout();
// If we got to this destructor somehow, the app didn't hang.
@@ -648,18 +710,40 @@ bool LLAppViewer::init()
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
+#if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::initClass();
+#endif
+
// *NOTE:Mani - LLCurl::initClass is not thread safe.
// Called before threads are created.
LLCurl::initClass();
LLMachineID::init();
+
+ {
+ // Viewer metrics initialization
+ static LLCachedControl<bool> metrics_submode(gSavedSettings,
+ "QAModeMetrics",
+ false,
+ "Enables QA features (logging, faster cycling) for metrics collector");
+
+ if (metrics_submode)
+ {
+ app_metrics_qa_mode = true;
+ app_metrics_interval = METRICS_INTERVAL_QA;
+ }
+ LLViewerAssetStatsFF::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,12 +887,18 @@ bool LLAppViewer::init()
return 1;
}
+ // Initialize the repeater service.
+ LLMainLoopRepeater::instance().start();
+
//
// Initialize the window
//
gGLActive = TRUE;
initWindow();
+ // initWindow also initializes the Feature List, so now we can initialize this global.
+ LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
+
// call all self-registered classes
LLInitClassList::instance().fireCallbacks();
@@ -817,16 +907,22 @@ bool LLAppViewer::init()
gGLManager.getGLInfo(gDebugInfo);
gGLManager.printGLInfoString();
- //load key settings
- bind_keyboard_functions();
-
// Load Default bindings
- if (!gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"keys.ini")))
+ std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
+ gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+
+
+ if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
{
- LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
+ std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
+ gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+ gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+ if (!gViewerKeyboard.loadBindings(key_bindings_file))
+ {
+ LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
+ }
}
- // Load Custom bindings (override defaults)
- gViewerKeyboard.loadBindings(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"custom_keys.ini"));
// If we don't have the right GL requirements, exit.
if (!gGLManager.mHasRequirements && !gNoRender)
@@ -899,7 +995,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;
@@ -943,6 +1040,8 @@ bool LLAppViewer::init()
LLAgentLanguage::init();
+
+
return true;
}
@@ -974,13 +1073,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 +1091,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 +1340,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");
@@ -1275,6 +1402,21 @@ bool LLAppViewer::mainLoop()
return true;
}
+void LLAppViewer::flushVFSIO()
+{
+ while (1)
+ {
+ S32 pending = LLVFSThread::updateClass(0);
+ pending += LLLFSThread::updateClass(0);
+ if (!pending)
+ {
+ break;
+ }
+ llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
+ ms_sleep(100);
+ }
+}
+
bool LLAppViewer::cleanup()
{
// workaround for DEV-35406 crash on shutdown
@@ -1300,16 +1442,6 @@ bool LLAppViewer::cleanup()
}
mPlugins.clear();
- //----------------------------------------------
- //this test code will be removed after the test
- //test manual call stack tracer
- if(gSavedSettings.getBOOL("QAMode"))
- {
- LLError::LLCallStacks::print() ;
- }
- //end of the test code
- //----------------------------------------------
-
//flag all elements as needing to be destroyed immediately
// to ensure shutdown order
LLMortician::setZealous(TRUE);
@@ -1329,11 +1461,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 +1480,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;
@@ -1409,17 +1546,7 @@ bool LLAppViewer::cleanup()
llinfos << "Cache files removed" << llendflush;
// Wait for any pending VFS IO
- while (1)
- {
- S32 pending = LLVFSThread::updateClass(0);
- pending += LLLFSThread::updateClass(0);
- if (!pending)
- {
- break;
- }
- llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
- ms_sleep(100);
- }
+ flushVFSIO();
llinfos << "Shutting down Views" << llendflush;
// Destroy the UI
@@ -1594,8 +1721,8 @@ bool LLAppViewer::cleanup()
// Delete workers first
// shotdown all worker threads before deleting them in case of co-dependencies
- sTextureCache->shutdown();
sTextureFetch->shutdown();
+ sTextureCache->shutdown();
sImageDecodeThread->shutdown();
sTextureFetch->shutDownTextureCacheThread() ;
@@ -1614,22 +1741,20 @@ 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() ;
+
+#if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::cleanupClass();
+#endif
llinfos << "Cleaning up Media and Textures" << llendflush;
@@ -1648,7 +1773,10 @@ bool LLAppViewer::cleanup()
#ifndef LL_RELEASE_FOR_DOWNLOAD
llinfos << "Auditing VFS" << llendl;
- gVFS->audit();
+ if(gVFS)
+ {
+ gVFS->audit();
+ }
#endif
llinfos << "Misc Cleanup" << llendflush;
@@ -1666,6 +1794,8 @@ bool LLAppViewer::cleanup()
LLWatchdog::getInstance()->cleanup();
+ LLViewerAssetStatsFF::cleanup();
+
llinfos << "Shutting down message system" << llendflush;
end_messaging_system();
@@ -1689,8 +1819,12 @@ bool LLAppViewer::cleanup()
llinfos << "File launched." << llendflush;
}
+ LLMainLoopRepeater::instance().stop();
+
ll_close_fail_log();
+ MEM_TRACK_RELEASE
+
llinfos << "Goodbye!" << llendflush;
// return 0;
@@ -1730,13 +1864,16 @@ bool LLAppViewer::initThreads()
// Image decoding
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
- LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
+ LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
+ sImageDecodeThread,
+ enable_threads && true,
+ app_metrics_qa_mode);
LLImage::initClass();
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
{
LLFastTimer::sLogLock = new LLMutex(NULL);
- mFastTimerLogThread = new LLFastTimerLogThread();
+ mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
mFastTimerLogThread->start();
}
@@ -1786,85 +1923,80 @@ bool LLAppViewer::initLogging()
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
bool set_defaults)
{
- // Find and vet the location key.
- if(!mSettingsLocationList.has(location_key))
+ if (!mSettingsLocationList)
{
- llerrs << "Requested unknown location: " << location_key << llendl;
- return false;
+ llerrs << "Invalid settings location list" << llendl;
}
- LLSD location = mSettingsLocationList.get(location_key);
-
- if(!location.has("PathIndex"))
+ LLControlGroup* global_settings = LLControlGroup::getInstance(sGlobalSettingsName);
+ for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
+ it != end_it;
+ ++it)
{
- llerrs << "Settings location is missing PathIndex value. Settings cannot be loaded." << llendl;
- return false;
- }
- ELLPath path_index = (ELLPath)(location.get("PathIndex").asInteger());
- if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
- {
- llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
- return false;
- }
+ // skip settings groups that aren't the one we requested
+ if (it->name() != location_key) continue;
- // Iterate through the locations list of files.
- LLSD files = location.get("Files");
- for(LLSD::map_iterator itr = files.beginMap(); itr != files.endMap(); ++itr)
- {
- std::string settings_group = (*itr).first;
- llinfos << "Attempting to load settings for the group " << settings_group
- << " - from location " << location_key << llendl;
-
- if(!LLControlGroup::getInstance(settings_group))
+ ELLPath path_index = (ELLPath)it->path_index();
+ if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
{
- llwarns << "No matching settings group for name " << settings_group << llendl;
- continue;
+ llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
+ return false;
}
- LLSD file = (*itr).second;
-
- std::string full_settings_path;
- if(file.has("NameFromSetting"))
+ LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
+ for (file_it = it->files.begin(), end_file_it = it->files.end();
+ file_it != end_file_it;
+ ++file_it)
{
- std::string custom_name_setting = file.get("NameFromSetting");
- // *NOTE: Regardless of the group currently being lodaed,
- // this setting is always read from the Global settings.
- if(LLControlGroup::getInstance(sGlobalSettingsName)->controlExists(custom_name_setting))
+ llinfos << "Attempting to load settings for the group " << file_it->name()
+ << " - from location " << location_key << llendl;
+
+ LLControlGroup* settings_group = LLControlGroup::getInstance(file_it->name);
+ if(!settings_group)
{
- std::string file_name =
- LLControlGroup::getInstance(sGlobalSettingsName)->getString(custom_name_setting);
- full_settings_path = file_name;
+ llwarns << "No matching settings group for name " << file_it->name() << llendl;
+ continue;
}
- }
- if(full_settings_path.empty())
- {
- std::string file_name = file.get("Name");
- full_settings_path = gDirUtilp->getExpandedFilename(path_index, file_name);
- }
+ std::string full_settings_path;
- int requirement = 0;
- if(file.has("Requirement"))
- {
- requirement = file.get("Requirement").asInteger();
- }
-
- if(!LLControlGroup::getInstance(settings_group)->loadFromFile(full_settings_path, set_defaults))
- {
- if(requirement == 1)
+ if (file_it->file_name_setting.isProvided()
+ && global_settings->controlExists(file_it->file_name_setting))
{
- llwarns << "Error: Cannot load required settings file from: "
- << full_settings_path << llendl;
- return false;
+ // try to find filename stored in file_name_setting control
+ full_settings_path = global_settings->getString(file_it->file_name_setting);
+ if (!gDirUtilp->fileExists(full_settings_path))
+ {
+ // search in default path
+ full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
+ }
}
else
{
- llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
+ // by default, use specified file name
+ full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file_it->file_name());
+ }
+
+ if(settings_group->loadFromFile(full_settings_path, set_defaults, file_it->persistent))
+ { // success!
+ llinfos << "Loaded settings file " << full_settings_path << llendl;
+ }
+ else
+ { // failed to load
+ if(file_it->required)
+ {
+ llerrs << "Error: Cannot load required settings file from: " << full_settings_path << llendl;
+ return false;
+ }
+ else
+ {
+ // only complain if we actually have a filename at this point
+ if (!full_settings_path.empty())
+ {
+ llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
+ }
+ }
}
- }
- else
- {
- llinfos << "Loaded settings file " << full_settings_path << llendl;
}
}
@@ -1874,18 +2006,25 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
const std::string& file)
{
- if(mSettingsLocationList.has(location_key))
+ for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
+ it != end_it;
+ ++it)
{
- LLSD location = mSettingsLocationList.get(location_key);
- if(location.has("Files"))
+ if (it->name() == location_key)
{
- LLSD files = location.get("Files");
- if(files.has(file) && files[file].has("Name"))
+ LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
+ for (file_it = it->files.begin(), end_file_it = it->files.end();
+ file_it != end_file_it;
+ ++file_it)
{
- return files.get(file).get("Name").asString();
+ if (file_it->name() == file)
+ {
+ return file_it->file_name;
+ }
}
}
}
+
return std::string();
}
@@ -1898,14 +2037,29 @@ bool LLAppViewer::initConfiguration()
{
//Load settings files list
std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
- LLControlGroup settings_control("SettingsFiles");
- llinfos << "Loading settings file list " << settings_file_list << llendl;
- if (0 == settings_control.loadFromFile(settings_file_list))
+ //LLControlGroup settings_control("SettingsFiles");
+ //llinfos << "Loading settings file list " << settings_file_list << llendl;
+ //if (0 == settings_control.loadFromFile(settings_file_list))
+ //{
+ // llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
+ //}
+
+ LLXMLNodePtr root;
+ BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL);
+ if (!success)
{
llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
}
- mSettingsLocationList = settings_control.getLLSD("Locations");
+ mSettingsLocationList = new SettingsFiles();
+
+ LLXUIParser parser;
+ parser.readXUI(root, *mSettingsLocationList, settings_file_list);
+
+ if (!mSettingsLocationList->validateBlock())
+ {
+ llerrs << "Invalid settings file list " << settings_file_list << llendl;
+ }
// The settings and command line parsing have a fragile
// order-of-operation:
@@ -1935,8 +2089,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
@@ -2016,9 +2168,44 @@ bool LLAppViewer::initConfiguration()
// - load overrides from user_settings
loadSettingsFromDirectory("User");
+
+ if (gSavedSettings.getBOOL("FirstRunThisInstall"))
+ {
+ gSavedSettings.setString("SessionSettingsFile", "settings_minimal.xml");
+ gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
+ }
+
+ if (clp.hasOption("sessionsettings"))
+ {
+ std::string session_settings_filename = clp.getOption("sessionsettings")[0];
+ gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
+ llinfos << "Using session settings filename: "
+ << session_settings_filename << llendl;
+ }
+ loadSettingsFromDirectory("Session");
+
+ if (clp.hasOption("usersessionsettings"))
+ {
+ std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];
+ gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
+ llinfos << "Using user session settings filename: "
+ << user_session_settings_filename << llendl;
+
+ }
+ loadSettingsFromDirectory("UserSession");
+
// - 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 +2255,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 +2270,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"))
@@ -2131,7 +2337,7 @@ bool LLAppViewer::initConfiguration()
if (clp.hasOption("nonotifications"))
{
- gSavedSettings.setBOOL("IgnoreAllNotifications", TRUE);
+ gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false);
}
if (clp.hasOption("debugsession"))
@@ -2178,8 +2384,8 @@ bool LLAppViewer::initConfiguration()
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
{
// hack to force the skin to default.
- //gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
- gDirUtilp->setSkinFolder("default");
+ gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
+ //gDirUtilp->setSkinFolder("default");
}
mYieldTime = gSavedSettings.getS32("YieldTime");
@@ -2323,6 +2529,163 @@ bool LLAppViewer::initConfiguration()
return true; // Config was successful.
}
+namespace {
+ // *TODO - decide if there's a better place for these functions.
+ // do we need a file llupdaterui.cpp or something? -brad
+
+ void apply_update_callback(LLSD const & notification, LLSD const & response)
+ {
+ lldebugs << "LLUpdate user response: " << response << llendl;
+ if(response["OK_okcancelbuttons"].asBoolean())
+ {
+ llinfos << "LLUpdate restarting viewer" << llendl;
+ static const bool install_if_ready = true;
+ // *HACK - this lets us launch the installer immediately for now
+ LLUpdaterService().startChecking(install_if_ready);
+ }
+ }
+
+ void apply_update_ok_callback(LLSD const & notification, LLSD const & response)
+ {
+ llinfos << "LLUpdate restarting viewer" << llendl;
+ static const bool install_if_ready = true;
+ // *HACK - this lets us launch the installer immediately for now
+ LLUpdaterService().startChecking(install_if_ready);
+ }
+
+ void on_update_downloaded(LLSD const & data)
+ {
+ std::string notification_name;
+ void (*apply_callback)(LLSD const &, LLSD const &) = NULL;
+
+ if(data["required"].asBoolean())
+ {
+ if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT)
+ {
+ // The user never saw the progress bar.
+ apply_callback = &apply_update_ok_callback;
+ notification_name = "RequiredUpdateDownloadedVerboseDialog";
+ }
+ else if(LLStartUp::getStartupState() < STATE_WORLD_INIT)
+ {
+ // The user is logging in but blocked.
+ apply_callback = &apply_update_ok_callback;
+ notification_name = "RequiredUpdateDownloadedDialog";
+ }
+ else
+ {
+ // The user is already logged in; treat like an optional update.
+ apply_callback = &apply_update_callback;
+ notification_name = "DownloadBackgroundTip";
+ }
+ }
+ else
+ {
+ apply_callback = &apply_update_callback;
+ if(LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ // CHOP-262 we need to use a different notification
+ // method prior to login.
+ notification_name = "DownloadBackgroundDialog";
+ }
+ else
+ {
+ notification_name = "DownloadBackgroundTip";
+ }
+ }
+
+ LLSD substitutions;
+ substitutions["VERSION"] = data["version"];
+
+ // truncate version at the rightmost '.'
+ std::string version_short(data["version"]);
+ size_t short_length = version_short.rfind('.');
+ if (short_length != std::string::npos)
+ {
+ version_short.resize(short_length);
+ }
+
+ LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]");
+ relnotes_url.setArg("[VERSION_SHORT]", version_short);
+
+ // *TODO thread the update service's response through to this point
+ std::string const & channel = LLVersionInfo::getChannel();
+ boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free);
+
+ relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
+ relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
+ substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString();
+
+ LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback);
+ }
+
+ void install_error_callback(LLSD const & notification, LLSD const & response)
+ {
+ LLAppViewer::instance()->forceQuit();
+ }
+
+ bool notify_update(LLSD const & evt)
+ {
+ std::string notification_name;
+ switch (evt["type"].asInteger())
+ {
+ case LLUpdaterService::DOWNLOAD_COMPLETE:
+ on_update_downloaded(evt);
+ break;
+ case LLUpdaterService::INSTALL_ERROR:
+ if(evt["required"].asBoolean()) {
+ LLNotificationsUtil::add("FailedRequiredUpdateInstall", LLSD(), LLSD(), &install_error_callback);
+ } else {
+ LLNotificationsUtil::add("FailedUpdateInstall");
+ }
+ break;
+ default:
+ break;
+ }
+
+ // let others also handle this event by default
+ return false;
+ }
+
+ bool on_bandwidth_throttle(LLUpdaterService * updater, LLSD const & evt)
+ {
+ updater->setBandwidthLimit(evt.asInteger() * (1024/8));
+ return false; // Let others receive this event.
+ };
+};
+
+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);
+ mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8));
+ gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()->
+ connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2));
+ if(gSavedSettings.getU32("UpdaterServiceSetting"))
+ {
+ 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)
{
@@ -2382,7 +2745,7 @@ bool LLAppViewer::initWindow()
VIEWER_WINDOW_CLASSNAME,
gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
- FALSE, ignorePixelDepth);
+ gSavedSettings.getBOOL("WindowFullScreen"), ignorePixelDepth);
// Need to load feature table before cheking to start watchdog.
const S32 NEVER_SUBMIT_REPORT = 2;
@@ -2483,15 +2846,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 +2880,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 +2961,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 +2983,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();
@@ -2733,8 +3104,10 @@ void LLAppViewer::handleViewerCrash()
pApp->removeMarkerFile(false);
}
+#if LL_SEND_CRASH_REPORTS
// Call to pure virtual, handled by platform specific llappviewer instance.
pApp->handleCrashReporting();
+#endif
return;
}
@@ -2791,35 +3164,32 @@ void LLAppViewer::initMarkerFile()
std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
-
if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB) && !anotherInstanceRunning())
{
gLastExecEvent = LAST_EXEC_FROZE;
LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL;
}
-
if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
{
- LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << LL_ENDL;
gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
+ LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ LLAPRFile::remove(logout_marker_file);
}
if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
{
- llinfos << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << llendl;
if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
else gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
+ LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ LLAPRFile::remove(llerror_marker_file);
}
if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
{
- LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << LAST_EXEC_OTHER_CRASH << LL_ENDL;
if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
else gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+ LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+ LLAPRFile::remove(error_marker_file);
}
-
- LLAPRFile::remove(logout_marker_file);
- LLAPRFile::remove(llerror_marker_file);
- LLAPRFile::remove(error_marker_file);
-
+
// No new markers if another instance is running.
if(anotherInstanceRunning())
{
@@ -2869,6 +3239,23 @@ void LLAppViewer::forceQuit()
LLApp::setQuitting();
}
+//TODO: remove
+void LLAppViewer::fastQuit(S32 error_code)
+{
+ // finish pending transfers
+ flushVFSIO();
+ // let sim know we're logging out
+ sendLogoutRequest();
+ // flush network buffers by shutting down messaging system
+ end_messaging_system();
+ // figure out the error code
+ S32 final_error_code = error_code ? error_code : (S32)isError();
+ // this isn't a crash
+ removeMarkerFile();
+ // get outta here
+ _exit(final_error_code);
+}
+
void LLAppViewer::requestQuit()
{
llinfos << "requestQuit" << llendl;
@@ -2877,11 +3264,21 @@ void LLAppViewer::requestQuit()
if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
{
+ // If we have a region, make some attempt to send a logout request first.
+ // This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes.
+ if(region)
+ {
+ sendLogoutRequest();
+ }
+
// Quit immediately
forceQuit();
return;
}
+ // Try to send metrics back to the grid
+ metricsSend(!gDisconnected);
+
LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
effectp->setPositionGlobal(gAgent.getPositionGlobal());
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
@@ -2916,9 +3313,23 @@ static bool finish_quit(const LLSD& notification, const LLSD& response)
}
static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_quit);
+static bool switch_standard_skin_and_quit(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ if (option == 0)
+ {
+ gSavedSettings.setString("SessionSettingsFile", "");
+ LLAppViewer::instance()->requestQuit();
+ }
+ return false;
+}
+
+static LLNotificationFunctorRegistration standard_skin_quit_reg("SwitchToStandardSkinAndQuit", switch_standard_skin_and_quit);
+
void LLAppViewer::userQuit()
{
- if (gDisconnected)
+ if (gDisconnected || gViewerWindow->getProgressView()->getVisible())
{
requestQuit();
}
@@ -2941,12 +3352,12 @@ void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit);
}
-void LLAppViewer::forceExit(S32 arg)
+// case where we need the viewer to exit without any need for notifications
+void LLAppViewer::earlyExitNoNotify()
{
- removeMarkerFile();
-
- // *FIX:Mani - This kind of exit hardly seems appropriate.
- exit(arg);
+ llwarns << "app_early_exit with no notification: " << llendl;
+ gDoDisconnect = TRUE;
+ finish_early_exit( LLSD(), LLSD() );
}
void LLAppViewer::abortQuit()
@@ -2990,7 +3401,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 +3620,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;
@@ -3434,6 +3845,7 @@ void LLAppViewer::loadNameCache()
// display names cache
std::string filename =
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+ LL_INFOS("AvNameCache") << filename << LL_ENDL;
llifstream name_cache_stream(filename);
if(name_cache_stream.is_open())
{
@@ -3542,6 +3954,18 @@ void LLAppViewer::idle()
}
}
+ // debug setting to quit after N seconds of being AFK - 0 to never do this
+ F32 qas_afk = gSavedSettings.getF32("QuitAfterSecondsOfAFK");
+ if (qas_afk > 0.f)
+ {
+ // idle time is more than setting
+ if ( gAwayTriggerTimer.getElapsedTimeF32() > qas_afk )
+ {
+ // go ahead and just quit gracefully
+ LLAppViewer::instance()->requestQuit();
+ }
+ }
+
// Must wait until both have avatar object and mute list, so poll
// here.
request_initial_instant_messages();
@@ -3647,6 +4071,11 @@ void LLAppViewer::idle()
llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
gObjectList.mNumUnknownUpdates = 0;
}
+
+ // ViewerMetrics FPS piggy-backing on the debug timer.
+ // The 5-second interval is nice for this purpose. If the object debug
+ // bit moves or is disabled, please give this a suitable home.
+ LLViewerAssetStatsFF::record_fps_main(gFPSClamped);
}
}
@@ -3689,6 +4118,18 @@ void LLAppViewer::idle()
gInventory.idleNotifyObservers();
}
+ // Metrics logging (LLViewerAssetStats, etc.)
+ {
+ static LLTimer report_interval;
+
+ // *TODO: Add configuration controls for this
+ if (report_interval.getElapsedTimeF32() >= app_metrics_interval)
+ {
+ metricsSend(! gDisconnected);
+ report_interval.reset();
+ }
+ }
+
if (gDisconnected)
{
return;
@@ -3978,7 +4419,10 @@ void LLAppViewer::sendLogoutRequest()
gLogoutMaxTime = LOGOUT_REQUEST_TIME;
mLogoutRequestSent = TRUE;
- LLVoiceClient::getInstance()->leaveChannel();
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->leaveChannel();
+ }
//Set internal status variables and marker files
gLogoutInProgress = TRUE;
@@ -4225,13 +4669,20 @@ 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();
cleanup_xfer_manager();
gDisconnected = TRUE;
+
+ // Pass the connection state to LLUrlEntryParcel not to attempt
+ // parcel info requests while disconnected.
+ LLUrlEntryParcel::setDisconnected(gDisconnected);
}
void LLAppViewer::forceErrorLLError()
@@ -4339,7 +4790,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();
@@ -4399,6 +4850,35 @@ void LLAppViewer::loadEventHostModule(S32 listen_port)
return;
}
+ LL_INFOS("eventhost") << "Found lleventhost at '" << dso_path << "'" << LL_ENDL;
+#if ! defined(LL_WINDOWS)
+ {
+ std::string outfile("/tmp/lleventhost.file.out");
+ std::string command("file '" + dso_path + "' > '" + outfile + "' 2>&1");
+ int rc = system(command.c_str());
+ if (rc != 0)
+ {
+ LL_WARNS("eventhost") << command << " ==> " << rc << ':' << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("eventhost") << command << ':' << LL_ENDL;
+ }
+ {
+ std::ifstream reader(outfile.c_str());
+ std::string line;
+ while (std::getline(reader, line))
+ {
+ size_t len = line.length();
+ if (len && line[len-1] == '\n')
+ line.erase(len-1);
+ LL_INFOS("eventhost") << line << LL_ENDL;
+ }
+ }
+ remove(outfile.c_str());
+ }
+#endif // LL_WINDOWS
+
apr_dso_handle_t * eventhost_dso_handle = NULL;
apr_pool_t * eventhost_dso_memory_pool = NULL;
@@ -4407,13 +4887,13 @@ void LLAppViewer::loadEventHostModule(S32 listen_port)
apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
dso_path.c_str(),
eventhost_dso_memory_pool);
- ll_apr_assert_status(rv);
+ llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
llassert_always(eventhost_dso_handle != NULL);
int (*ll_plugin_start_func)(LLSD const &) = NULL;
rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start");
- ll_apr_assert_status(rv);
+ llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
llassert_always(ll_plugin_start_func != NULL);
LLSD args;
@@ -4445,7 +4925,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 +4993,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;
@@ -4583,3 +5065,75 @@ bool LLAppViewer::getMasterSystemAudioMute()
{
return gSavedSettings.getBOOL("MuteAudio");
}
+
+//----------------------------------------------------------------------------
+// Metrics-related methods (static and otherwise)
+//----------------------------------------------------------------------------
+
+/**
+ * LLViewerAssetStats collects data on a per-region (as defined by the agent's
+ * location) so we need to tell it about region changes which become a kind of
+ * hidden variable/global state in the collectors. For collectors not running
+ * on the main thread, we need to send a message to move the data over safely
+ * and cheaply (amortized over a run).
+ */
+void LLAppViewer::metricsUpdateRegion(U64 region_handle)
+{
+ if (0 != region_handle)
+ {
+ LLViewerAssetStatsFF::set_region_main(region_handle);
+ if (LLAppViewer::sTextureFetch)
+ {
+ // Send a region update message into 'thread1' to get the new region.
+ LLAppViewer::sTextureFetch->commandSetRegion(region_handle);
+ }
+ else
+ {
+ // No 'thread1', a.k.a. TextureFetch, so update directly
+ LLViewerAssetStatsFF::set_region_thread1(region_handle);
+ }
+ }
+}
+
+
+/**
+ * Attempts to start a multi-threaded metrics report to be sent back to
+ * the grid for consumption.
+ */
+void LLAppViewer::metricsSend(bool enable_reporting)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ if (LLAppViewer::sTextureFetch)
+ {
+ LLViewerRegion * regionp = gAgent.getRegion();
+
+ if (enable_reporting && regionp)
+ {
+ std::string caps_url = regionp->getCapability("ViewerMetrics");
+
+ // Make a copy of the main stats to send into another thread.
+ // Receiving thread takes ownership.
+ LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStatsMain));
+
+ // Send a report request into 'thread1' to get the rest of the data
+ // and provide some additional parameters while here.
+ LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
+ gAgentSessionID,
+ gAgentID,
+ main_stats);
+ main_stats = 0; // Ownership transferred
+ }
+ else
+ {
+ LLAppViewer::sTextureFetch->commandDataBreak();
+ }
+ }
+
+ // Reset even if we can't report. Rather than gather up a huge chunk of
+ // data, we'll keep to our sampling interval and retain the data
+ // resolution in time.
+ gViewerAssetStatsMain->reset();
+}
+
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index fdc3b9ef9e..0226211735 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;
@@ -65,12 +65,14 @@ public:
virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
// Application control
+ void flushVFSIO(); // waits for vfs transfers to complete
void forceQuit(); // Puts the viewer into 'shutting down without error' mode.
+ void fastQuit(S32 error_code = 0); // Shuts down the viewer immediately after sending a logout message
void requestQuit(); // Request a quit. A kinder, gentler quit.
void userQuit(); // The users asks to quit. Confirm, then requestQuit()
void earlyExit(const std::string& name,
const LLSD& substitutions = LLSD()); // Display an error dialog and forcibly quit.
- void forceExit(S32 arg); // exit() immediately (after some cleanup).
+ void earlyExitNoNotify(); // Do not display error dialog then forcibly quit.
void abortQuit(); // Called to abort a quit request.
bool quitRequested() { return mQuitRequested; }
@@ -167,6 +169,10 @@ public:
// mute/unmute the system's master audio
virtual void setMasterSystemAudioMute(bool mute);
virtual bool getMasterSystemAudioMute();
+
+ // Metrics policy helper statics.
+ static void metricsUpdateRegion(U64 region_handle);
+ static void metricsSend(bool enable_reporting);
protected:
virtual bool initWindow(); // Initialize the viewer's window.
@@ -186,7 +192,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.
@@ -247,11 +253,13 @@ private:
bool mQuitRequested; // User wants to quit, may have modified documents open.
bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim.
S32 mYieldTime;
- LLSD mSettingsLocationList;
+ struct SettingsFiles* mSettingsLocationList;
LLWatchdogTimeout* mMainloopTimeout;
+ // For performance and metric gathering
LLThread* mFastTimerLogThread;
+
// for tracking viewer<->region circuit death
bool mAgentRegionLastAlive;
LLUUID mAgentRegionLastID;
@@ -260,7 +268,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 +287,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/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index f12bc16d4b..dd5bc74b2a 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -126,6 +126,7 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)
break;
}
LLUploadDialog::modalUploadFinished();
+ LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails
}
//virtual
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 066b4d8bc3..afa8b62c74 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -47,6 +47,7 @@
#include "llfloatergroups.h"
#include "llfloaterreg.h"
#include "llfloaterpay.h"
+#include "llfloaterwebcontent.h"
#include "llfloaterworldmap.h"
#include "llgiveinventory.h"
#include "llinventorybridge.h"
@@ -56,9 +57,11 @@
#include "llmutelist.h"
#include "llnotificationsutil.h" // for LLNotificationsUtil
#include "llpaneloutfitedit.h"
+#include "llpanelprofile.h"
#include "llrecentpeople.h"
#include "llsidetray.h"
#include "lltrans.h"
+#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
#include "llviewermessage.h" // for handle_lure
#include "llviewerregion.h"
@@ -306,6 +309,20 @@ void LLAvatarActions::showProfile(const LLUUID& id)
params["id"] = id;
params["open_tab_name"] = "panel_profile";
+ // PROFILES: open in webkit window
+ std::string full_name;
+ if (gCacheName->getFullName(id,full_name))
+ {
+ std::string agent_name = LLCacheName::buildUsername(full_name);
+ llinfos << "opening web profile for " << agent_name << llendl;
+ std::string url = getProfileURL(agent_name);
+ LLWeb::loadWebURLInternal(url, "", id.asString());
+ }
+ else
+ {
+ llwarns << "no name info for agent id " << id << llendl;
+ }
+#if 0
//Show own profile
if(gAgent.getID() == id)
{
@@ -316,6 +333,25 @@ void LLAvatarActions::showProfile(const LLUUID& id)
{
LLSideTray::getInstance()->showPanel("panel_profile_view", params);
}
+#endif
+ }
+}
+
+//static
+bool LLAvatarActions::profileVisible(const LLUUID& id)
+{
+ LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::findInstance("web_content", id.asString()));
+ return browser && browser->isShown();
+}
+
+
+//static
+void LLAvatarActions::hideProfile(const LLUUID& id)
+{
+ LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::findInstance("web_content", id.asString()));
+ if (browser)
+ {
+ browser->closeFloater();
}
}
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 2db2918eed..956fed7461 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -93,6 +93,8 @@ public:
* Show avatar profile.
*/
static void showProfile(const LLUUID& id);
+ static void hideProfile(const LLUUID& id);
+ static bool profileVisible(const LLUUID& id);
/**
* Show avatar on world map.
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index ff7dfccc0a..771419f60a 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -240,6 +240,9 @@ void LLAvatarList::addAvalineItem(const LLUUID& item_id, const LLUUID& session_i
LLAvalineListItem* item = new LLAvalineListItem(/*hide_number=*/false);
item->setAvatarId(item_id, session_id, true, false);
item->setName(item_name);
+ item->showLastInteractionTime(mShowLastInteractionTime);
+ item->showSpeakingIndicator(mShowSpeakingIndicator);
+ item->setOnline(false);
addItem(item, item_id);
mIDs.push_back(item_id);
@@ -286,9 +289,18 @@ void LLAvatarList::refresh()
{
// *NOTE: If you change the UI to show a different string,
// be sure to change the filter code below.
- addNewItem(buddy_id,
- av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName,
- LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+ if (LLRecentPeople::instance().isAvalineCaller(buddy_id))
+ {
+ const LLSD& call_data = LLRecentPeople::instance().getData(buddy_id);
+ addAvalineItem(buddy_id, call_data["session_id"].asUUID(), call_data["call_number"].asString());
+ }
+ else
+ {
+ addNewItem(buddy_id,
+ av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName,
+ LLAvatarTracker::instance().isBuddyOnline(buddy_id));
+ }
+
modified = true;
nadded++;
}
@@ -440,7 +452,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is
BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
- if ( mContextMenu )
+ if ( mContextMenu && !isAvalineItemSelected())
{
uuid_vec_t selected_uuids;
getSelectedUUIDs(selected_uuids);
@@ -449,6 +461,21 @@ BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
return handled;
}
+bool LLAvatarList::isAvalineItemSelected()
+{
+ std::vector<LLPanel*> selected_items;
+ getSelectedItems(selected_items);
+ std::vector<LLPanel*>::iterator it = selected_items.begin();
+
+ for(; it != selected_items.end(); ++it)
+ {
+ if (dynamic_cast<LLAvalineListItem*>(*it))
+ return true;
+ }
+
+ return false;
+}
+
void LLAvatarList::setVisible(BOOL visible)
{
if ( visible == FALSE && mContextMenu )
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index cacbcf7244..4814a88a79 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -112,6 +112,8 @@ protected:
private:
+ bool isAvalineItemSelected();
+
bool mIgnoreOnlineStatus;
bool mShowLastInteractionTime;
bool mDirty;
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..0371b7be71 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -38,12 +38,15 @@
#include "lltexteditor.h"
// newview includes
+#include "llagent.h"
#include "llagentcamera.h"
+#include "llavataractions.h"
#include "llchiclet.h"
#include "llfloatercamera.h"
#include "llhints.h"
#include "llimfloater.h" // for LLIMFloater
#include "llnearbychatbar.h"
+#include "llsidetray.h"
#include "llspeakbutton.h"
#include "llsplitbutton.h"
#include "llsyswellwindow.h"
@@ -52,6 +55,7 @@
#include "llviewerwindow.h"
#include "llsdserialize.h"
+#include "llfirstuse.h"
// Distance from mouse down on which drag'n'drop should be started.
#define DRAG_START_DISTANCE 3
@@ -65,31 +69,43 @@ LLDefaultChildRegistry::Register<LLBottomtrayButton> bottomtray_button("bottomtr
// virtual
BOOL LLBottomtrayButton::handleHover(S32 x, S32 y, MASK mask)
{
- S32 screenX, screenY;
- localPointToScreen(x, y, &screenX, &screenY);
- // pass hover to bottomtray
- LLBottomTray::getInstance()->onDraggableButtonHover(screenX, screenY);
- return FALSE;
+ if (mCanDrag)
+ {
+ // pass hover to bottomtray
+ S32 screenX, screenY;
+ localPointToScreen(x, y, &screenX, &screenY);
+ LLBottomTray::getInstance()->onDraggableButtonHover(screenX, screenY);
+
+ return TRUE;
+ }
+ else
+ {
+ return LLButton::handleHover(x, y, mask);
+ }
}
//virtual
BOOL LLBottomtrayButton::handleMouseUp(S32 x, S32 y, MASK mask)
{
+ if (mCanDrag)
+ {
S32 screenX, screenY;
localPointToScreen(x, y, &screenX, &screenY);
// pass mouse up to bottomtray
LLBottomTray::getInstance()->onDraggableButtonMouseUp(this, screenX, screenY);
- LLButton::handleMouseUp(x, y, mask);
- return FALSE;
+ }
+ return LLButton::handleMouseUp(x, y, mask);
}
//virtual
BOOL LLBottomtrayButton::handleMouseDown(S32 x, S32 y, MASK mask)
{
+ if (mCanDrag)
+ {
S32 screenX, screenY;
localPointToScreen(x, y, &screenX, &screenY);
// pass mouse up to bottomtray
LLBottomTray::getInstance()->onDraggableButtonMouseDown(this, screenX, screenY);
- LLButton::handleMouseDown(x, y, mask);
- return FALSE;
+ }
+ return LLButton::handleMouseDown(x, y, mask);
}
static void update_build_button_enable_state()
@@ -150,8 +166,6 @@ public:
{
mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
buildFromFile("panel_bottomtray_lite.xml");
- // Necessary for focus movement among child controls
- setFocusRoot(TRUE);
}
BOOL postBuild()
@@ -191,6 +205,7 @@ LLBottomTray::LLBottomTray(const LLSD&)
mSpeakBtn(NULL),
mNearbyChatBar(NULL),
mChatBarContainer(NULL),
+ mNearbyCharResizeHandlePanel(NULL),
mToolbarStack(NULL),
mMovementButton(NULL),
mResizeState(RS_NORESIZE),
@@ -218,9 +233,6 @@ LLBottomTray::LLBottomTray(const LLSD&)
//destroyed LLBottomTray requires some subsystems that are long gone
//LLUI::getRootView()->addChild(this);
- // Necessary for focus movement among child controls
- setFocusRoot(TRUE);
-
{
mBottomTrayLite = new LLBottomTrayLite();
mBottomTrayLite->setFollowsAll();
@@ -370,7 +382,12 @@ void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, b
// skipped to avoid button blinking
if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL)
{
- mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
+ bool voice_status = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
+ mSpeakBtn->setFlyoutBtnEnabled(voice_status);
+ if (voice_status)
+ {
+ LLFirstUse::speak(true);
+ }
}
}
@@ -410,10 +427,6 @@ void LLBottomTray::setVisible(BOOL visible)
{
LLPanel::setVisible(visible);
}
- if(visible)
- gFloaterView->setSnapOffsetBottom(getRect().getHeight());
- else
- gFloaterView->setSnapOffsetBottom(0);
}
S32 LLBottomTray::notifyParent(const LLSD& info)
@@ -499,6 +512,23 @@ void LLBottomTray::showSnapshotButton(BOOL visible)
setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
}
+void LLBottomTray::showSpeakButton(bool visible)
+{
+ // Show/hide the button
+ setTrayButtonVisible(RS_BUTTON_SPEAK, visible);
+
+ // and adjust other panels according to the occupied/freed space.
+ const S32 panel_width = mSpeakPanel->getRect().getWidth();
+ if (visible)
+ {
+ processWidthDecreased(-panel_width);
+ }
+ else
+ {
+ processWidthIncreased(panel_width);
+ }
+}
+
void LLBottomTray::toggleMovementControls()
{
if (mMovementButton)
@@ -513,6 +543,9 @@ void LLBottomTray::toggleCameraControls()
BOOL LLBottomTray::postBuild()
{
+ LLHints::registerHintTarget("bottom_tray", LLView::getHandle());
+ LLHints::registerHintTarget("dest_guide_btn", getChild<LLUICtrl>("destination_btn")->getHandle());
+ LLHints::registerHintTarget("avatar_picker_btn", getChild<LLUICtrl>("avatar_btn")->getHandle());
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("NearbyChatBar.Action", boost::bind(&LLBottomTray::onContextMenuItemClicked, this, _2));
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("NearbyChatBar.EnableMenuItem", boost::bind(&LLBottomTray::onContextMenuItemEnabled, this, _2));
@@ -524,6 +557,7 @@ BOOL LLBottomTray::postBuild()
LLHints::registerHintTarget("chat_bar", mNearbyChatBar->LLView::getHandle());
mChatBarContainer = getChild<LLLayoutPanel>("chat_bar_layout_panel");
+ mNearbyCharResizeHandlePanel = getChild<LLPanel>("chat_bar_resize_handle_panel");
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
mMovementButton = getChild<LLButton>("movement_btn");
@@ -533,6 +567,7 @@ BOOL LLBottomTray::postBuild()
mSpeakPanel = getChild<LLPanel>("speak_panel");
mSpeakBtn = getChild<LLSpeakButton>("talk");
+ LLHints::registerHintTarget("speak_btn", mSpeakBtn->getHandle());
// Both parts of speak button should be initially disabled because
// it takes some time between logging in to world and connecting to voice channel.
@@ -642,12 +677,20 @@ void LLBottomTray::onDraggableButtonHover(S32 x, S32 y)
gViewerWindow->getWindow()->setCursor(UI_CURSOR_NO);
}
}
+ else
+ {
+ // Reset cursor in case you move your mouse from the drag handle to a button.
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+
+ }
}
bool LLBottomTray::isCursorOverDraggableArea(S32 x, S32 y)
{
+ // Draggable area lasts from the nearby chat input resize handle
+ // to the chiclet area (exlusively).
bool result = getRect().pointInRect(x, y);
- result = result && mNearbyChatBar->calcScreenRect().mRight < x;
+ result = result && mNearbyCharResizeHandlePanel->calcScreenRect().mRight < x;
result = result && mChicletPanel->calcScreenRect().mRight > x;
return result;
}
@@ -658,10 +701,7 @@ void LLBottomTray::updateButtonsOrdersAfterDnD()
// (and according to future possible changes in the way button order is saved between sessions).
state_object_map_t::const_iterator it = mStateProcessedObjectMap.begin();
state_object_map_t::const_iterator it_end = mStateProcessedObjectMap.end();
- // Speak button is currently the only draggable button not in mStateProcessedObjectMap,
- // so if dragged_state is not found in that map, it should be RS_BUTTON_SPEAK. Change this code if any other
- // exclusions from mStateProcessedObjectMap will become draggable.
- EResizeState dragged_state = RS_BUTTON_SPEAK;
+ EResizeState dragged_state = RS_NORESIZE;
EResizeState landing_state = RS_NORESIZE;
bool landing_state_found = false;
// Find states for dragged item and landing tab
@@ -677,7 +717,17 @@ void LLBottomTray::updateButtonsOrdersAfterDnD()
landing_state_found = true;
}
}
-
+
+ if (dragged_state == RS_NORESIZE)
+ {
+ llwarns << "Cannot determine what button is being dragged" << llendl;
+ llassert(dragged_state != RS_NORESIZE);
+ return;
+ }
+
+ lldebugs << "Will place " << resizeStateToString(dragged_state)
+ << " before " << resizeStateToString(landing_state) << llendl;
+
// Update order of buttons according to drag'n'drop
mButtonsOrder.erase(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), dragged_state));
if (!landing_state_found && mLandingTab == getChild<LLPanel>(PANEL_CHICLET_NAME))
@@ -686,9 +736,10 @@ void LLBottomTray::updateButtonsOrdersAfterDnD()
}
else
{
- if (!landing_state_found) landing_state = RS_BUTTON_SPEAK;
+ if (!landing_state_found) landing_state = RS_BUTTON_SPEAK; // just a random fallback
mButtonsOrder.insert(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), landing_state), dragged_state);
}
+
// Synchronize button process order with their order
resize_state_vec_t::const_iterator it1 = mButtonsOrder.begin();
const resize_state_vec_t::const_iterator it_end1 = mButtonsOrder.end();
@@ -765,11 +816,12 @@ void LLBottomTray::loadButtonsOrder()
// placing panels in layout stack according to button order which we loaded in previous for
for (resize_state_vec_t::const_reverse_iterator it = mButtonsOrder.rbegin(); it != it_end; ++it, ++i)
{
- LLPanel* panel_to_move = *it == RS_BUTTON_SPEAK ? mSpeakPanel : mStateProcessedObjectMap[*it];
+ LLPanel* panel_to_move = getButtonPanel(*it);
mToolbarStack->movePanel(panel_to_move, NULL, true); // prepend
}
// Nearbychat is not stored in order settings file, but it must be the first of the panels, so moving it
- // manually here
+ // (along with its drag handle) manually here.
+ mToolbarStack->movePanel(getChild<LLLayoutPanel>("chat_bar_resize_handle_panel"), NULL, true);
mToolbarStack->movePanel(mChatBarContainer, NULL, true);
}
@@ -803,6 +855,24 @@ void LLBottomTray::draw()
LLRect rect = mLandingTab->calcScreenRect();
mImageDragIndication->draw(rect.mLeft - w/2, rect.getHeight(), w, h);
}
+ getChild<LLButton>("show_profile_btn")->setToggleState(LLAvatarActions::profileVisible(gAgent.getID()));
+
+ LLPanel* panel = LLSideTray::getInstance()->getPanel("panel_people");
+ if (panel && panel->isInVisibleChain())
+ {
+ getChild<LLButton>("show_people_button")->setToggleState(true);
+ }
+ else
+ {
+ getChild<LLButton>("show_people_button")->setToggleState(false);
+ }
+
+ LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
+ bool help_floater_visible = (help_browser && help_browser->isInVisibleChain());
+
+ getChild<LLButton>("show_help_btn")->setToggleState(help_floater_visible);
+
+
}
bool LLBottomTray::onContextMenuItemEnabled(const LLSD& userdata)
@@ -1169,9 +1239,8 @@ void LLBottomTray::processShowButtons(S32& available_width)
bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32& available_width)
{
lldebugs << "Trying to show object type: " << shown_object_type << llendl;
- llassert(mStateProcessedObjectMap[shown_object_type] != NULL);
- LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ LLPanel* panel = getButtonPanel(shown_object_type);
if (NULL == panel)
{
lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
@@ -1217,9 +1286,7 @@ void LLBottomTray::processHideButtons(S32& required_width, S32& buttons_freed_wi
void LLBottomTray::processHideButton(EResizeState processed_object_type, S32& required_width, S32& buttons_freed_width)
{
lldebugs << "Trying to hide object type: " << processed_object_type << llendl;
- llassert(mStateProcessedObjectMap[processed_object_type] != NULL);
-
- LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+ LLPanel* panel = getButtonPanel(processed_object_type);
if (NULL == panel)
{
lldebugs << "There is no object to process for state: " << processed_object_type << llendl;
@@ -1264,7 +1331,6 @@ void LLBottomTray::processShrinkButtons(S32& required_width, S32& buttons_freed_
// then shrink Speak button
if (required_width < 0)
{
-
S32 panel_min_width = 0;
std::string panel_name = mSpeakPanel->getName();
bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width);
@@ -1300,8 +1366,7 @@ void LLBottomTray::processShrinkButtons(S32& required_width, S32& buttons_freed_
void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32& required_width)
{
- llassert(mStateProcessedObjectMap[processed_object_type] != NULL);
- LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+ LLPanel* panel = getButtonPanel(processed_object_type);
if (NULL == panel)
{
lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
@@ -1365,20 +1430,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
@@ -1389,8 +1467,7 @@ void LLBottomTray::processExtendButtons(S32& available_width)
void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32& available_width)
{
- llassert(mStateProcessedObjectMap[processed_object_type] != NULL);
- LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
+ LLPanel* panel = getButtonPanel(processed_object_type);
if (NULL == panel)
{
lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
@@ -1458,6 +1535,7 @@ bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
void LLBottomTray::initResizeStateContainers()
{
// init map with objects should be processed for each type
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SPEAK, getChild<LLPanel>("speak_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, getChild<LLPanel>("gesture_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLPanel>("movement_panel")));
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, getChild<LLPanel>("cam_panel")));
@@ -1490,22 +1568,22 @@ void LLBottomTray::initResizeStateContainers()
{
const EResizeState button_type = *it;
// is there an appropriate object?
- llassert(mStateProcessedObjectMap.count(button_type) > 0);
- if (0 == mStateProcessedObjectMap.count(button_type)) continue;
+ LLPanel* button_panel = getButtonPanel(button_type);
+ if (!button_panel) continue;
// set default width for it.
- mObjectDefaultWidthMap[button_type] = mStateProcessedObjectMap[button_type]->getRect().getWidth();
+ mObjectDefaultWidthMap[button_type] = button_panel->getRect().getWidth();
}
// ... and add Speak button because it also can be shrunk.
mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth();
-
}
// this method must be called before restoring of the chat entry field on startup
// because it resets chatbar's width according to resize logic.
void LLBottomTray::initButtonsVisibility()
{
+ setVisibleAndFitWidths(RS_BUTTON_SPEAK, gSavedSettings.getBOOL("EnableVoiceChat"));
setVisibleAndFitWidths(RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"));
setVisibleAndFitWidths(RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"));
setVisibleAndFitWidths(RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"));
@@ -1518,6 +1596,7 @@ void LLBottomTray::initButtonsVisibility()
void LLBottomTray::setButtonsControlsAndListeners()
{
+ gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SPEAK, _2));
gSavedSettings.getControl("ShowGestureButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_GESTURES, _2));
gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MOVEMENT, _2));
gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_CAMERA, _2));
@@ -1546,8 +1625,7 @@ bool LLBottomTray::toggleShowButton(LLBottomTray::EResizeState button_type, cons
void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
{
- llassert(mStateProcessedObjectMap[shown_object_type] != NULL);
- LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ LLPanel* panel = getButtonPanel(shown_object_type);
if (NULL == panel)
{
lldebugs << "There is no object to show for state: " << shown_object_type << llendl;
@@ -1570,7 +1648,15 @@ void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type
bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible)
{
- LLPanel* cur_panel = mStateProcessedObjectMap[object_type];
+ // The Speak button is treated specially: if voice is enabled,
+ // the button should be displayed no matter how much space we've got.
+ if (object_type == RS_BUTTON_SPEAK)
+ {
+ showSpeakButton(visible);
+ return true;
+ }
+
+ LLPanel* cur_panel = getButtonPanel(object_type);
if (NULL == cur_panel)
{
lldebugs << "There is no object to process for state: " << object_type << llendl;
@@ -1615,7 +1701,7 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible
for (; it != it_end; ++it)
{
- LLPanel * cur_panel = mStateProcessedObjectMap[*it];
+ LLPanel* cur_panel = getButtonPanel(*it);
sum_of_min_widths += get_panel_min_width(mToolbarStack, cur_panel);
sum_of_curr_widths += get_curr_width(cur_panel);
}
@@ -1673,6 +1759,19 @@ bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible
return is_set;
}
+LLPanel* LLBottomTray::getButtonPanel(EResizeState button_type)
+{
+ // Don't use the operator[] because it inserts a NULL value if the key is not found.
+ if (mStateProcessedObjectMap.count(button_type) == 0)
+ {
+ llwarns << "Cannot find a panel for " << resizeStateToString(button_type) << llendl;
+ llassert(mStateProcessedObjectMap.count(button_type) == 1);
+ return NULL;
+ }
+
+ return mStateProcessedObjectMap[button_type];
+}
+
void LLBottomTray::showWellButton(EResizeState object_type, bool visible)
{
llassert( ((RS_NOTIFICATION_WELL | RS_IM_WELL) & object_type) == object_type );
@@ -1730,4 +1829,29 @@ void LLBottomTray::processChatbarCustomization(S32 new_width)
}
}
+// static
+std::string LLBottomTray::resizeStateToString(EResizeState state)
+{
+ switch (state)
+ {
+ case RS_NORESIZE: return "RS_NORESIZE";
+ case RS_CHICLET_PANEL: return "RS_CHICLET_PANEL";
+ case RS_CHATBAR_INPUT: return "RS_CHATBAR_INPUT";
+ case RS_BUTTON_SNAPSHOT: return "RS_BUTTON_SNAPSHOT";
+ case RS_BUTTON_CAMERA: return "RS_BUTTON_CAMERA";
+ case RS_BUTTON_MOVEMENT: return "RS_BUTTON_MOVEMENT";
+ case RS_BUTTON_GESTURES: return "RS_BUTTON_GESTURES";
+ case RS_BUTTON_SPEAK: return "RS_BUTTON_SPEAK";
+ case RS_IM_WELL: return "RS_IM_WELL";
+ case RS_NOTIFICATION_WELL: return "RS_NOTIFICATION_WELL";
+ case RS_BUTTON_BUILD: return "RS_BUTTON_BUILD";
+ case RS_BUTTON_SEARCH: return "RS_BUTTON_SEARCH";
+ case RS_BUTTON_WORLD_MAP: return "RS_BUTTON_WORLD_MAP";
+ case RS_BUTTON_MINI_MAP: return "RS_BUTTON_MINI_MAP";
+ case RS_BUTTONS_CAN_BE_HIDDEN: return "RS_BUTTONS_CAN_BE_HIDDEN";
+ // No default to track additions.
+ }
+ return "UNKNOWN_BUTTON";
+}
+
//EOF
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 8d8a42c553..04e5f5e9e0 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -54,7 +54,9 @@ class LLBottomtrayButton : public LLButton
public:
struct Params : public LLInitParam::Block<Params, LLButton::Params>
{
- Params(){}
+ Optional<bool> can_drag;
+ Params()
+ : can_drag("can_drag", true){}
};
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -62,11 +64,14 @@ public:
protected:
LLBottomtrayButton(const Params& p)
- : LLButton(p)
+ : LLButton(p),
+ mCanDrag(p.can_drag)
{
}
friend class LLUICtrlFactory;
+
+ bool mCanDrag;
};
class LLBottomTray
@@ -111,6 +116,7 @@ public:
void showMoveButton(BOOL visible);
void showCameraButton(BOOL visible);
void showSnapshotButton(BOOL visible);
+ void showSpeakButton(bool visible);
void toggleMovementControls();
void toggleCameraControls();
@@ -386,6 +392,13 @@ private:
bool setVisibleAndFitWidths(EResizeState object_type, bool visible);
/**
+ * Get panel containing the given button.
+ *
+ * @see mStateProcessedObjectMap
+ */
+ LLPanel* getButtonPanel(EResizeState button_type);
+
+ /**
* Shows/hides panel with specified well button (IM or Notification)
*
* @param[in] object_type - type of well button to be processed.
@@ -404,12 +417,21 @@ private:
*/
void processChatbarCustomization(S32 new_width);
+ /// Get button name for debugging.
+ static std::string resizeStateToString(EResizeState state);
+ /// Buttons automatically hidden due to lack of space.
MASK mResizeState;
+ /**
+ * Mapping of button types to the layout panels the buttons are wrapped in.
+ *
+ * Used by getButtonPanel().
+ */
typedef std::map<EResizeState, LLPanel*> state_object_map_t;
state_object_map_t mStateProcessedObjectMap;
+ /// Default (maximum) widths of the layout panels.
typedef std::map<EResizeState, S32> state_object_width_map_t;
state_object_width_map_t mObjectDefaultWidthMap;
@@ -419,6 +441,7 @@ private:
* Contains order in which child buttons should be processed in show/hide, extend/shrink methods.
*/
resize_state_vec_t mButtonsProcessOrder;
+
/**
* Contains order in which child buttons are shown.
* It traces order of all bottomtray buttons that may change place via drag'n'drop and should
@@ -446,6 +469,7 @@ protected:
LLSpeakButton* mSpeakBtn;
LLNearbyChatBar* mNearbyChatBar;
LLLayoutPanel* mChatBarContainer;
+ LLPanel* mNearbyCharResizeHandlePanel;
LLLayoutStack* mToolbarStack;
LLMenuGL* mBottomTrayContextMenu;
LLButton* mCamButton;
diff --git a/indra/newview/llbreastmotion.cpp b/indra/newview/llbreastmotion.cpp
new file mode 100644
index 0000000000..7c205a8b9f
--- /dev/null
+++ b/indra/newview/llbreastmotion.cpp
@@ -0,0 +1,402 @@
+/**
+ * @file llbreastmotion.cpp
+ * @brief Implementation of LLBreastMotion class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+#include "m3math.h"
+#include "v3dmath.h"
+
+#include "llbreastmotion.h"
+#include "llcharacter.h"
+#include "llviewercontrol.h"
+#include "llviewervisualparam.h"
+#include "llvoavatarself.h"
+
+#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f;
+
+#define N_PARAMS 2
+
+// User-set params
+static const std::string breast_param_names_user[N_PARAMS] =
+{
+ "Breast_Female_Cleavage_Driver",
+ "Breast_Gravity_Driver"
+};
+
+// Params driven by this algorithm
+static const std::string breast_param_names_driven[N_PARAMS] =
+{
+ "Breast_Female_Cleavage",
+ "Breast_Gravity"
+};
+
+
+
+LLBreastMotion::LLBreastMotion(const LLUUID &id) :
+ LLMotion(id),
+ mCharacter(NULL)
+{
+ mName = "breast_motion";
+ mChestState = new LLJointState;
+
+ mBreastMassParam = (F32)1.0;
+ mBreastDragParam = LLVector3((F32)0.1, (F32)0.1, (F32)0.1);
+ mBreastSmoothingParam = (U32)2;
+ mBreastGravityParam = (F32)0.0;
+
+ mBreastSpringParam = LLVector3((F32)3.0, (F32)0.0, (F32)3.0);
+ mBreastGainParam = LLVector3((F32)50.0, (F32)0.0, (F32)50.0);
+ mBreastDampingParam = LLVector3((F32)0.3, (F32)0.0, (F32)0.3);
+ mBreastMaxVelocityParam = LLVector3((F32)10.0, (F32)0.0, (F32)10.0);
+
+ mBreastParamsUser[0] = mBreastParamsUser[1] = mBreastParamsUser[2] = NULL;
+ mBreastParamsDriven[0] = mBreastParamsDriven[1] = mBreastParamsDriven[2] = NULL;
+
+ mCharLastPosition_world_pt = LLVector3(0,0,0);
+ mCharLastVelocity_local_vec = LLVector3(0,0,0);
+ mCharLastAcceleration_local_vec = LLVector3(0,0,0);
+ mBreastLastPosition_local_pt = LLVector3(0,0,0);
+ mBreastLastUpdatePosition_local_pt = LLVector3(0,0,0);
+ mBreastVelocity_local_vec = LLVector3(0,0,0);
+}
+
+LLBreastMotion::~LLBreastMotion()
+{
+}
+
+BOOL LLBreastMotion::onActivate()
+{
+ return TRUE;
+}
+
+void LLBreastMotion::onDeactivate()
+{
+}
+
+LLMotion::LLMotionInitStatus LLBreastMotion::onInitialize(LLCharacter *character)
+{
+ mCharacter = character;
+
+ if (!mChestState->setJoint(character->getJoint("mChest")))
+ {
+ return STATUS_FAILURE;
+ }
+
+ mChestState->setUsage(LLJointState::ROT);
+ addJointState( mChestState );
+
+ for (U32 i=0; i < N_PARAMS; i++)
+ {
+ mBreastParamsUser[i] = NULL;
+ mBreastParamsDriven[i] = NULL;
+ mBreastParamsMin[i] = 0;
+ mBreastParamsMax[i] = 0;
+ if (breast_param_names_user[i] != "" && breast_param_names_driven[i] != "")
+ {
+ mBreastParamsUser[i] = (LLViewerVisualParam*)mCharacter->getVisualParam(breast_param_names_user[i].c_str());
+ mBreastParamsDriven[i] = (LLViewerVisualParam*)mCharacter->getVisualParam(breast_param_names_driven[i].c_str());
+ if (mBreastParamsDriven[i])
+ {
+ mBreastParamsMin[i] = mBreastParamsDriven[i]->getMinWeight();
+ mBreastParamsMax[i] = mBreastParamsDriven[i]->getMaxWeight();
+ }
+ }
+ }
+
+ mTimer.reset();
+ return STATUS_SUCCESS;
+}
+
+F32 LLBreastMotion::getMinPixelArea()
+{
+ return MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION;
+}
+
+
+F32 LLBreastMotion::calculateTimeDelta()
+{
+ const F32 time = mTimer.getElapsedTimeF32();
+ const F32 time_delta = time - mLastTime;
+ mLastTime = time;
+ return time_delta;
+}
+
+// Local space means "parameter space".
+LLVector3 LLBreastMotion::toLocal(const LLVector3 &world_vector)
+{
+ LLVector3 local_vec(0,0,0);
+
+ LLJoint *chest_joint = mChestState->getJoint();
+ const LLQuaternion world_rot = chest_joint->getWorldRotation();
+
+ // Cleavage
+ LLVector3 breast_dir_world_vec = LLVector3(-1,0,0) * world_rot; // -1 b/c cleavage param changes opposite to direction
+ breast_dir_world_vec.normalize();
+ local_vec[0] = world_vector * breast_dir_world_vec;
+
+ // Up-Down Bounce
+ LLVector3 breast_up_dir_world_vec = LLVector3(0,0,1) * world_rot;
+ breast_up_dir_world_vec.normalize();
+ local_vec[1] = world_vector * breast_up_dir_world_vec;
+
+ return local_vec;
+}
+
+LLVector3 LLBreastMotion::calculateVelocity_local(const F32 time_delta)
+{
+ LLJoint *chest_joint = mChestState->getJoint();
+ const LLVector3 world_pos_pt = chest_joint->getWorldPosition();
+ const LLQuaternion world_rot = chest_joint->getWorldRotation();
+ const LLVector3 last_world_pos_pt = mCharLastPosition_world_pt;
+ const LLVector3 char_velocity_world_vec = (world_pos_pt-last_world_pos_pt) / time_delta;
+ const LLVector3 char_velocity_local_vec = toLocal(char_velocity_world_vec);
+
+ return char_velocity_local_vec;
+}
+
+LLVector3 LLBreastMotion::calculateAcceleration_local(const LLVector3 &new_char_velocity_local_vec,
+ const F32 time_delta)
+{
+ LLVector3 char_acceleration_local_vec = new_char_velocity_local_vec - mCharLastVelocity_local_vec;
+
+ char_acceleration_local_vec =
+ char_acceleration_local_vec * 1.0/mBreastSmoothingParam +
+ mCharLastAcceleration_local_vec * (mBreastSmoothingParam-1.0)/mBreastSmoothingParam;
+
+ mCharLastAcceleration_local_vec = char_acceleration_local_vec;
+
+ return char_acceleration_local_vec;
+}
+
+BOOL LLBreastMotion::onUpdate(F32 time, U8* joint_mask)
+{
+ // Skip if disabled globally.
+ if (!gSavedSettings.getBOOL("AvatarPhysics"))
+ {
+ return TRUE;
+ }
+
+ // Higher LOD is better. This controls the granularity
+ // and frequency of updates for the motions.
+ const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor;
+ if (lod_factor == 0)
+ {
+ return TRUE;
+ }
+
+ if (mCharacter->getSex() != SEX_FEMALE) return TRUE;
+ const F32 time_delta = calculateTimeDelta();
+ if (time_delta < .01 || time_delta > 10.0) return TRUE;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Get all parameters and settings
+ //
+
+ mBreastMassParam = mCharacter->getVisualParamWeight("Breast_Physics_Mass");
+ mBreastSmoothingParam = (U32)(mCharacter->getVisualParamWeight("Breast_Physics_Smoothing"));
+ mBreastGravityParam = mCharacter->getVisualParamWeight("Breast_Physics_Gravity");
+
+ mBreastSpringParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Spring");
+ mBreastGainParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Gain");
+ mBreastDampingParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Damping");
+ mBreastMaxVelocityParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Max_Velocity");
+ mBreastDragParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Drag");
+
+ mBreastSpringParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Spring");
+ mBreastGainParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Gain");
+ mBreastDampingParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Damping");
+ mBreastMaxVelocityParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Max_Velocity");
+ mBreastDragParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Drag");
+
+
+ // Get the current morph parameters.
+ LLVector3 breast_user_local_pt(0,0,0);
+ for (U32 i=0; i < N_PARAMS; i++)
+ {
+ if (mBreastParamsUser[i] != NULL)
+ {
+ breast_user_local_pt[i] = mBreastParamsUser[i]->getWeight();
+ }
+ }
+
+ LLVector3 breast_current_local_pt = mBreastLastPosition_local_pt;
+
+ //
+ // End parameters and settings
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate velocity and acceleration in parameter space.
+ //
+
+ const LLVector3 char_velocity_local_vec = calculateVelocity_local(time_delta);
+ const LLVector3 char_acceleration_local_vec = calculateAcceleration_local(char_velocity_local_vec, time_delta);
+ mCharLastVelocity_local_vec = char_velocity_local_vec;
+
+ LLJoint *chest_joint = mChestState->getJoint();
+ mCharLastPosition_world_pt = chest_joint->getWorldPosition();
+
+ //
+ // End velocity and acceleration
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate the total force
+ //
+
+ // Spring force is a restoring force towards the original user-set breast position.
+ // F = kx
+ const LLVector3 spring_length_local = breast_current_local_pt-breast_user_local_pt;
+ LLVector3 force_spring_local_vec = -spring_length_local; force_spring_local_vec *= mBreastSpringParam;
+
+ // Acceleration is the force that comes from the change in velocity of the torso.
+ // F = ma + mg
+ LLVector3 force_accel_local_vec = char_acceleration_local_vec * mBreastMassParam;
+ const LLVector3 force_gravity_local_vec = toLocal(LLVector3(0,0,1))* mBreastGravityParam * mBreastMassParam;
+ force_accel_local_vec += force_gravity_local_vec;
+ force_accel_local_vec *= mBreastGainParam;
+
+ // Damping is a restoring force that opposes the current velocity.
+ // F = -kv
+ LLVector3 force_damping_local_vec = -mBreastDampingParam;
+ force_damping_local_vec *= mBreastVelocity_local_vec;
+
+ // Drag is a force imparted by velocity, intuitively it is similar to wind resistance.
+ // F = .5v*v
+ LLVector3 force_drag_local_vec = .5*char_velocity_local_vec;
+ force_drag_local_vec *= char_velocity_local_vec;
+ force_drag_local_vec *= mBreastDragParam[0];
+
+ LLVector3 force_net_local_vec =
+ force_accel_local_vec +
+ force_gravity_local_vec +
+ force_spring_local_vec +
+ force_damping_local_vec +
+ force_drag_local_vec;
+
+ //
+ // End total force
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate new params
+ //
+
+ // Calculate the new acceleration based on the net force.
+ // a = F/m
+ LLVector3 acceleration_local_vec = force_net_local_vec / mBreastMassParam;
+ mBreastVelocity_local_vec += acceleration_local_vec;
+ mBreastVelocity_local_vec.clamp(-mBreastMaxVelocityParam*100.0, mBreastMaxVelocityParam*100.0);
+
+ // Temporary debugging setting to cause all avatars to move, for profiling purposes.
+ if (gSavedSettings.getBOOL("AvatarPhysicsTest"))
+ {
+ mBreastVelocity_local_vec[0] = sin(mTimer.getElapsedTimeF32()*4.0)*5.0;
+ mBreastVelocity_local_vec[1] = sin(mTimer.getElapsedTimeF32()*3.0)*5.0;
+ }
+ // Calculate the new parameters and clamp them to the min/max ranges.
+ LLVector3 new_local_pt = breast_current_local_pt + mBreastVelocity_local_vec*time_delta;
+ new_local_pt.clamp(mBreastParamsMin,mBreastParamsMax);
+
+ // Set the new parameters.
+ for (U32 i=0; i < 3; i++)
+ {
+ // If the param is disabled, just set the param to the user value.
+ if (mBreastMaxVelocityParam[i] == 0)
+ {
+ new_local_pt[i] = breast_user_local_pt[i];
+ }
+ if (mBreastParamsDriven[i])
+ {
+ mCharacter->setVisualParamWeight(mBreastParamsDriven[i],
+ new_local_pt[i],
+ FALSE);
+ }
+ }
+
+ mBreastLastPosition_local_pt = new_local_pt;
+
+ //
+ // End calculate new params
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Conditionally update the visual params
+ //
+
+ // Updating the visual params (i.e. what the user sees) is fairly expensive.
+ // So only update if the params have changed enough, and also take into account
+ // the graphics LOD settings.
+
+ // For non-self, if the avatar is small enough visually, then don't update.
+ const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(this) != NULL);
+ if (!is_self)
+ {
+ const F32 area_for_max_settings = 0.0;
+ const F32 area_for_min_settings = 1400.0;
+
+ const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor);
+ const F32 pixel_area = fsqrtf(mCharacter->getPixelArea());
+ if (pixel_area < area_for_this_setting)
+ {
+ return TRUE;
+ }
+ }
+
+ // If the parameter hasn't changed enough, then don't update.
+ LLVector3 position_diff = mBreastLastUpdatePosition_local_pt-new_local_pt;
+ for (U32 i=0; i < 3; i++)
+ {
+ const F32 min_delta = (1.0-lod_factor)*(mBreastParamsMax[i]-mBreastParamsMin[i])/2.0;
+ if (llabs(position_diff[i]) > min_delta)
+ {
+ mCharacter->updateVisualParams();
+ mBreastLastUpdatePosition_local_pt = new_local_pt;
+ return TRUE;
+ }
+ }
+
+ //
+ // End update visual params
+ ////////////////////////////////////////////////////////////////////////////////
+
+ return TRUE;
+}
diff --git a/indra/newview/llbreastmotion.h b/indra/newview/llbreastmotion.h
new file mode 100644
index 0000000000..8578d4ad1a
--- /dev/null
+++ b/indra/newview/llbreastmotion.h
@@ -0,0 +1,160 @@
+/**
+ * @file llbreastmotion.h
+ * @brief Implementation of LLBreastMotion class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLBREASTMOTION_H
+#define LL_LLBREASTMOTION_H
+
+//-----------------------------------------------------------------------------
+// Header files
+//-----------------------------------------------------------------------------
+#include "llmotion.h"
+#include "llframetimer.h"
+
+#define BREAST_MOTION_FADEIN_TIME 1.0f
+#define BREAST_MOTION_FADEOUT_TIME 1.0f
+
+class LLViewerVisualParam;
+
+//-----------------------------------------------------------------------------
+// class LLBreastMotion
+//-----------------------------------------------------------------------------
+class LLBreastMotion :
+ public LLMotion
+{
+public:
+ // Constructor
+ LLBreastMotion(const LLUUID &id);
+
+ // Destructor
+ virtual ~LLBreastMotion();
+
+public:
+ //-------------------------------------------------------------------------
+ // functions to support MotionController and MotionRegistry
+ //-------------------------------------------------------------------------
+
+ // static constructor
+ // all subclasses must implement such a function and register it
+ static LLMotion *create(const LLUUID &id) { return new LLBreastMotion(id); }
+
+public:
+ //-------------------------------------------------------------------------
+ // animation callbacks to be implemented by subclasses
+ //-------------------------------------------------------------------------
+
+ // motions must specify whether or not they loop
+ virtual BOOL getLoop() { return TRUE; }
+
+ // motions must report their total duration
+ virtual F32 getDuration() { return 0.0; }
+
+ // motions must report their "ease in" duration
+ virtual F32 getEaseInDuration() { return BREAST_MOTION_FADEIN_TIME; }
+
+ // motions must report their "ease out" duration.
+ virtual F32 getEaseOutDuration() { return BREAST_MOTION_FADEOUT_TIME; }
+
+ // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
+ virtual F32 getMinPixelArea();
+
+ // motions must report their priority
+ virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; }
+
+ virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; }
+
+ // run-time (post constructor) initialization,
+ // called after parameters have been set
+ // must return true to indicate success and be available for activation
+ virtual LLMotionInitStatus onInitialize(LLCharacter *character);
+
+ // called when a motion is activated
+ // must return TRUE to indicate success, or else
+ // it will be deactivated
+ virtual BOOL onActivate();
+
+ // called per time step
+ // must return TRUE while it is active, and
+ // must return FALSE when the motion is completed.
+ virtual BOOL onUpdate(F32 time, U8* joint_mask);
+
+ // called when a motion is deactivated
+ virtual void onDeactivate();
+
+protected:
+ LLVector3 toLocal(const LLVector3 &world_vector);
+ LLVector3 calculateVelocity_local(const F32 time_delta);
+ LLVector3 calculateAcceleration_local(const LLVector3 &new_char_velocity_local_vec,
+ const F32 time_delta);
+ F32 calculateTimeDelta();
+private:
+ //-------------------------------------------------------------------------
+ // joint states to be animated
+ //-------------------------------------------------------------------------
+ LLPointer<LLJointState> mChestState;
+ LLCharacter* mCharacter;
+
+
+ //-------------------------------------------------------------------------
+ // miscellaneous parameters
+ //-------------------------------------------------------------------------
+ LLViewerVisualParam *mBreastParamsUser[3];
+ LLViewerVisualParam *mBreastParamsDriven[3];
+ LLVector3 mBreastParamsMin;
+ LLVector3 mBreastParamsMax;
+
+ LLVector3 mCharLastPosition_world_pt; // Last position of the avatar
+ LLVector3 mCharLastVelocity_local_vec; // How fast the character is moving
+ LLVector3 mCharLastAcceleration_local_vec; // Change in character velocity
+
+ LLVector3 mBreastLastPosition_local_pt; // Last parameters for breast
+ LLVector3 mBreastVelocity_local_vec; // How fast the breast params are moving
+ LLVector3 mBreastLastUpdatePosition_local_pt; // Last parameters when visual update was sent
+
+
+ F32 mBreastMassParam;
+ F32 mBreastGravityParam;
+ U32 mBreastSmoothingParam;
+
+ LLVector3 mBreastSpringParam;
+ LLVector3 mBreastDampingParam;
+ LLVector3 mBreastGainParam;
+ LLVector3 mBreastMaxVelocityParam;
+ LLVector3 mBreastDragParam;
+
+ LLFrameTimer mTimer;
+ F32 mLastTime;
+
+ U32 mFileTicks;
+};
+
+#endif // LL_LLBREASTMOTION_H
+
diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp
index d6a813d608..6e77d1e336 100644
--- a/indra/newview/llbrowsernotification.cpp
+++ b/indra/newview/llbrowsernotification.cpp
@@ -29,8 +29,9 @@
#include "llnotificationhandler.h"
#include "llnotifications.h"
-#include "llfloaterreg.h"
#include "llmediactrl.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
using namespace LLNotificationsUI;
@@ -39,10 +40,19 @@ bool LLBrowserNotification::processNotification(const LLSD& notify)
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (!notification) return false;
- LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(notification->getPayload()["media_id"].asUUID());
+ LLUUID media_id = notification->getPayload()["media_id"].asUUID();
+ LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id);
if (media_instance)
{
media_instance->showNotification(notification);
}
+ else if (LLViewerMediaFocus::instance().getControlsMediaID() == media_id)
+ {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(media_id);
+ if (impl)
+ {
+ impl->showNotification(notification);
+ }
+ }
return false;
}
diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp
index d35c9ed853..e5a9be0203 100644
--- a/indra/newview/llbuycurrencyhtml.cpp
+++ b/indra/newview/llbuycurrencyhtml.cpp
@@ -33,6 +33,7 @@
#include "llfloaterreg.h"
#include "llcommandhandler.h"
#include "llviewercontrol.h"
+#include "llstatusbar.h"
// support for secondlife:///app/buycurrencyhtml/{ACTION}/{NEXT_ACTION}/{RETURN_CODE} SLapps
class LLBuyCurrencyHTMLHandler :
@@ -156,4 +157,7 @@ void LLBuyCurrencyHTML::closeDialog()
{
buy_currency_floater->closeFloater();
};
+
+ // Update L$ balance in the status bar in case L$ were purchased
+ LLStatusBar::sendMoneyBalanceRequest();
}
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 078bd73379..945a760d05 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -45,10 +45,12 @@
#include "llspeakers.h"
#include "lltextutil.h"
#include "lltransientfloatermgr.h"
+#include "llviewercontrol.h"
#include "llviewerdisplayname.h"
#include "llviewerwindow.h"
#include "llvoicechannel.h"
#include "llviewerparcelmgr.h"
+#include "llfirstuse.h"
static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids);
void reshape_floater(LLCallFloater* floater, S32 delta_height);
@@ -166,15 +168,16 @@ BOOL LLCallFloater::postBuild()
//chrome="true" hides floater caption
if (mDragHandle)
mDragHandle->setTitleVisible(TRUE);
+ updateTransparency(TT_ACTIVE); // force using active floater transparency (STORM-730)
updateSession();
-
return TRUE;
}
// virtual
void LLCallFloater::onOpen(const LLSD& /*key*/)
{
+ LLFirstUse::speak(false);
}
// virtual
@@ -205,6 +208,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 +349,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/llcapabilityprovider.h b/indra/newview/llcapabilityprovider.h
index a6e743f625..9d91245597 100644
--- a/indra/newview/llcapabilityprovider.h
+++ b/indra/newview/llcapabilityprovider.h
@@ -46,7 +46,7 @@ public:
/**
* Get host to which to send that capability request.
*/
- virtual LLHost getHost() const = 0;
+ virtual const LLHost& getHost() const = 0;
/**
* Describe this LLCapabilityProvider for logging etc.
*/
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 9153f7325f..c0c9ea1451 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -138,10 +138,7 @@ public:
if (level == "profile")
{
- LLSD params;
- params["object_id"] = getAvatarId();
-
- LLFloaterReg::showInstance("inspect_object", params);
+ LLFloaterReg::showInstance("inspect_remote_object", mObjectData);
}
else if (level == "block")
{
@@ -229,7 +226,7 @@ public:
if (mSourceType == CHAT_SOURCE_OBJECT)
{
- LLFloaterReg::showInstance("inspect_object", LLSD().with("object_id", mAvatarID));
+ LLFloaterReg::showInstance("inspect_remote_object", mObjectData);
}
else if (mSourceType == CHAT_SOURCE_AGENT)
{
@@ -251,7 +248,7 @@ public:
const LLUUID& getAvatarId () const { return mAvatarID;}
- void setup(const LLChat& chat,const LLStyle::Params& style_params)
+ void setup(const LLChat& chat, const LLStyle::Params& style_params, const LLSD& args)
{
mAvatarID = chat.mFromID;
mSessionID = chat.mSessionID;
@@ -332,7 +329,8 @@ public:
setTimeField(chat);
-
+
+ // Set up the icon.
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
if(mSourceType != CHAT_SOURCE_AGENT || mAvatarID.isNull())
@@ -352,6 +350,30 @@ public:
case CHAT_SOURCE_UNKNOWN:
icon->setValue(LLSD("Unknown_Icon"));
}
+
+ // In case the message came from an object, save the object info
+ // to be able properly show its profile.
+ if ( chat.mSourceType == CHAT_SOURCE_OBJECT)
+ {
+ std::string slurl = args["slurl"].asString();
+ if (slurl.empty())
+ {
+ LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
+ if(region)
+ {
+ LLSLURL region_slurl(region->getName(), chat.mPosAgent);
+ slurl = region_slurl.getLocationString();
+ }
+ }
+
+ LLSD payload;
+ payload["object_id"] = chat.mFromID;
+ payload["name"] = chat.mFromName;
+ payload["owner_id"] = chat.mOwnerID;
+ payload["slurl"] = LLWeb::escapeURL(slurl);
+
+ mObjectData = payload;
+ }
}
/*virtual*/ void draw()
@@ -540,6 +562,7 @@ protected:
static LLUICtrl* sInfoCtrl;
LLUUID mAvatarID;
+ LLSD mObjectData;
EChatSourceType mSourceType;
std::string mFrom;
LLUUID mSessionID;
@@ -586,7 +609,7 @@ void LLChatHistory::initFromParams(const LLChatHistory::Params& p)
LLLayoutStack::Params layout_p;
layout_p.rect = stack_rect;
layout_p.follows.flags = FOLLOWS_ALL;
- layout_p.orientation = "vertical";
+ layout_p.orientation = LLLayoutStack::VERTICAL;
layout_p.mouse_opaque = false;
LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p, this);
@@ -649,10 +672,10 @@ LLView* LLChatHistory::getSeparator()
return separator;
}
-LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params)
+LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style_params, const LLSD& args)
{
LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
- header->setup(chat,style_params);
+ header->setup(chat, style_params, args);
return header;
}
@@ -770,41 +793,31 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())
{
// for object IMs, create a secondlife:///app/objectim SLapp
- std::string url = LLSLURL("objectim", chat.mFromID, "").getSLURLString();
- url += "?name=" + chat.mFromName;
- url += "&owner=" + chat.mOwnerID.asString();
-
- std::string slurl = args["slurl"].asString();
- if (slurl.empty())
- {
- LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
- if(region)
- {
- LLSLURL region_slurl(region->getName(), chat.mPosAgent);
- slurl = region_slurl.getLocationString();
- }
- }
- url += "&slurl=" + LLURI::escape(slurl);
+ std::string url = LLViewerChat::getSenderSLURL(chat, args);
// 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);
}
}
}
@@ -830,7 +843,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
}
else
{
- view = getHeader(chat, style_params);
+ view = getHeader(chat, style_params, args);
if (mEditor->getText().size() == 0)
p.top_pad = 0;
else
@@ -895,31 +908,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
}
}
- LLTextEditor* text_editor = notify_box->getChild<LLTextEditor>("text_editor_box", TRUE);
- S32 text_heigth = 0;
- if(text_editor != NULL)
- {
- text_heigth = text_editor->getTextBoundingRect().getHeight();
- }
-
//Prepare the rect for the view
LLRect target_rect = mEditor->getDocumentView()->getRect();
// squeeze down the widget by subtracting padding off left and right
target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad();
target_rect.mRight -= mRightWidgetPad;
- notify_box->reshape(target_rect.getWidth(),
- notify_box->getRect().getHeight());
+ notify_box->reshape(target_rect.getWidth(), notify_box->getRect().getHeight());
notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom);
- if (text_editor != NULL)
- {
- S32 text_heigth_delta =
- text_editor->getTextBoundingRect().getHeight()
- - text_heigth;
- notify_box->reshape(target_rect.getWidth(),
- notify_box->getRect().getHeight() + text_heigth_delta);
- }
-
LLInlineViewSegment::Params params;
params.view = notify_box;
params.left_pad = mLeftWidgetPad;
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index ac48d7bf29..28344e6a10 100644
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -94,7 +94,7 @@ class LLChatHistory : public LLUICtrl
* Builds a message header.
* @return pointer to LLView header object.
*/
- LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params);
+ LLView* getHeader(const LLChat& chat,const LLStyle::Params& style_params, const LLSD& args);
void onClickMoreText();
diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp
index ababa71348..8584885bc9 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,33 @@ 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");
-
- style_params_name.color(userNameColor);
+ LLColor4 user_name_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
+ style_params_name.color(user_name_color);
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 = notification["sender_slurl"].asString();
+ 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..d77ebc5367 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);
@@ -181,6 +185,10 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
llassert(getEnabled());
llassert(getVisible());
+ // Focus the widget now in order to return the focus
+ // after the color picker is closed.
+ setFocus(TRUE);
+
showPicker(FALSE);
}
}
@@ -191,10 +199,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 +213,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
@@ -303,7 +323,7 @@ void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op )
// This is called when the main floatercustomize panel is closed.
// Since this class has pointers up to its parents, we need to cleanup
// this class first in order to avoid a crash.
-void LLColorSwatchCtrl::onParentFloaterClosed()
+void LLColorSwatchCtrl::closeFloaterColorPicker()
{
LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)mPickerHandle.get();
if (pickerp)
diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h
index a4ce1ca099..5bdd1712d2 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;
@@ -99,7 +100,7 @@ public:
/*virtual*/ void setEnabled( BOOL enabled );
static void onColorChanged ( void* data, EColorPickOp pick_op = COLOR_CHANGE );
- void onParentFloaterClosed();
+ void closeFloaterColorPicker();
protected:
BOOL mValid;
@@ -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/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 360ba080ac..1b6ba02aac 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -35,7 +35,7 @@
// system includes
#include <boost/tokenizer.hpp>
-#define THROTTLE_PERIOD 15 // required secs between throttled commands
+#define THROTTLE_PERIOD 5 // required secs between throttled commands
static LLCommandDispatcherListener sCommandDispatcherListener;
diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp
index ee8646aad0..65c61c4a8b 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)
{
@@ -341,7 +345,10 @@ bool LLCommandLineParser::parseCommandLine(int argc, char **argv)
bool LLCommandLineParser::parseCommandLineString(const std::string& str)
{
// Split the string content into tokens
- boost::escaped_list_separator<char> sep("\\", "\r\n ", "\"'");
+ const char* escape_chars = "\\";
+ const char* separator_chars = "\r\n ";
+ const char* quote_chars = "\"'";
+ boost::escaped_list_separator<char> sep(escape_chars, separator_chars, quote_chars);
boost::tokenizer< boost::escaped_list_separator<char> > tok(str, sep);
std::vector<std::string> tokens;
// std::copy(tok.begin(), tok.end(), std::back_inserter(tokens));
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/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 53101f0ce2..dd243397a1 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -35,6 +35,7 @@
#include "llframetimer.h"
#include "lltrans.h"
#include "llwindow.h" // beforeDialog()
+#include "llviewercontrol.h"
#if LL_LINUX || LL_SOLARIS
# include "llfilepicker.h"
@@ -53,6 +54,23 @@ LLDirPicker LLDirPicker::sInstance;
//
// Implementation
//
+
+// utility function to check if access to local file system via file browser
+// is enabled and if not, tidy up and indicate we're not allowed to do this.
+bool LLDirPicker::check_local_file_access_enabled()
+{
+ // if local file browsing is turned off, return without opening dialog
+ bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled");
+ if ( ! local_file_system_browsing_enabled )
+ {
+ mDir.clear(); // Windows
+ mFileName = NULL; // Mac/Linux
+ return false;
+ }
+
+ return true;
+}
+
#if LL_WINDOWS
LLDirPicker::LLDirPicker() :
@@ -72,6 +90,13 @@ BOOL LLDirPicker::getDir(std::string* filename)
{
return FALSE;
}
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
BOOL success = FALSE;
// Modal, so pause agent
@@ -231,7 +256,13 @@ BOOL LLDirPicker::getDir(std::string* filename)
if( mLocked ) return FALSE;
BOOL success = FALSE;
OSStatus error = noErr;
-
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
mFileName = filename;
// mNavOptions.saveFileName
@@ -289,6 +320,13 @@ void LLDirPicker::reset()
BOOL LLDirPicker::getDir(std::string* filename)
{
reset();
+
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
if (mFilePicker)
{
GtkWindow* picker = mFilePicker->buildFilePicker(false, true,
diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h
index a360293fff..2188b7edd0 100644
--- a/indra/newview/lldirpicker.h
+++ b/indra/newview/lldirpicker.h
@@ -75,6 +75,7 @@ private:
};
void buildDirname( void );
+ bool check_local_file_access_enabled();
#if LL_DARWIN
NavDialogCreationOptions mNavOptions;
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/lldriverparam.h b/indra/newview/lldriverparam.h
index a0e45cf5e5..fb1b44458c 100644
--- a/indra/newview/lldriverparam.h
+++ b/indra/newview/lldriverparam.h
@@ -30,6 +30,7 @@
#include "llviewervisualparam.h"
#include "llwearabletype.h"
+class LLPhysicsMotion;
class LLVOAvatar;
class LLWearable;
@@ -76,6 +77,7 @@ protected:
class LLDriverParam : public LLViewerVisualParam
{
+ friend class LLPhysicsMotion; // physics motion needs to access driven params directly.
public:
LLDriverParam(LLVOAvatar *avatarp);
LLDriverParam(LLWearable *wearablep);
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index a3d2941114..f781d5f3ff 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -177,10 +177,6 @@ void LLViewerDynamicTexture::postRender(BOOL success)
generateGLTexture() ;
}
- if(gGLManager.mDebugGPU)
- {
- LLGLState::dumpStates() ;
- }
success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight);
}
}
@@ -220,12 +216,6 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
LLViewerDynamicTexture *dynamicTexture = *iter;
if (dynamicTexture->needsRender())
{
- if(gGLManager.mDebugGPU)
- {
- llinfos << "class type: " << (S32)dynamicTexture->getType() << llendl;
- LLGLState::dumpStates() ;
- }
-
glClear(GL_DEPTH_BUFFER_BIT);
gDepthDirty = TRUE;
diff --git a/indra/newview/llexternaleditor.cpp b/indra/newview/llexternaleditor.cpp
new file mode 100644
index 0000000000..ed1d7e860a
--- /dev/null
+++ b/indra/newview/llexternaleditor.cpp
@@ -0,0 +1,208 @@
+/**
+ * @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 "lltrans.h"
+#include "llui.h"
+
+// static
+const std::string LLExternalEditor::sFilenameMarker = "%s";
+
+// static
+const std::string LLExternalEditor::sSetting = "ExternalEditor";
+
+LLExternalEditor::EErrorCode LLExternalEditor::setCommand(const std::string& env_var, const std::string& override)
+{
+ std::string cmd = findCommand(env_var, override);
+ if (cmd.empty())
+ {
+ llwarns << "Editor command is empty or not set" << llendl;
+ return EC_NOT_SPECIFIED;
+ }
+
+ // 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 EC_PARSE_ERROR;
+ }
+
+ // Check executable for existence.
+ std::string bin_path = tokens[0];
+ if (!LLFile::isfile(bin_path))
+ {
+ llwarns << "Editor binary [" << bin_path << "] not found" << llendl;
+ return EC_BINARY_NOT_FOUND;
+ }
+
+ // 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 EC_SUCCESS;
+}
+
+LLExternalEditor::EErrorCode LLExternalEditor::run(const std::string& file_path)
+{
+ std::string args = mArgs;
+ if (mProcess.getExecutable().empty() || args.empty())
+ {
+ llwarns << "Editor command not set" << llendl;
+ return EC_NOT_SPECIFIED;
+ }
+
+ // 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 ? EC_SUCCESS : EC_FAILED_TO_RUN;
+}
+
+// static
+std::string LLExternalEditor::getErrorMessage(EErrorCode code)
+{
+ switch (code)
+ {
+ case EC_SUCCESS: return LLTrans::getString("ok");
+ case EC_NOT_SPECIFIED: return LLTrans::getString("ExternalEditorNotSet");
+ case EC_PARSE_ERROR: return LLTrans::getString("ExternalEditorCommandParseError");
+ case EC_BINARY_NOT_FOUND: return LLTrans::getString("ExternalEditorNotFound");
+ case EC_FAILED_TO_RUN: return LLTrans::getString("ExternalEditorFailedToRun");
+ }
+
+ return LLTrans::getString("Unknown");
+}
+
+// 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..ef5db56c6e
--- /dev/null
+++ b/indra/newview/llexternaleditor.h
@@ -0,0 +1,105 @@
+/**
+ * @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:
+
+ typedef enum e_error_code {
+ EC_SUCCESS, /// No error.
+ EC_NOT_SPECIFIED, /// Editor path not specified.
+ EC_PARSE_ERROR, /// Editor command parsing error.
+ EC_BINARY_NOT_FOUND, /// Could find the editor binary (missing or not quoted).
+ EC_FAILED_TO_RUN, /// Could not execute the editor binary.
+ } EErrorCode;
+
+ /**
+ * 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 EC_SUCCESS if command is valid and refers to an existing executable,
+ * EC_NOT_SPECIFIED or EC_FAILED_TO_RUNan on error.
+ *
+ * @see sSetting
+ */
+ EErrorCode 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 EC_SUCCESS on success, error code on error.
+ */
+ EErrorCode run(const std::string& file_path);
+
+ /**
+ * Get a meaningful error message for the given status code.
+ */
+ static std::string getErrorMessage(EErrorCode code);
+
+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..fe201a6773 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)
@@ -1233,7 +1155,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (rebuild_tcoord)
{
LLVector2 tc = vf.mVertices[i].mTexCoord;
-
+
if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
{
LLVector3 vec = vf.mVertices[i].mPosition;
@@ -1409,7 +1331,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
mTexExtents[0].setVec(0,0);
mTexExtents[1].setVec(1,1);
xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt);
- xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
+ xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt);
+
+ F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ;
+ F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ;
+ mTexExtents[0][0] *= es ;
+ mTexExtents[1][0] *= es ;
+ mTexExtents[0][1] *= et ;
+ mTexExtents[1][1] *= et ;
}
mLastVertexBuffer = mVertexBuffer;
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..279904b740 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();
@@ -1141,67 +1149,18 @@ void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target
os.close();
}
-//-------------------------
//static
-LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
+void LLFastTimerView::outputAllMetrics()
{
- LLSD ret;
- LLSD cur;
-
- while (!is.eof() && LLSDSerialize::fromXML(cur, is))
+ if (LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
{
- for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
+ for (LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin();
+ iter != LLMetricPerformanceTesterBasic::sTesterMap.end(); ++iter)
{
- std::string label = iter->first;
-
- LLMetricPerformanceTester* tester = LLMetricPerformanceTester::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++)
- {
- ret[label][ tester->getMetricString(index) ] = iter->second[ tester->getMetricString(index) ] ;
- }
- }
+ LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second);
+ tester->outputTestResults();
}
}
-
- return ret;
-}
-
-//static
-void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
-{
- if(!LLMetricPerformanceTester::hasMetricPerformanceTesters())
- {
- return ;
- }
-
- //analyze baseline
- std::ifstream base_is(baseline.c_str());
- 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();
-
- //output comparision
- 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)
- {
- LLMetricPerformanceTester* tester = ((LLMetricPerformanceTester*)iter->second) ;
- tester->analyzePerformance(&os, &base, &current) ;
- }
-
- os.flush();
- os.close();
}
//static
@@ -1215,7 +1174,7 @@ void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::
if(LLFastTimer::sMetricLog)
{
- doAnalysisMetrics(baseline, target, output) ;
+ LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline, target, output) ;
return ;
}
}
diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h
index 3788897cec..b40d7ffc1a 100644
--- a/indra/newview/llfasttimerview.h
+++ b/indra/newview/llfasttimerview.h
@@ -37,12 +37,11 @@ public:
static BOOL sAnalyzePerformance;
+ static void outputAllMetrics();
static void doAnalysis(std::string baseline, std::string target, std::string output);
private:
static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ;
- static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
- static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
static LLSD analyzePerformanceLogDefault(std::istream& is) ;
public:
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 3981b887ad..0b17d64eb0 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -368,14 +368,15 @@ LLFavoritesBarCtrl::Params::Params()
LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
: LLUICtrl(p),
mFont(p.font.isProvided() ? p.font() : LLFontGL::getFontSansSerifSmall()),
- mPopupMenuHandle(),
- mInventoryItemsPopupMenuHandle(),
+ mOverflowMenuHandle(),
+ mContextMenuHandle(),
mImageDragIndication(p.image_drag_indication),
mShowDragMarker(FALSE),
mLandingTab(NULL),
mLastTab(NULL),
mTabsHighlightEnabled(TRUE)
, mUpdateDropDownItems(true)
+, mRestoreOverflowMenu(false)
{
// Register callback for menus with current registrar (will be parent panel's registrar)
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected",
@@ -402,8 +403,8 @@ LLFavoritesBarCtrl::~LLFavoritesBarCtrl()
{
gInventory.removeObserver(this);
- LLView::deleteViewByHandle(mPopupMenuHandle);
- LLView::deleteViewByHandle(mInventoryItemsPopupMenuHandle);
+ LLView::deleteViewByHandle(mOverflowMenuHandle);
+ LLView::deleteViewByHandle(mContextMenuHandle);
}
BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
@@ -414,6 +415,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)
{
@@ -517,7 +521,7 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)
gInventory.saveItemsOrder(mItems);
- LLToggleableMenu* menu = (LLToggleableMenu*) mPopupMenuHandle.get();
+ LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get();
if (menu && menu->getVisible())
{
@@ -603,6 +607,15 @@ void LLFavoritesBarCtrl::changed(U32 mask)
}
else
{
+ LLInventoryModel::item_array_t items;
+ LLInventoryModel::cat_array_t cats;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ (*i)->getSLURL();
+ }
updateButtons();
}
}
@@ -773,7 +786,7 @@ void LLFavoritesBarCtrl::updateButtons()
mChevronButton->setVisible(TRUE);
}
// Update overflow menu
- LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mPopupMenuHandle.get());
+ LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mOverflowMenuHandle.get());
if (overflow_menu && overflow_menu->getVisible())
{
overflow_menu->setVisible(FALSE);
@@ -847,7 +860,7 @@ BOOL LLFavoritesBarCtrl::postBuild()
menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu");
}
menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
- mInventoryItemsPopupMenuHandle = menu->getHandle();
+ mContextMenuHandle = menu->getHandle();
return TRUE;
}
@@ -878,7 +891,7 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it
void LLFavoritesBarCtrl::showDropDownMenu()
{
- if (mPopupMenuHandle.isDead())
+ if (mOverflowMenuHandle.isDead())
{
LLToggleableMenu::Params menu_p;
menu_p.name("favorites menu");
@@ -889,10 +902,10 @@ void LLFavoritesBarCtrl::showDropDownMenu()
menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
LLToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p);
- mPopupMenuHandle = menu->getHandle();
+ mOverflowMenuHandle = menu->getHandle();
}
- LLToggleableMenu* menu = (LLToggleableMenu*)mPopupMenuHandle.get();
+ LLToggleableMenu* menu = (LLToggleableMenu*)mOverflowMenuHandle.get();
if (menu)
{
@@ -970,11 +983,19 @@ void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S
{
mSelectedItemID = item_id;
- LLMenuGL* menu = (LLMenuGL*)mInventoryItemsPopupMenuHandle.get();
+ LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get();
if (!menu)
{
return;
}
+
+ // Remember that the context menu was shown simultaneously with the overflow menu,
+ // so that we can restore the overflow menu when user clicks a context menu item
+ // (which hides the overflow menu).
+ {
+ LLView* overflow_menu = mOverflowMenuHandle.get();
+ mRestoreOverflowMenu = overflow_menu && overflow_menu->getVisible();
+ }
// Release mouse capture so hover events go to the popup menu
// because this is happening during a mouse down.
@@ -1079,8 +1100,8 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
// Pop-up the overflow menu again (it gets hidden whenever the user clicks a context menu item).
// See EXT-4217 and STORM-207.
- LLToggleableMenu* menu = (LLToggleableMenu*) mPopupMenuHandle.get();
- if (menu && !menu->getVisible())
+ LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get();
+ if (mRestoreOverflowMenu && menu && !menu->getVisible())
{
showDropDownMenu();
}
@@ -1146,11 +1167,11 @@ void LLFavoritesBarCtrl::pastFromClipboard() const
void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
// EXT-6997 (Fav bar: Pop-up menu for LM in overflow dropdown is kept after LM was dragged away)
- // mInventoryItemsPopupMenuHandle.get() - is a pop-up menu (of items) in already opened dropdown menu.
+ // mContextMenuHandle.get() - is a pop-up menu (of items) in already opened dropdown menu.
// We have to check and set visibility of pop-up menu in such a way instead of using
// LLMenuHolderGL::hideMenus() because it will close both menus(dropdown and pop-up), but
// we need to close only pop-up menu while dropdown one should be still opened.
- LLMenuGL* menu = (LLMenuGL*)mInventoryItemsPopupMenuHandle.get();
+ LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get();
if(menu && menu->getVisible())
{
menu->setVisible(FALSE);
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 37645523f6..1a28731c4f 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -91,13 +91,14 @@ protected:
void showDropDownMenu();
- LLHandle<LLView> mPopupMenuHandle;
- LLHandle<LLView> mInventoryItemsPopupMenuHandle;
+ LLHandle<LLView> mOverflowMenuHandle;
+ LLHandle<LLView> mContextMenuHandle;
LLUUID mFavoriteFolderId;
const LLFontGL *mFont;
S32 mFirstDropDownItem;
bool mUpdateDropDownItems;
+ bool mRestoreOverflowMenu;
LLUUID mSelectedItemID;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index ca2ef5f5b8..4e16cc4217 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -290,11 +290,9 @@ BOOL LLFeatureManager::parseFeatureTable(std::string filename)
mTableVersion = version;
LLFeatureList *flp = NULL;
- while (!file.eof() && file.good())
+ while (file >> name)
{
char buffer[MAX_STRING]; /*Flawfinder: ignore*/
-
- file >> name;
if (name.substr(0,2) == "//")
{
@@ -303,13 +301,6 @@ BOOL LLFeatureManager::parseFeatureTable(std::string filename)
continue;
}
- if (name.empty())
- {
- // This is a blank line
- file.getline(buffer, MAX_STRING);
- continue;
- }
-
if (name == "list")
{
if (flp)
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index c14be89641..51e76bcf9b 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -33,6 +33,7 @@
#include "lldir.h"
#include "llframetimer.h"
#include "lltrans.h"
+#include "llviewercontrol.h"
#include "llwindow.h" // beforeDialog()
#if LL_SDL
@@ -104,6 +105,20 @@ LLFilePicker::~LLFilePicker()
// nothing
}
+// utility function to check if access to local file system via file browser
+// is enabled and if not, tidy up and indicate we're not allowed to do this.
+bool LLFilePicker::check_local_file_access_enabled()
+{
+ // if local file browsing is turned off, return without opening dialog
+ bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled");
+ if ( ! local_file_system_browsing_enabled )
+ {
+ mFiles.clear();
+ return false;
+ }
+
+ return true;
+}
const std::string LLFilePicker::getFirstFile()
{
@@ -203,6 +218,12 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
}
BOOL success = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
// don't provide default file selection
mFilesW[0] = '\0';
@@ -241,6 +262,12 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
}
BOOL success = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
// don't provide default file selection
mFilesW[0] = '\0';
@@ -304,6 +331,12 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
}
BOOL success = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
mOFN.lpstrFile = mFilesW;
if (!filename.empty())
{
@@ -370,9 +403,9 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
{
wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
- mOFN.lpstrDefExt = L"jpeg";
+ mOFN.lpstrDefExt = L"jpg";
mOFN.lpstrFilter =
- L"JPEG Images (*.jpeg)\0*.jpeg\0" \
+ L"JPEG Images (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \
L"\0";
break;
case FFSAVE_AVI:
@@ -581,6 +614,12 @@ OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter)
NavDialogRef navRef = NULL;
NavReplyRecord navReply;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
memset(&navReply, 0, sizeof(navReply));
// NOTE: we are passing the address of a local variable here.
@@ -809,6 +848,12 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
BOOL success = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
OSStatus error = noErr;
reset();
@@ -845,6 +890,12 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
BOOL success = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
OSStatus error = noErr;
reset();
@@ -876,6 +927,12 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
BOOL success = FALSE;
OSStatus error = noErr;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
reset();
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
@@ -1100,6 +1157,12 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
{
BOOL rtn = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
gViewerWindow->mWindow->beforeDialog();
reset();
@@ -1189,6 +1252,12 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
{
BOOL rtn = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
gViewerWindow->mWindow->beforeDialog();
reset();
@@ -1233,6 +1302,12 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
{
BOOL rtn = FALSE;
+ // if local file browsing is turned off, return without opening dialog
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
gViewerWindow->mWindow->beforeDialog();
reset();
@@ -1263,6 +1338,13 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
{
+ // if local file browsing is turned off, return without opening dialog
+ // (Even though this is a stub, I think we still should not return anything at all)
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
reset();
llinfos << "getSaveFile suggested filename is [" << filename
@@ -1277,6 +1359,13 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
{
+ // if local file browsing is turned off, return without opening dialog
+ // (Even though this is a stub, I think we still should not return anything at all)
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
reset();
// HACK: Static filenames for 'open' until we implement filepicker
@@ -1295,6 +1384,13 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
{
+ // if local file browsing is turned off, return without opening dialog
+ // (Even though this is a stub, I think we still should not return anything at all)
+ if ( check_local_file_access_enabled() == false )
+ {
+ return FALSE;
+ }
+
reset();
return FALSE;
}
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 5819ac4fd8..596bfa3e69 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -140,6 +140,10 @@ private:
//FILENAME_BUFFER_SIZE = 65536
FILENAME_BUFFER_SIZE = 65000
};
+
+ // utility function to check if access to local file system via file browser
+ // is enabled and if not, tidy up and indicate we're not allowed to do this.
+ bool check_local_file_access_enabled();
#if LL_WINDOWS
OPENFILENAMEW mOFN; // for open and save dialogs
diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp
index b08c113923..d63685e1af 100644
--- a/indra/newview/llfirstuse.cpp
+++ b/indra/newview/llfirstuse.cpp
@@ -78,6 +78,12 @@ void LLFirstUse::otherAvatarChatFirst(bool enable)
}
// static
+void LLFirstUse::speak(bool enable)
+{
+ firstUseNotification("FirstSpeak", enable, "HintSpeak", LLSD(), LLSD().with("target", "speak_btn").with("direction", "top"));
+}
+
+// static
void LLFirstUse::sit(bool enable)
{
firstUseNotification("FirstSit", enable, "HintSit", LLSD(), LLSD().with("target", "stand_btn").with("direction", "top"));
@@ -100,7 +106,7 @@ void LLFirstUse::useSandbox()
void LLFirstUse::notUsingDestinationGuide(bool enable)
{
// not doing this yet
- //firstUseNotification("FirstNotUseDestinationGuide", enable, "HintDestinationGuide", LLSD(), LLSD().with("target", "dest_guide_btn").with("direction", "left"));
+ firstUseNotification("FirstNotUseDestinationGuide", enable, "HintDestinationGuide", LLSD(), LLSD().with("target", "dest_guide_btn").with("direction", "top"));
}
// static
@@ -113,7 +119,15 @@ void LLFirstUse::notUsingSidePanel(bool enable)
// static
void LLFirstUse::notMoving(bool enable)
{
+ // fire off 2 notifications and rely on filtering to select the relevant one
firstUseNotification("FirstNotMoving", enable, "HintMove", LLSD(), LLSD().with("target", "move_btn").with("direction", "top"));
+ firstUseNotification("FirstNotMoving", enable, "HintMoveArrows", LLSD(), LLSD().with("target", "bottom_tray").with("direction", "top").with("hint_image", "arrow_keys.png").with("down_arrow", ""));
+}
+
+// static
+void LLFirstUse::viewPopup(bool enable)
+{
+ firstUseNotification("FirstViewPopup", enable, "HintView", LLSD(), LLSD().with("target", "view_popup").with("direction", "right"));
}
// static
diff --git a/indra/newview/llfirstuse.h b/indra/newview/llfirstuse.h
index 3b7ff6383b..4c8c9d3cde 100644
--- a/indra/newview/llfirstuse.h
+++ b/indra/newview/llfirstuse.h
@@ -68,6 +68,8 @@ object or from inventory.
13. First time you open the debug menus (ctrl-alt-shift D)
14. First time you create/edit a sculpted prim.
+
+15. Explanation of Speak&flyout buttons.
*/
class LLNotification;
@@ -85,10 +87,12 @@ public:
static void resetFirstUse();
static void otherAvatarChatFirst(bool enable = true);
+ static void speak(bool enable = true);
static void sit(bool enable = true);
static void notUsingDestinationGuide(bool enable = true);
static void notUsingSidePanel(bool enable = true);
static void notMoving(bool enable = true);
+ static void viewPopup(bool enable = true);
static void newInventory(bool enable = true);
static void receiveLindens(bool enable = true);
static void setDisplayName(bool enable = true);
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 135137069c..2873bc0059 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();
@@ -272,7 +272,7 @@ LLSD LLFloaterAbout::getInfo()
}
// TODO: Implement media plugin version query
- info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)";
+ info["QT_WEBKIT_VERSION"] = "4.7.1 (version number hard-coded)";
if (gPacketsIn > 0)
{
@@ -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/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 252c7b51ae..c95b046707 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -351,8 +351,8 @@ void LLFloaterAuction::doResetParcel()
body["media_height"] = (S32) 0;
body["auto_scale"] = (S32) 0;
body["media_loop"] = (S32) 0;
- body["obscure_media"] = (S32) 0;
- body["obscure_music"] = (S32) 0;
+ body["obscure_media"] = (S32) 0; // OBSOLETE - no longer used
+ body["obscure_music"] = (S32) 0; // OBSOLETE - no longer used
body["media_id"] = LLUUID::null;
body["group_id"] = MAINTENANCE_GROUP_ID; // Use maintenance group
body["pass_price"] = (S32) 10; // Defaults to $10
diff --git a/indra/newview/llfloaterbeacons.cpp b/indra/newview/llfloaterbeacons.cpp
index e24df948c4..316294a477 100644
--- a/indra/newview/llfloaterbeacons.cpp
+++ b/indra/newview/llfloaterbeacons.cpp
@@ -48,6 +48,7 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed)
LLPipeline::setRenderParticleBeacons( gSavedSettings.getBOOL("particlesbeacon"));
LLPipeline::setRenderHighlights( gSavedSettings.getBOOL("renderhighlights"));
LLPipeline::setRenderBeacons( gSavedSettings.getBOOL("renderbeacons"));
+ LLPipeline::setRenderMOAPBeacons( gSavedSettings.getBOOL("moapbeacon"));
mCommitCallbackRegistrar.add("Beacons.UICheck", boost::bind(&LLFloaterBeacons::onClickUICheck, this,_1));
}
@@ -96,6 +97,7 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl)
else if(name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get());
else if(name == "sounds") LLPipeline::setRenderSoundBeacons(check->get());
else if(name == "particles") LLPipeline::setRenderParticleBeacons(check->get());
+ else if(name == "moapbeacon") LLPipeline::setRenderMOAPBeacons(check->get());
else if(name == "highlights")
{
LLPipeline::toggleRenderHighlights(NULL);
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 58c79fdf15..e21a8594bc 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -267,17 +267,23 @@ void LLFloaterBuyCurrencyUI::onClickBuy()
{
mManager.buy(getString("buy_currency"));
updateUI();
+ // Update L$ balance
+ LLStatusBar::sendMoneyBalanceRequest();
}
void LLFloaterBuyCurrencyUI::onClickCancel()
{
closeFloater();
+ // Update L$ balance
+ LLStatusBar::sendMoneyBalanceRequest();
}
void LLFloaterBuyCurrencyUI::onClickErrorWeb()
{
LLWeb::loadURLExternal(mManager.errorURI());
closeFloater();
+ // Update L$ balance
+ LLStatusBar::sendMoneyBalanceRequest();
}
// static
diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp
index bde620d965..013cf74c7b 100644
--- a/indra/newview/llfloaterbuycurrencyhtml.cpp
+++ b/indra/newview/llfloaterbuycurrencyhtml.cpp
@@ -82,7 +82,7 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL()
LLStringUtil::format( buy_currency_url, replace );
// write final URL to debug console
- llinfos << "Buy currency HTML prased URL is " << buy_currency_url << llendl;
+ llinfos << "Buy currency HTML parsed URL is " << buy_currency_url << llendl;
// kick off the navigation
mBrowser->navigateTo( buy_currency_url, "text/html" );
@@ -105,7 +105,7 @@ void LLFloaterBuyCurrencyHTML::handleMediaEvent( LLPluginClassMedia* self, EMedi
//
void LLFloaterBuyCurrencyHTML::onClose( bool app_quitting )
{
- // update L$ balanace one more time
+ // Update L$ balance one more time
LLStatusBar::sendMoneyBalanceRequest();
destroy();
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index ad24c6534a..1dfa904a19 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -40,6 +40,8 @@
#include "lltoolmgr.h"
#include "lltoolfocus.h"
#include "llslider.h"
+#include "llfirstuse.h"
+#include "llhints.h"
static LLDefaultChildRegistry::Register<LLPanelCameraItem> r("panel_camera_item");
@@ -73,6 +75,8 @@ protected:
void onZoomPlusHeldDown();
void onZoomMinusHeldDown();
void onSliderValueChanged();
+ void onCameraTrack();
+ void onCameraRotate();
F32 getOrbitRate(F32 time);
private:
@@ -162,6 +166,8 @@ LLPanelCameraZoom::LLPanelCameraZoom()
mCommitCallbackRegistrar.add("Zoom.minus", boost::bind(&LLPanelCameraZoom::onZoomMinusHeldDown, this));
mCommitCallbackRegistrar.add("Zoom.plus", boost::bind(&LLPanelCameraZoom::onZoomPlusHeldDown, this));
mCommitCallbackRegistrar.add("Slider.value_changed", boost::bind(&LLPanelCameraZoom::onSliderValueChanged, this));
+ mCommitCallbackRegistrar.add("Camera.track", boost::bind(&LLPanelCameraZoom::onCameraTrack, this));
+ mCommitCallbackRegistrar.add("Camera.rotate", boost::bind(&LLPanelCameraZoom::onCameraRotate, this));
}
BOOL LLPanelCameraZoom::postBuild()
@@ -198,6 +204,18 @@ void LLPanelCameraZoom::onZoomMinusHeldDown()
gAgentCamera.setOrbitOutKey(getOrbitRate(time));
}
+void LLPanelCameraZoom::onCameraTrack()
+{
+ // EXP-202 when camera panning activated, remove the hint
+ LLFirstUse::viewPopup( false );
+}
+
+void LLPanelCameraZoom::onCameraRotate()
+{
+ // EXP-202 when camera rotation activated, remove the hint
+ LLFirstUse::viewPopup( false );
+}
+
F32 LLPanelCameraZoom::getOrbitRate(F32 time)
{
if( time < NUDGE_TIME )
@@ -294,6 +312,8 @@ LLFloaterCamera* LLFloaterCamera::findInstance()
void LLFloaterCamera::onOpen(const LLSD& key)
{
+ LLFirstUse::viewPopup();
+
LLButton *anchor_panel = LLBottomTray::getInstance()->getChild<LLButton>("camera_btn");
setDockControl(new LLDockControl(
@@ -336,6 +356,7 @@ LLFloaterCamera::LLFloaterCamera(const LLSD& val)
mCurrMode(CAMERA_CTRL_MODE_PAN),
mPrevMode(CAMERA_CTRL_MODE_PAN)
{
+ LLHints::registerHintTarget("view_popup", LLView::getHandle());
}
// virtual
@@ -343,6 +364,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/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index cec98e9992..a650886d89 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -132,9 +132,10 @@ void LLFloaterHelpBrowser::onClickOpenWebBrowser(void* user_data)
void LLFloaterHelpBrowser::openMedia(const std::string& media_url)
{
- mBrowser->setHomePageUrl(media_url);
- //mBrowser->navigateTo("data:text/html;charset=utf-8,I'd really love to be going to:<br><b>" + media_url + "</b>"); // tofu HACK for debugging =:)
- mBrowser->navigateTo(media_url);
+ // explicitly make the media mime type for this floater since it will
+ // only ever display one type of content (Web).
+ mBrowser->setHomePageUrl(media_url, "text/html");
+ mBrowser->navigateTo(media_url, "text/html");
setCurrentURL(media_url);
}
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index a6025661b7..7be4ebc690 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2871,7 +2871,10 @@ void LLPanelLandCovenant::refresh()
LLTextBox* region_landtype = getChild<LLTextBox>("region_landtype_text");
if (region_landtype)
{
- region_landtype->setText(region->getSimProductName());
+ std::string land_type;
+ bool is_land_type_localized = LLTrans::findString(land_type, region->getSimProductName());
+
+ region_landtype->setText(is_land_type_localized ? land_type : region->getSimProductName());
}
LLTextBox* region_maturity = getChild<LLTextBox>("region_maturity_text");
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index a1d291fea6..641e64247b 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -42,7 +42,8 @@
#include "llviewercamera.h"
#include "lldraghandle.h"
#include "lltextbox.h"
-#include "llviewermenu.h"
+#include "llfloaterworldmap.h"
+#include "llagent.h"
//
// Constants
@@ -61,7 +62,6 @@ const S32 MAP_PADDING_BOTTOM = 0;
LLFloaterMap::LLFloaterMap(const LLSD& key)
: LLFloater(key),
- mPopupMenu(NULL),
mTextBoxEast(NULL),
mTextBoxNorth(NULL),
mTextBoxWest(NULL),
@@ -81,8 +81,14 @@ LLFloaterMap::~LLFloaterMap()
BOOL LLFloaterMap::postBuild()
{
mMap = getChild<LLNetMap>("Net Map");
- mMap->setScale(gSavedSettings.getF32("MiniMapScale"));
- mMap->setToolTipMsg(getString("ToolTipMsg"));
+ if (gSavedSettings.getBOOL("DoubleClickTeleport"))
+ {
+ mMap->setToolTipMsg(getString("AltToolTipMsg"));
+ }
+ else if (gSavedSettings.getBOOL("DoubleClickShowWorldMap"))
+ {
+ mMap->setToolTipMsg(getString("ToolTipMsg"));
+ }
sendChildToBack(mMap);
mTextBoxNorth = getChild<LLTextBox> ("floater_map_north");
@@ -94,17 +100,6 @@ BOOL LLFloaterMap::postBuild()
mTextBoxSouthWest = getChild<LLTextBox> ("floater_map_southwest");
mTextBoxNorthWest = getChild<LLTextBox> ("floater_map_northwest");
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
- registrar.add("Minimap.Zoom", boost::bind(&LLFloaterMap::handleZoom, this, _2));
- registrar.add("Minimap.Tracker", boost::bind(&LLFloaterMap::handleStopTracking, this, _2));
-
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- if (mPopupMenu && !LLTracker::isTracking(0))
- {
- mPopupMenu->setItemEnabled ("Stop Tracking", false);
- }
-
stretchMiniMap(getRect().getWidth() - MAP_PADDING_LEFT - MAP_PADDING_RIGHT
,getRect().getHeight() - MAP_PADDING_TOP - MAP_PADDING_BOTTOM);
@@ -122,21 +117,35 @@ 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);
- return TRUE;
-}
+ if (isMinimized())
+ {
+ setMinimized(FALSE);
+ return TRUE;
+ }
-BOOL LLFloaterMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- if (mPopupMenu)
+ LLVector3d pos_global = mMap->viewPosToGlobal(x, y);
+
+ // If we're not tracking a beacon already, double-click will set one
+ if (!LLTracker::isTracking(NULL))
{
- mPopupMenu->buildDrawLabels();
- mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ 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 if (gSavedSettings.getBOOL("DoubleClickShowWorldMap"))
+ {
+ LLFloaterReg::showInstance("world_map");
}
return TRUE;
}
@@ -211,11 +220,6 @@ void LLFloaterMap::draw()
getDragHandle()->setMouseOpaque(TRUE);
}
- if (LLTracker::isTracking(0))
- {
- mPopupMenu->setItemEnabled ("Stop Tracking", true);
- }
-
LLFloater::draw();
}
@@ -261,7 +265,16 @@ void LLFloaterMap::handleZoom(const LLSD& userdata)
std::string level = userdata.asString();
F32 scale = 0.0f;
- if (level == std::string("close"))
+ if (level == std::string("default"))
+ {
+ LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale");
+ if(pvar)
+ {
+ pvar->resetToDefault();
+ scale = gSavedSettings.getF32("MiniMapScale");
+ }
+ }
+ else if (level == std::string("close"))
scale = LLNetMap::MAP_SCALE_MAX;
else if (level == std::string("medium"))
scale = LLNetMap::MAP_SCALE_MID;
@@ -269,19 +282,10 @@ void LLFloaterMap::handleZoom(const LLSD& userdata)
scale = LLNetMap::MAP_SCALE_MIN;
if (scale != 0.0f)
{
- gSavedSettings.setF32("MiniMapScale", scale );
mMap->setScale(scale);
}
}
-void LLFloaterMap::handleStopTracking (const LLSD& userdata)
-{
- if (mPopupMenu)
- {
- mPopupMenu->setItemEnabled ("Stop Tracking", false);
- LLTracker::stopTracking ((void*)LLTracker::isTracking(NULL));
- }
-}
void LLFloaterMap::setMinimized(BOOL b)
{
LLFloater::setMinimized(b);
diff --git a/indra/newview/llfloatermap.h b/indra/newview/llfloatermap.h
index 4cbb48fb3e..5cf66a594b 100644
--- a/indra/newview/llfloatermap.h
+++ b/indra/newview/llfloatermap.h
@@ -29,7 +29,6 @@
#include "llfloater.h"
-class LLMenuGL;
class LLNetMap;
class LLTextBox;
@@ -44,7 +43,6 @@ public:
/*virtual*/ BOOL postBuild();
/*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
- /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void draw();
/*virtual*/ void onFocusLost();
@@ -54,14 +52,11 @@ public:
private:
void handleZoom(const LLSD& userdata);
- void handleStopTracking (const LLSD& userdata);
void setDirectionPos( LLTextBox* text_box, F32 rotation );
void updateMinorDirections();
void stretchMiniMap(S32 width,S32 height);
- LLMenuGL* mPopupMenu;
-
LLTextBox* mTextBoxEast;
LLTextBox* mTextBoxNorth;
LLTextBox* mTextBoxWest;
diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp
index d20092e344..7a670dd90c 100644
--- a/indra/newview/llfloatermediabrowser.cpp
+++ b/indra/newview/llfloatermediabrowser.cpp
@@ -306,17 +306,14 @@ void LLFloaterMediaBrowser::setCurrentURL(const std::string& url)
{
mCurrentURL = url;
- // redirects will navigate momentarily to about:blank, don't add to history
- if (mCurrentURL != "about:blank")
- {
- mAddressCombo->remove(mCurrentURL);
- mAddressCombo->add(mCurrentURL);
- mAddressCombo->selectByValue(mCurrentURL);
+ mAddressCombo->remove(mCurrentURL);
+ mAddressCombo->add(mCurrentURL);
+ mAddressCombo->selectByValue(mCurrentURL);
+
+ // Serialize url history
+ LLURLHistory::removeURL("browser", mCurrentURL);
+ LLURLHistory::addURL("browser", mCurrentURL);
- // Serialize url history
- LLURLHistory::removeURL("browser", mCurrentURL);
- LLURLHistory::addURL("browser", mCurrentURL);
- }
getChildView("back")->setEnabled(mBrowser->canNavigateBack());
getChildView("forward")->setEnabled(mBrowser->canNavigateForward());
getChildView("reload")->setEnabled(TRUE);
@@ -334,8 +331,15 @@ void LLFloaterMediaBrowser::onClickRefresh(void* user_data)
{
LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data;
- self->mAddressCombo->remove(0);
- self->mBrowser->navigateTo(self->mCurrentURL);
+ if( self->mBrowser->getMediaPlugin() && self->mBrowser->getMediaPlugin()->pluginSupportsMediaBrowser())
+ {
+ bool ignore_cache = true;
+ self->mBrowser->getMediaPlugin()->browse_reload( ignore_cache );
+ }
+ else
+ {
+ self->mBrowser->navigateTo(self->mCurrentURL);
+ }
}
//static
diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp
index 42dc60f9e0..29af81d64c 100644
--- a/indra/newview/llfloaternotificationsconsole.cpp
+++ b/indra/newview/llfloaternotificationsconsole.cpp
@@ -174,6 +174,7 @@ BOOL LLFloaterNotificationConsole::postBuild()
// these are in the order of processing
addChannel("Unexpired");
addChannel("Ignore");
+ addChannel("VisibilityRules");
addChannel("Visible", true);
// all the ones below attach to the Visible channel
addChannel("Persistent");
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index e8e9f76912..dd0b1d999c 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -112,11 +112,14 @@ LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLView
// Take the images from the caller
// It's now our job to clean them up
LLFloaterPostcard* instance = LLFloaterReg::showTypedInstance<LLFloaterPostcard>("postcard", LLSD(img->getID()));
-
- instance->mJPEGImage = jpeg;
- instance->mViewerImage = img;
- instance->mImageScale = image_scale;
- instance->mPosTakenGlobal = pos_taken_global;
+
+ if (instance) // may be 0 if we're in mouselook mode
+ {
+ instance->mJPEGImage = jpeg;
+ instance->mViewerImage = img;
+ instance->mImageScale = image_scale;
+ instance->mPosTakenGlobal = pos_taken_global;
+ }
return instance;
}
@@ -128,6 +131,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 +154,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 +169,7 @@ void LLFloaterPostcard::draw()
rect.getWidth(),
rect.getHeight(),
mViewerImage.get(),
- LLColor4::white);
+ LLColor4::white % alpha);
}
glMatrixMode(GL_TEXTURE);
glPopMatrix();
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 2bea3d37ff..ffbb0efad3 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -105,6 +105,7 @@
#include "llteleporthistorystorage.h"
#include "lllogininstance.h" // to check if logged in yet
+#include "llsdserialize.h"
const F32 MAX_USER_FAR_CLIP = 512.f;
const F32 MIN_USER_FAR_CLIP = 64.f;
@@ -282,8 +283,12 @@ std::string LLFloaterPreference::sSkin = "";
LLFloaterPreference::LLFloaterPreference(const LLSD& key)
: LLFloater(key),
mGotPersonalInfo(false),
- mOriginalIMViaEmail(false)
+ mOriginalIMViaEmail(false),
+ mLanguageChanged(false),
+ mDoubleClickActionDirty(false),
+ mFavoritesRecordMayExist(false)
{
+
//Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
static bool registered_dialog = false;
@@ -320,14 +325,61 @@ 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));
-
- sSkin = gSavedSettings.getString("SkinCurrent");
+ sSkin = gSavedSettings.getString("SkinCurrent");
+
+ mCommitCallbackRegistrar.add("Pref.CommitDoubleClickChekbox", boost::bind(&LLFloaterPreference::onDoubleClickCheckBox, this, _1));
+ mCommitCallbackRegistrar.add("Pref.CommitRadioDoubleClick", boost::bind(&LLFloaterPreference::onDoubleClickRadio, this));
+
gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2));
gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2));
+
+ LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
+}
+
+void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type )
+{
+ if ( APT_PROPERTIES == type )
+ {
+ const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData );
+ if( pAvatarData && gAgent.getID() == pAvatarData->avatar_id )
+ {
+ storeAvatarProperties( pAvatarData );
+ processProfileProperties( pAvatarData );
+ }
+ }
}
+void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData )
+{
+ mAvatarProperties.avatar_id = gAgent.getID();
+ mAvatarProperties.image_id = pAvatarData->image_id;
+ mAvatarProperties.fl_image_id = pAvatarData->fl_image_id;
+ mAvatarProperties.about_text = pAvatarData->about_text;
+ mAvatarProperties.fl_about_text = pAvatarData->fl_about_text;
+ mAvatarProperties.profile_url = pAvatarData->profile_url;
+ mAvatarProperties.flags = pAvatarData->flags;
+ mAvatarProperties.allow_publish = pAvatarData->flags & AVATAR_ALLOW_PUBLISH;
+}
+
+void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarData )
+{
+ getChild<LLUICtrl>("online_searchresults")->setValue( (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH) );
+}
+
+void LLFloaterPreference::saveAvatarProperties( void )
+{
+ mAvatarProperties.allow_publish = getChild<LLUICtrl>("online_searchresults")->getValue();
+ if ( mAvatarProperties.allow_publish )
+ {
+ mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH;
+ }
+
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties );
+}
+
+
BOOL LLFloaterPreference::postBuild()
{
gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2));
@@ -338,14 +390,20 @@ BOOL LLFloaterPreference::postBuild()
gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2));
+ gSavedSettings.getControl("ChatBubbleOpacity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onNameTagOpacityChange, this, _2));
+
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
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)
{
@@ -405,6 +463,8 @@ void LLFloaterPreference::saveSettings()
void LLFloaterPreference::apply()
{
+ LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this );
+
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
if (sSkin != gSavedSettings.getString("SkinCurrent"))
{
@@ -475,6 +535,42 @@ void LLFloaterPreference::apply()
gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);
}
}
+
+ saveAvatarProperties();
+
+ if (mDoubleClickActionDirty)
+ {
+ updateDoubleClickSettings();
+ mDoubleClickActionDirty = false;
+ }
+
+ if (mFavoritesRecordMayExist && !gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
+ {
+ removeFavoritesRecordOfUser();
+ }
+}
+
+void LLFloaterPreference::removeFavoritesRecordOfUser()
+{
+ mFavoritesRecordMayExist = false;
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
+ LLSD fav_llsd;
+ llifstream file;
+ file.open(filename);
+ if (!file.is_open()) return;
+ LLSDSerialize::fromXML(fav_llsd, file);
+
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( gAgentID, &av_name );
+ if (fav_llsd.has(av_name.getLegacyName()))
+ {
+ fav_llsd.erase(av_name.getLegacyName());
+ }
+
+ llofstream out_file;
+ out_file.open(filename);
+ LLSDSerialize::toPrettyXML(fav_llsd, out_file);
+
}
void LLFloaterPreference::cancel()
@@ -501,10 +597,17 @@ void LLFloaterPreference::cancel()
// reverts any changes to current skin
gSavedSettings.setString("SkinCurrent", sSkin);
+
+ if (mDoubleClickActionDirty)
+ {
+ updateDoubleClickControls();
+ mDoubleClickActionDirty = false;
+ }
}
void LLFloaterPreference::onOpen(const LLSD& key)
{
+
// this variable and if that follows it are used to properly handle busy mode response message
static bool initialized = FALSE;
// if user is logged in and we haven't initialized busy_response yet, do it
@@ -531,7 +634,7 @@ void LLFloaterPreference::onOpen(const LLSD& key)
(gAgent.isMature() || gAgent.isGodlike());
LLComboBox* maturity_combo = getChild<LLComboBox>("maturity_desired_combobox");
-
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest( gAgent.getID() );
if (can_choose_maturity)
{
// if they're not adult or a god, they shouldn't see the adult selection, so delete it
@@ -553,6 +656,14 @@ void LLFloaterPreference::onOpen(const LLSD& key)
getChildView("maturity_desired_combobox")->setVisible( false);
}
+ if (LLStartUp::getStartupState() == STATE_STARTED)
+ {
+ mFavoritesRecordMayExist = gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin");
+ }
+
+ // Forget previous language changes.
+ mLanguageChanged = false;
+
// Display selected maturity icons.
onChangeMaturity();
@@ -710,6 +821,28 @@ 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::onNameTagOpacityChange(const LLSD& newvalue)
+{
+ LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background");
+ if (color_swatch)
+ {
+ LLColor4 new_color = color_swatch->get();
+ color_swatch->set( new_color.setAlpha(newvalue.asReal()) );
+ }
+}
+
void LLFloaterPreference::onClickSetCache()
{
std::string cur_name(gSavedSettings.getString("CacheLocation"));
@@ -803,7 +936,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)
@@ -1067,6 +1200,7 @@ void LLFloaterPreference::refresh()
updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail", true), getChild<LLTextBox>("FlexibleMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail", true), getChild<LLTextBox>("TreeMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail", true), getChild<LLTextBox>("AvatarMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail", true), getChild<LLTextBox>("AvatarPhysicsDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true));
updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true));
@@ -1155,7 +1289,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 +1303,7 @@ void LLFloaterPreference::resetAllIgnored()
{
if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- iter->second->mForm->setIgnored(true);
+ iter->second->mForm->setIgnored(false);
}
}
}
@@ -1182,7 +1316,7 @@ void LLFloaterPreference::setAllIgnored()
{
if (iter->second->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
{
- iter->second->mForm->setIgnored(false);
+ iter->second->mForm->setIgnored(true);
}
}
}
@@ -1241,12 +1375,13 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
// getChild<LLUICtrl>("busy_response")->setValue(gSavedSettings.getString("BusyModeResponse2"));
+ getChildView("favorites_on_login_check")->setEnabled(TRUE);
getChildView("log_nearby_chat")->setEnabled(TRUE);
getChildView("log_instant_messages")->setEnabled(TRUE);
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 +1453,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)
{
@@ -1343,6 +1540,7 @@ LLPanelPreference::LLPanelPreference()
: LLPanel()
{
mCommitCallbackRegistrar.add("Pref.setControlFalse", boost::bind(&LLPanelPreference::setControlFalse,this, _2));
+ mCommitCallbackRegistrar.add("Pref.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelPreference::updateMediaAutoPlayCheckbox, this, _1));
}
//virtual
@@ -1394,6 +1592,10 @@ BOOL LLPanelPreference::postBuild()
{
getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2));
}
+ if (hasChild("favorites_on_login_check"))
+ {
+ getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2));
+ }
// Panel Advanced
if (hasChild("modifier_combo"))
@@ -1461,6 +1663,14 @@ void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& v
}
}
+void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value)
+{
+ if (checkbox && checkbox->getValue())
+ {
+ LLNotificationsUtil::add("FavoritesOnLogin");
+ }
+}
+
void LLPanelPreference::cancel()
{
for (control_values_map_t::iterator iter = mSavedValues.begin();
@@ -1492,6 +1702,21 @@ void LLPanelPreference::setControlFalse(const LLSD& user_data)
control->set(LLSD(FALSE));
}
+void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
+{
+ std::string name = ctrl->getName();
+
+ // Disable "Allow Media to auto play" only when both
+ // "Streaming Music" and "Media" are unchecked. STORM-513.
+ if ((name == "enable_music") || (name == "enable_media"))
+ {
+ bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
+ bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
+
+ getChild<LLCheckBoxCtrl>("media_auto_play_btn")->setEnabled(music_enabled || media_enabled);
+ }
+}
+
static LLRegisterPanelClassWrapper<LLPanelPreferenceGraphics> t_pref_graph("panel_preference_graphics");
BOOL LLPanelPreferenceGraphics::postBuild()
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index e99731b92e..46014804ec 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -34,6 +34,7 @@
#define LL_LLFLOATERPREFERENCE_H
#include "llfloater.h"
+#include "llavatarpropertiesprocessor.h"
class LLPanelPreference;
class LLPanelLCD;
@@ -55,7 +56,7 @@ typedef enum
// Floater to control preferences (display, audio, bandwidth, general.
-class LLFloaterPreference : public LLFloater
+class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver
{
public:
LLFloaterPreference(const LLSD& key);
@@ -77,12 +78,19 @@ public:
// translate user's busy response message according to current locale if message is default, otherwise do nothing
static void initBusyResponse();
+ void processProperties( void* pData, EAvatarProcessorType type );
+ void processProfileProperties(const LLAvatarData* pAvatarData );
+ void storeAvatarProperties( const LLAvatarData* pAvatarData );
+ void saveAvatarProperties( void );
+
protected:
void onBtnOK();
void onBtnCancel();
void onBtnApply();
void onClickBrowserClearCache();
+ void onLanguageChange();
+ void onNameTagOpacityChange(const LLSD& newvalue);
// set value of "BusyResponseChanged" in account settings depending on whether busy response
// string differs from default after user changes.
@@ -95,6 +103,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.
@@ -143,13 +159,23 @@ public:
void buildPopupLists();
static void refreshSkin(void* data);
+ // Remove record of current user's favorites from file on disk.
+ void removeFavoritesRecordOfUser();
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;
+ // Record of current user's favorites may be stored in file on disk.
+ bool mFavoritesRecordMayExist;
std::string mDirectoryVisibility;
+
+ LLAvatarData mAvatarProperties;
};
class LLPanelPreference : public LLPanel
@@ -163,6 +189,10 @@ public:
void setControlFalse(const LLSD& user_data);
virtual void setHardwareDefaults(){};
+ // Disables "Allow Media to auto play" check box only when both
+ // "Streaming Music" and "Media" are unchecked. Otherwise enables it.
+ void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl);
+
// This function squirrels away the current values of the controls so that
// cancel() can restore them.
virtual void saveSettings();
@@ -170,6 +200,8 @@ public:
private:
//for "Only friends and groups can call or IM me"
static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&);
+ //for "Show my Favorite Landmarks at Login"
+ static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value);
typedef std::map<LLControlVariable*, LLSD> control_values_map_t;
control_values_map_t mSavedValues;
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
new file mode 100644
index 0000000000..ada0dcf569
--- /dev/null
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -0,0 +1,221 @@
+/**
+ * @file llfloaterregiondebugconsole.h
+ * @author Brad Kittenbrink <brad@lindenlab.com>
+ * @brief Quick and dirty console for region debug settings
+ *
+ * $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 "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..3aa525724e
--- /dev/null
+++ b/indra/newview/llfloaterregiondebugconsole.h
@@ -0,0 +1,57 @@
+/**
+ * @file llfloaterregiondebugconsole.h
+ * @author Brad Kittenbrink <brad@lindenlab.com>
+ * @brief Quick and dirty console for region debug settings
+ *
+ * $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_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/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 3ed4aec89a..2041fac8d8 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -200,5 +200,5 @@ void LLFloaterSearch::search(const LLSD &key)
url = LLWeb::expandURLSubstitutions(url, subs);
// and load the URL in the web view
- mBrowser->navigateTo(url);
+ mBrowser->navigateTo(url, "text/html");
}
diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp
index 71882fbb83..07f5220ab7 100644
--- a/indra/newview/llfloatersettingsdebug.cpp
+++ b/indra/newview/llfloatersettingsdebug.cpp
@@ -178,7 +178,7 @@ void LLFloaterSettingsDebug::onClickDefault()
if (controlp)
{
- controlp->resetToDefault();
+ controlp->resetToDefault(true);
updateControl(controlp);
}
}
diff --git a/indra/newview/llfloatersidetraytab.cpp b/indra/newview/llfloatersidetraytab.cpp
index f13b4db3a0..94407e6da0 100644
--- a/indra/newview/llfloatersidetraytab.cpp
+++ b/indra/newview/llfloatersidetraytab.cpp
@@ -30,6 +30,7 @@
// newview includes
#include "lltransientfloatermgr.h"
+#include "llsidetray.h"
LLFloaterSideTrayTab::LLFloaterSideTrayTab(const LLSD& key, const Params& params)
: LLFloater(key, params)
@@ -43,3 +44,8 @@ LLFloaterSideTrayTab::~LLFloaterSideTrayTab()
{
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::GLOBAL, this);
}
+
+void LLFloaterSideTrayTab::onClose(bool app_quitting)
+{
+ LLSideTray::getInstance()->setTabDocked(getName(), true);
+}
diff --git a/indra/newview/llfloatersidetraytab.h b/indra/newview/llfloatersidetraytab.h
index e47f82e8ba..89f2444a0e 100644
--- a/indra/newview/llfloatersidetraytab.h
+++ b/indra/newview/llfloatersidetraytab.h
@@ -42,6 +42,8 @@ class LLFloaterSideTrayTab : public LLFloater
public:
LLFloaterSideTrayTab(const LLSD& key, const Params& params = getDefaultParams());
~LLFloaterSideTrayTab();
+
+ void onClose(bool app_quitting);
};
#endif // LL_LLFLOATERSIDETRAYTAB_H
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 36e8ad9dfc..add591895b 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1212,8 +1212,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;
}
@@ -1365,6 +1363,36 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
floater->getChildView("auto_snapshot_check")->setVisible( is_advance);
floater->getChildView("image_quality_slider")->setVisible( is_advance && show_slider);
+ if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
+ { //clamp snapshot resolution to window size when showing UI or HUD in snapshot
+
+ LLSpinCtrl* width_ctrl = floater->getChild<LLSpinCtrl>("snapshot_width");
+ LLSpinCtrl* height_ctrl = floater->getChild<LLSpinCtrl>("snapshot_height");
+
+ S32 width = gViewerWindow->getWindowWidthRaw();
+ S32 height = gViewerWindow->getWindowHeightRaw();
+
+ width_ctrl->setMaxValue(width);
+
+ height_ctrl->setMaxValue(height);
+
+ if (width_ctrl->getValue().asInteger() > width)
+ {
+ width_ctrl->forceSetValue(width);
+ }
+ if (height_ctrl->getValue().asInteger() > height)
+ {
+ height_ctrl->forceSetValue(height);
+ }
+ }
+ else
+ {
+ LLSpinCtrl* width = floater->getChild<LLSpinCtrl>("snapshot_width");
+ width->setMaxValue(6016);
+ LLSpinCtrl* height = floater->getChild<LLSpinCtrl>("snapshot_height");
+ height->setMaxValue(6016);
+ }
+
LLSnapshotLivePreview* previewp = getPreviewView(floater);
BOOL got_bytes = previewp && previewp->getDataSize() > 0;
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
@@ -1812,6 +1840,13 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL
previewp->getSize(width, height);
+ if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot"))
+ { //clamp snapshot resolution to window size when showing UI or HUD in snapshot
+ width = llmin(width, gViewerWindow->getWindowWidthRaw());
+ height = llmin(height, gViewerWindow->getWindowHeightRaw());
+ }
+
+
if(checkImageSize(previewp, width, height, TRUE, previewp->getMaxImageSize()))
{
resetSnapshotSizeOnUI(view, width, height) ;
@@ -2191,9 +2226,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/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 370bf05bf7..364fbad193 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -220,6 +220,8 @@ BOOL LLFloaterTools::postBuild()
mRadioGroupEdit = getChild<LLRadioGroup>("edit_radio_group");
mBtnGridOptions = getChild<LLButton>("Options...");
mTitleMedia = getChild<LLMediaCtrl>("title_media");
+ mBtnLink = getChild<LLButton>("link_btn");
+ mBtnUnlink = getChild<LLButton>("unlink_btn");
mCheckSelectIndividual = getChild<LLCheckBoxCtrl>("checkbox edit linked parts");
getChild<LLUICtrl>("checkbox edit linked parts")->setValue((BOOL)gSavedSettings.getBOOL("EditLinkedParts"));
@@ -315,6 +317,9 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mBtnRotateReset(NULL),
mBtnRotateRight(NULL),
+ mBtnLink(NULL),
+ mBtnUnlink(NULL),
+
mBtnDelete(NULL),
mBtnDuplicate(NULL),
mBtnDuplicateInPlace(NULL),
@@ -341,7 +346,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mNeedMediaTitle(TRUE)
{
gFloaterTools = this;
-
+
setAutoFocus(FALSE);
mFactoryMap["General"] = LLCallbackMap(createPanelPermissions, this);//LLPanelPermissions
mFactoryMap["Object"] = LLCallbackMap(createPanelObject, this);//LLPanelObject
@@ -366,6 +371,9 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mCommitCallbackRegistrar.add("BuildTool.DeleteMedia", boost::bind(&LLFloaterTools::onClickBtnDeleteMedia,this));
mCommitCallbackRegistrar.add("BuildTool.EditMedia", boost::bind(&LLFloaterTools::onClickBtnEditMedia,this));
+ mCommitCallbackRegistrar.add("BuildTool.LinkObjects", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance()));
+ mCommitCallbackRegistrar.add("BuildTool.UnlinkObjects", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
+
}
LLFloaterTools::~LLFloaterTools()
@@ -566,6 +574,12 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
bool linked_parts = gSavedSettings.getBOOL("EditLinkedParts");
getChildView("RenderingCost")->setVisible( !linked_parts && (edit_visible || focus_visible || move_visible) && sShowObjectCost);
+ mBtnLink->setVisible(edit_visible);
+ mBtnUnlink->setVisible(edit_visible);
+
+ mBtnLink->setEnabled(LLSelectMgr::instance().enableLinkObjects());
+ mBtnUnlink->setEnabled(LLSelectMgr::instance().enableUnlinkObjects());
+
if (mCheckSelectIndividual)
{
mCheckSelectIndividual->setVisible(edit_visible);
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 87c3d2ab47..fd81a75397 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -135,6 +135,8 @@ public:
LLRadioGroup* mRadioGroupEdit;
LLCheckBoxCtrl *mCheckSelectIndividual;
+ LLButton* mBtnLink;
+ LLButton* mBtnUnlink;
LLCheckBoxCtrl* mCheckSnapToGrid;
LLButton* mBtnGridOptions;
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index e5c4547226..87d048c15b 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);
@@ -197,11 +185,9 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
have_extended_data = true;
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);
+ msg->getS32("DataExtended", "PublicURLs", public_urls, block);
}
-
LLSD element;
element["id"] = task_id;
@@ -237,7 +223,8 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
columns[3]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
columns[3]["font"] = "SANSSERIF";
columns[4]["column"] = "time";
- columns[4]["value"] = formatted_time((time_t)time_stamp);
+ columns[4]["type"] = "date";
+ columns[4]["value"] = LLDate((time_t)time_stamp);
columns[4]["font"] = "SANSSERIF";
if (mCurrentMode == STAT_REPORT_TOP_SCRIPTS
@@ -252,16 +239,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..0d8601410a 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,66 @@ 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
- {
- 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)
+ // Determine file to edit.
+ std::string file_path;
{
- 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)
+ // 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
{
- std::string warning = std::string("Unable to find a valid path to the specified executable for XUI XML editing: ") + exe_path;
- popupAndPrintWarning(warning);
- return;
+ 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
}
- 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));
+ // Set the editor command.
+ std::string cmd_override;
+ {
+ std::string bin = mEditorPathTextBox->getText();
+ if (!bin.empty())
+ {
+ // surround command with double quotes for the case if the path contains spaces
+ if (bin.find("\"") == std::string::npos)
+ {
+ bin = "\"" + bin + "\"";
+ }
- 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"'
+ std::string args = mEditorArgsTextBox->getText();
+ cmd_override = bin + " " + args;
+ }
+ }
- 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());
+ LLExternalEditor::EErrorCode status = mExternalEditor.setCommand("LL_XUI_EDITOR", cmd_override);
+ if (status != LLExternalEditor::EC_SUCCESS)
+ {
+ std::string warning;
- // 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))
+ if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error.
{
- // DWORD dwErr = GetLastError();
- std::string warning = "Creating editor process failed!";
- popupAndPrintWarning(warning);
+ warning = getString("ExternalEditorNotSet");
}
else
{
- // 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
+ warning = LLExternalEditor::getErrorMessage(status);
}
- 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)
- {
- 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)
- {
- // 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);
- }
-
- // parent
- delete[] fakeargv;
- // sGatewayPID = id;
- }
-#endif // LL_WINDOWS
+ popupAndPrintWarning(warning);
+ return;
}
- else
+
+ // Run the editor.
+ if (mExternalEditor.run(file_path) != LLExternalEditor::EC_SUCCESS)
{
- std::string warning = "Unable to find path to external XML editor for XUI preview tool";
- popupAndPrintWarning(warning);
+ popupAndPrintWarning(LLExternalEditor::getErrorMessage(status));
+ return;
}
}
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
new file mode 100644
index 0000000000..058567492b
--- /dev/null
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -0,0 +1,402 @@
+/**
+ * @file llfloaterwebcontent.cpp
+ * @brief floater for displaying web content - e.g. profiles and search (eventually)
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llcombobox.h"
+#include "lliconctrl.h"
+#include "llfloaterreg.h"
+#include "lllayoutstack.h"
+#include "llpluginclassmedia.h"
+#include "llprogressbar.h"
+#include "lltextbox.h"
+#include "llurlhistory.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+#include "llfloaterwebcontent.h"
+
+LLFloaterWebContent::LLFloaterWebContent( const LLSD& key )
+ : LLFloater( key )
+{
+ mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
+ mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
+ mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
+ mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
+ mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
+ mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
+}
+
+BOOL LLFloaterWebContent::postBuild()
+{
+ // these are used in a bunch of places so cache them
+ mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" );
+ mAddressCombo = getChild< LLComboBox >( "address" );
+ mStatusBarText = getChild< LLTextBox >( "statusbartext" );
+ mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" );
+
+ // observe browser events
+ mWebBrowser->addObserver( this );
+
+ // these buttons are always enabled
+ getChildView("reload")->setEnabled( true );
+ getChildView("popexternal")->setEnabled( true );
+
+ // cache image for secure browsing
+ mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
+
+ // initialize the URL history using the system URL History manager
+ initializeURLHistory();
+
+ return TRUE;
+}
+
+void LLFloaterWebContent::initializeURLHistory()
+{
+ // start with an empty list
+ LLCtrlListInterface* url_list = childGetListInterface("address");
+ if (url_list)
+ {
+ url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ // Get all of the entries in the "browser" collection
+ LLSD browser_history = LLURLHistory::getURLHistory("browser");
+ LLSD::array_iterator iter_history =
+ browser_history.beginArray();
+ LLSD::array_iterator end_history =
+ browser_history.endArray();
+ for(; iter_history != end_history; ++iter_history)
+ {
+ std::string url = (*iter_history).asString();
+ if(! url.empty())
+ url_list->addSimpleElement(url);
+ }
+}
+
+//static
+void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
+{
+ lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
+
+ std::string tag = target;
+
+ if(target.empty() || target == "_blank")
+ {
+ if(!uuid.empty())
+ {
+ tag = uuid;
+ }
+ else
+ {
+ // create a unique tag for this instance
+ LLUUID id;
+ id.generate();
+ tag = id.asString();
+ }
+ }
+
+ S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit");
+
+ if(LLFloaterReg::findInstance("web_content", tag) != NULL)
+ {
+ // There's already a web browser for this tag, so we won't be opening a new window.
+ }
+ else if(browser_window_limit != 0)
+ {
+ // showInstance will open a new window. Figure out how many web browsers are already open,
+ // and close the least recently opened one if this will put us over the limit.
+
+ LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content");
+ lldebugs << "total instance count is " << instances.size() << llendl;
+
+ for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
+ {
+ lldebugs << " " << (*iter)->getKey() << llendl;
+ }
+
+ if(instances.size() >= (size_t)browser_window_limit)
+ {
+ // Destroy the least recently opened instance
+ (*instances.begin())->closeFloater();
+ }
+ }
+
+ LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag));
+ llassert(browser);
+ if(browser)
+ {
+ browser->mUUID = uuid;
+
+ // tell the browser instance to load the specified URL
+ browser->open_media(url, target);
+ LLViewerMedia::proxyWindowOpened(target, uuid);
+ }
+}
+
+//static
+void LLFloaterWebContent::closeRequest(const std::string &uuid)
+{
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
+ lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
+ lldebugs << " " << i->mUUID << llendl;
+ if (i && i->mUUID == uuid)
+ {
+ i->closeFloater(false);
+ return;
+ }
+ }
+}
+
+//static
+void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height)
+{
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
+ lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
+ lldebugs << " " << i->mUUID << llendl;
+ if (i && i->mUUID == uuid)
+ {
+ i->geometryChanged(x, y, width, height);
+ return;
+ }
+ }
+}
+
+void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
+{
+ // Make sure the layout of the browser control is updated, so this calculation is correct.
+ LLLayoutStack::updateClass();
+
+ // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc.
+ LLCoordWindow window_size;
+ getWindow()->getSize(&window_size);
+
+ // Adjust width and height for the size of the chrome on the web Browser window.
+ width += getRect().getWidth() - mWebBrowser->getRect().getWidth();
+ height += getRect().getHeight() - mWebBrowser->getRect().getHeight();
+
+ LLRect geom;
+ geom.setOriginAndSize(x, window_size.mY - (y + height), width, height);
+
+ lldebugs << "geometry change: " << geom << llendl;
+
+ handleReshape(geom,false);
+}
+
+void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
+{
+ // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
+ mWebBrowser->setHomePageUrl(web_url, "text/html");
+ mWebBrowser->setTarget(target);
+ mWebBrowser->navigateTo(web_url, "text/html");
+ set_current_url(web_url);
+}
+
+//virtual
+void LLFloaterWebContent::onClose(bool app_quitting)
+{
+ LLViewerMedia::proxyWindowClosed(mUUID);
+ destroy();
+}
+
+// virtual
+void LLFloaterWebContent::draw()
+{
+ // this is asychronous so we need to keep checking
+ getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() );
+ getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() );
+
+ LLFloater::draw();
+}
+
+// virtual
+void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if(event == MEDIA_EVENT_LOCATION_CHANGED)
+ {
+ const std::string url = self->getLocation();
+
+ if ( url.length() )
+ mStatusBarText->setText( url );
+
+ set_current_url( url );
+ }
+ else if(event == MEDIA_EVENT_NAVIGATE_BEGIN)
+ {
+ // flags are sent with this event
+ getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
+ getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
+
+ // toggle visibility of these buttons based on browser state
+ getChildView("reload")->setVisible( false );
+ getChildView("stop")->setVisible( true );
+
+ // turn "on" progress bar now we're about to start loading
+ mStatusBarProgress->setVisible( true );
+ }
+ else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
+ {
+ // flags are sent with this event
+ getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
+ getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
+
+ // toggle visibility of these buttons based on browser state
+ getChildView("reload")->setVisible( true );
+ getChildView("stop")->setVisible( false );
+
+ // turn "off" progress bar now we're loaded
+ mStatusBarProgress->setVisible( false );
+
+ // we populate the status bar with URLs as they change so clear it now we're done
+ const std::string end_str = "";
+ mStatusBarText->setText( end_str );
+
+ // decide if secure browsing icon should be displayed
+ std::string prefix = std::string("https://");
+ std::string test_prefix = mCurrentURL.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ if(test_prefix == prefix)
+ {
+ mSecureLockIcon->setVisible(true);
+ }
+ else
+ {
+ mSecureLockIcon->setVisible(false);
+ }
+ }
+ else if(event == MEDIA_EVENT_CLOSE_REQUEST)
+ {
+ // The browser instance wants its window closed.
+ closeFloater();
+ }
+ else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
+ {
+ geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
+ }
+ else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
+ {
+ const std::string text = self->getStatusText();
+ if ( text.length() )
+ mStatusBarText->setText( text );
+ }
+ else if(event == MEDIA_EVENT_PROGRESS_UPDATED )
+ {
+ int percent = (int)self->getProgressPercent();
+ mStatusBarProgress->setValue( percent );
+ }
+ else if(event == MEDIA_EVENT_NAME_CHANGED )
+ {
+ std::string page_title = self->getMediaName();
+ // simulate browser behavior - title is empty, use the current URL
+ if ( page_title.length() > 0 )
+ setTitle( page_title );
+ else
+ setTitle( mCurrentURL );
+ }
+ else if(event == MEDIA_EVENT_LINK_HOVERED )
+ {
+ const std::string link = self->getHoverLink();
+ mStatusBarText->setText( link );
+ }
+}
+
+void LLFloaterWebContent::set_current_url(const std::string& url)
+{
+ mCurrentURL = url;
+
+ // serialize url history into the system URL History manager
+ LLURLHistory::removeURL("browser", mCurrentURL);
+ LLURLHistory::addURL("browser", mCurrentURL);
+
+ mAddressCombo->remove( mCurrentURL );
+ mAddressCombo->add( mCurrentURL );
+ mAddressCombo->selectByValue( mCurrentURL );
+}
+
+void LLFloaterWebContent::onClickForward()
+{
+ mWebBrowser->navigateForward();
+}
+
+void LLFloaterWebContent::onClickBack()
+{
+ mWebBrowser->navigateBack();
+}
+
+void LLFloaterWebContent::onClickReload()
+{
+
+ if( mWebBrowser->getMediaPlugin() )
+ {
+ bool ignore_cache = true;
+ mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache );
+ }
+ else
+ {
+ mWebBrowser->navigateTo(mCurrentURL);
+ }
+}
+
+void LLFloaterWebContent::onClickStop()
+{
+ if( mWebBrowser->getMediaPlugin() )
+ mWebBrowser->getMediaPlugin()->browse_stop();
+
+ // still should happen when we catch the navigate complete event
+ // but sometimes (don't know why) that event isn't sent from Qt
+ // and we getto a point where the stop button stays active.
+ getChildView("reload")->setVisible( true );
+ getChildView("stop")->setVisible( false );
+}
+
+void LLFloaterWebContent::onEnterAddress()
+{
+ // make sure there is at least something there.
+ // (perhaps this test should be for minimum length of a URL)
+ std::string url = mAddressCombo->getValue().asString();
+ if ( url.length() > 0 )
+ {
+ mWebBrowser->navigateTo( url, "text/html");
+ };
+}
+
+void LLFloaterWebContent::onPopExternal()
+{
+ // make sure there is at least something there.
+ // (perhaps this test should be for minimum length of a URL)
+ std::string url = mAddressCombo->getValue().asString();
+ if ( url.length() > 0 )
+ {
+ LLWeb::loadURLExternal( url );
+ };
+}
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
new file mode 100644
index 0000000000..ecc7e970d8
--- /dev/null
+++ b/indra/newview/llfloaterwebcontent.h
@@ -0,0 +1,82 @@
+/**
+ * @file llfloaterwebcontent.h
+ * @brief floater for displaying web content - e.g. profiles and search (eventually)
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERWEBCONTENT_H
+#define LL_LLFLOATERWEBCONTENT_H
+
+#include "llfloater.h"
+#include "llmediactrl.h"
+
+class LLMediaCtrl;
+class LLComboBox;
+class LLTextBox;
+class LLProgressBar;
+class LLIconCtrl;
+
+class LLFloaterWebContent :
+ public LLFloater,
+ public LLViewerMediaObserver
+{
+public:
+ LOG_CLASS(LLFloaterWebContent);
+ LLFloaterWebContent(const LLSD& key);
+
+ void initializeURLHistory();
+
+ static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
+
+ static void closeRequest(const std::string &uuid);
+ static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
+ void geometryChanged(S32 x, S32 y, S32 width, S32 height);
+
+ /* virtual */ BOOL postBuild();
+ /* virtual */ void onClose(bool app_quitting);
+ /* virtual */ void draw();
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
+ void onClickBack();
+ void onClickForward();
+ void onClickReload();
+ void onClickStop();
+ void onEnterAddress();
+ void onPopExternal();
+
+private:
+ void open_media(const std::string& media_url, const std::string& target);
+ void set_current_url(const std::string& url);
+
+ LLMediaCtrl* mWebBrowser;
+ LLComboBox* mAddressCombo;
+ LLIconCtrl *mSecureLockIcon;
+ LLTextBox* mStatusBarText;
+ LLProgressBar* mStatusBarProgress;
+ std::string mCurrentURL;
+ std::string mUUID;
+};
+
+#endif // LL_LLFLOATERWEBCONTENT_H
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 7236894542..03cf0332a9 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -72,7 +72,6 @@
#include "llweb.h"
#include "llslider.h"
#include "message.h"
-
#include "llwindow.h" // copyTextToClipboard()
//---------------------------------------------------------------------------
@@ -106,32 +105,75 @@ class LLWorldMapHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE) { }
-
+ LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { }
+
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableWorldMap"))
+ {
+ LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
if (params.size() == 0)
{
// support the secondlife:///app/worldmap SLapp
LLFloaterReg::showInstance("world_map", "center");
return true;
}
-
+
// support the secondlife:///app/worldmap/{LOCATION}/{COORDS} SLapp
const std::string region_name = LLURI::unescape(params[0].asString());
S32 x = (params.size() > 1) ? params[1].asInteger() : 128;
S32 y = (params.size() > 2) ? params[2].asInteger() : 128;
S32 z = (params.size() > 3) ? params[3].asInteger() : 0;
-
+
LLFloaterWorldMap::getInstance()->trackURL(region_name, x, y, z);
LLFloaterReg::showInstance("world_map", "center");
-
+
return true;
}
};
LLWorldMapHandler gWorldMapHandler;
+// SocialMap handler secondlife:///app/maptrackavatar/id
+class LLMapTrackAvatarHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE)
+ {
+ }
+
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableWorldMap"))
+ {
+ LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
+ //Make sure we have some parameters
+ if (params.size() == 0)
+ {
+ return false;
+ }
+
+ //Get the ID
+ LLUUID id;
+ if (!id.set( params[0], FALSE ))
+ {
+ return false;
+ }
+
+ LLFloaterWorldMap::getInstance()->avatarTrackFromSlapp( id );
+ LLFloaterReg::showInstance( "world_map", "center" );
+
+ return true;
+ }
+};
+LLMapTrackAvatarHandler gMapTrackAvatar;
LLFloaterWorldMap* gFloaterWorldMap = NULL;
@@ -142,7 +184,7 @@ public:
virtual ~LLMapInventoryObserver() {}
virtual void changed(U32 mask);
};
-
+
void LLMapInventoryObserver::changed(U32 mask)
{
// if there's a change we're interested in.
@@ -184,16 +226,16 @@ const LLUUID LLFloaterWorldMap::sHomeID( "10000000-0000-0000-0000-000000000001"
LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
: LLFloater(key),
- mInventory(NULL),
- mInventoryObserver(NULL),
- mFriendObserver(NULL),
- mCompletingRegionName(),
- mCompletingRegionPos(),
- mWaitingForTracker(FALSE),
- mIsClosing(FALSE),
- mSetToUserPosition(TRUE),
- mTrackedLocation(0,0,0),
- mTrackedStatus(LLTracker::TRACKING_NOTHING)
+mInventory(NULL),
+mInventoryObserver(NULL),
+mFriendObserver(NULL),
+mCompletingRegionName(),
+mCompletingRegionPos(),
+mWaitingForTracker(FALSE),
+mIsClosing(FALSE),
+mSetToUserPosition(TRUE),
+mTrackedLocation(0,0,0),
+mTrackedStatus(LLTracker::TRACKING_NOTHING)
{
gFloaterWorldMap = this;
@@ -210,7 +252,7 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
mCommitCallbackRegistrar.add("WMap.ShowAgent", boost::bind(&LLFloaterWorldMap::onShowAgentBtn, this));
mCommitCallbackRegistrar.add("WMap.Clear", boost::bind(&LLFloaterWorldMap::onClearBtn, this));
mCommitCallbackRegistrar.add("WMap.CopySLURL", boost::bind(&LLFloaterWorldMap::onCopySLURL, this));
-
+
gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterWorldMap::onChangeMaturity, this));
}
@@ -223,32 +265,32 @@ void* LLFloaterWorldMap::createWorldMapView(void* data)
BOOL LLFloaterWorldMap::postBuild()
{
mPanel = getChild<LLPanel>("objects_mapview");
-
+
LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
avatar_combo->selectFirstItem();
avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) );
avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
-
+
LLSearchEditor *location_editor = getChild<LLSearchEditor>("location");
location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1));
location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
-
+
LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");
landmark_combo->selectFirstItem();
landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) );
landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
-
+
mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f);
getChild<LLUICtrl>("zoom slider")->setValue(LLWorldMapView::sMapScale);
-
+
setDefaultBtn(NULL);
-
+
mZoomTimer.stop();
-
+
onChangeMaturity();
-
+
return TRUE;
}
@@ -257,11 +299,11 @@ LLFloaterWorldMap::~LLFloaterWorldMap()
{
// All cleaned up by LLView destructor
mPanel = NULL;
-
+
// Inventory deletes all observers on shutdown
mInventory = NULL;
mInventoryObserver = NULL;
-
+
// avatar tracker will delete this for us.
mFriendObserver = NULL;
@@ -285,13 +327,13 @@ void LLFloaterWorldMap::onClose(bool app_quitting)
void LLFloaterWorldMap::onOpen(const LLSD& key)
{
bool center_on_target = (key.asString() == "center");
-
+
mIsClosing = FALSE;
-
+
LLWorldMapView* map_panel;
map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
map_panel->clearLastClick();
-
+
{
// reset pan on show, so it centers on you again
if (!center_on_target)
@@ -299,27 +341,27 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
LLWorldMapView::setPan(0, 0, TRUE);
}
map_panel->updateVisibleBlocks();
-
+
// Reload items as they may have changed
LLWorldMap::getInstance()->reloadItems();
-
+
// We may already have a bounding box for the regions of the world,
// so use that to adjust the view.
adjustZoomSliderBounds();
-
+
// Could be first show
//LLFirstUse::useMap();
-
+
// Start speculative download of landmarks
const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id);
-
+
getChild<LLUICtrl>("location")->setFocus( TRUE);
gFocusMgr.triggerFocusFlash();
-
+
buildAvatarIDList();
buildLandmarkIDLists();
-
+
// If nothing is being tracked, set flag so the user position will be found
mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
}
@@ -356,7 +398,7 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
return TRUE;
}
}
-
+
return LLFloater::handleScrollWheel(x, y, clicks);
}
@@ -381,7 +423,7 @@ void LLFloaterWorldMap::draw()
bool agent_on_prelude = (regionp && regionp->isPrelude());
bool enable_go_home = gAgent.isGodlike() || !agent_on_prelude;
getChildView("Go Home")->setEnabled(enable_go_home);
-
+
updateLocation();
LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
@@ -393,7 +435,7 @@ void LLFloaterWorldMap::draw()
{
getChild<LLUICtrl>("avatar_icon")->setColor( map_track_disabled_color);
}
-
+
if (LLTracker::TRACKING_LANDMARK == tracking_status)
{
getChild<LLUICtrl>("landmark_icon")->setColor( map_track_color);
@@ -402,7 +444,7 @@ void LLFloaterWorldMap::draw()
{
getChild<LLUICtrl>("landmark_icon")->setColor( map_track_disabled_color);
}
-
+
if (LLTracker::TRACKING_LOCATION == tracking_status)
{
getChild<LLUICtrl>("location_icon")->setColor( map_track_color);
@@ -422,21 +464,21 @@ void LLFloaterWorldMap::draw()
getChild<LLUICtrl>("location_icon")->setColor( map_track_disabled_color);
}
}
-
+
// check for completion of tracking data
if (mWaitingForTracker)
{
centerOnTarget(TRUE);
}
-
+
getChildView("Teleport")->setEnabled((BOOL)tracking_status);
-// getChildView("Clear")->setEnabled((BOOL)tracking_status);
+ // getChildView("Clear")->setEnabled((BOOL)tracking_status);
getChildView("Show Destination")->setEnabled((BOOL)tracking_status || LLWorldMap::getInstance()->isTracking());
getChildView("copy_slurl")->setEnabled((mSLURL.isValid()) );
-
+
setMouseOpaque(TRUE);
getDragHandle()->setMouseOpaque(TRUE);
-
+
//RN: snaps to zoom value because interpolation caused jitter in the text rendering
if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal())
{
@@ -451,7 +493,7 @@ void LLFloaterWorldMap::draw()
mCurZoomVal = lerp(mCurZoomVal, (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(), interp);
F32 map_scale = 256.f*pow(2.f, mCurZoomVal);
LLWorldMapView::setScale( map_scale );
-
+
// Enable/disable checkboxes depending on the zoom level
// If above threshold level (i.e. low res) -> Disable all checkboxes
// If under threshold level (i.e. high res) -> Enable all checkboxes
@@ -477,7 +519,7 @@ void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const std::string&
{
LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
if (!iface) return;
-
+
buildAvatarIDList();
if(iface->setCurrentByID(avatar_id) || gAgent.isGodlike())
{
@@ -507,7 +549,7 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
{
LLCtrlSelectionInterface *iface = childGetSelectionInterface("landmark combo");
if (!iface) return;
-
+
buildLandmarkIDLists();
BOOL found = FALSE;
S32 idx;
@@ -519,7 +561,7 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
break;
}
}
-
+
if (found && iface->setCurrentByID( landmark_item_id ) )
{
LLUUID asset_id = mLandmarkAssetIDList.get( idx );
@@ -528,17 +570,17 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
if (combo) name = combo->getSimple();
mTrackedStatus = LLTracker::TRACKING_LANDMARK;
LLTracker::trackLandmark(mLandmarkAssetIDList.get( idx ), // assetID
- mLandmarkItemIDList.get( idx ), // itemID
- name); // name
-
+ mLandmarkItemIDList.get( idx ), // itemID
+ name); // name
+
if( asset_id != sHomeID )
{
// start the download process
gLandmarkList.getAsset( asset_id);
}
-
+
// We have to download both region info and landmark data, so set busy. JC
-// getWindow()->incBusyCount();
+ // getWindow()->incBusyCount();
}
else
{
@@ -574,10 +616,10 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
S32 world_y = S32(pos_global.mdV[1] / 256);
LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
setDefaultBtn("");
-
+
// clicked on a non-region - turn off coord display
enableTeleportCoordsDisplay( false );
-
+
return;
}
if (sim_info->isDown())
@@ -588,33 +630,33 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
LLWorldMap::getInstance()->setTrackingInvalid();
LLTracker::stopTracking(NULL);
setDefaultBtn("");
-
+
// clicked on a down region - turn off coord display
enableTeleportCoordsDisplay( false );
-
+
return;
}
-
+
std::string sim_name = sim_info->getName();
F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
std::string full_name = llformat("%s (%d, %d, %d)",
- sim_name.c_str(),
- llround(region_x),
- llround(region_y),
- llround((F32)pos_global.mdV[VZ]));
-
+ sim_name.c_str(),
+ llround(region_x),
+ llround(region_y),
+ llround((F32)pos_global.mdV[VZ]));
+
std::string tooltip("");
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(pos_global, full_name, tooltip);
LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking
-
+
LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
updateTeleportCoordsDisplay( coord_pos );
-
+
// we have a valid region - turn on coord display
enableTeleportCoordsDisplay( true );
-
+
setDefaultBtn("Teleport");
}
@@ -631,11 +673,11 @@ void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos )
{
// if we're going to update their value, we should also enable them
enableTeleportCoordsDisplay( true );
-
+
// 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 );
@@ -646,16 +688,16 @@ void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos )
void LLFloaterWorldMap::updateLocation()
{
bool gotSimName;
-
+
LLTracker::ETrackingStatus status = LLTracker::getTrackingStatus();
-
+
// These values may get updated by a message, so need to check them every frame
// The fields may be changed by the user, so only update them if the data changes
LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
if (pos_global.isExactlyZero())
{
LLVector3d agentPos = gAgent.getPositionGlobal();
-
+
// Set to avatar's current postion if nothing is selected
if ( status == LLTracker::TRACKING_NOTHING && mSetToUserPosition )
{
@@ -665,19 +707,19 @@ void LLFloaterWorldMap::updateLocation()
if ( gotSimName )
{
mSetToUserPosition = FALSE;
-
+
// Fill out the location field
getChild<LLUICtrl>("location")->setValue(agent_sim_name);
-
+
// update the coordinate display with location of avatar in region
updateTeleportCoordsDisplay( agentPos );
-
+
// Figure out where user is
// Set the current SLURL
mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionGlobal());
}
}
-
+
return; // invalid location
}
std::string sim_name;
@@ -699,17 +741,17 @@ void LLFloaterWorldMap::updateLocation()
pos_global[2] = 200;
}
}
-
+
getChild<LLUICtrl>("location")->setValue(sim_name);
-
+
// refresh coordinate display to reflect where user clicked.
LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
updateTeleportCoordsDisplay( coord_pos );
-
+
// simNameFromPosGlobal can fail, so don't give the user an invalid SLURL
if ( gotSimName )
{
- mSLURL = LLSLURL(sim_name, pos_global);
+ mSLURL = LLSLURL(sim_name, pos_global);
}
else
{ // Empty SLURL will disable the "Copy SLURL to clipboard" button
@@ -736,12 +778,12 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3
{
// fill in UI based on URL
gFloaterWorldMap->getChild<LLUICtrl>("location")->setValue(region_name);
-
+
// Save local coords to highlight position after region global
// position is returned.
gFloaterWorldMap->mCompletingRegionPos.set(
- (F32)x_coord, (F32)y_coord, (F32)z_coord);
-
+ (F32)x_coord, (F32)y_coord, (F32)z_coord);
+
// pass sim name to combo box
gFloaterWorldMap->mCompletingRegionName = region_name;
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name);
@@ -813,7 +855,7 @@ void LLFloaterWorldMap::buildAvatarIDList()
{
LLCtrlListInterface *list = childGetListInterface("friend combo");
if (!list) return;
-
+
// Delete all but the "None" entry
S32 list_size = list->getItemCount();
if (list_size > 1)
@@ -821,7 +863,7 @@ void LLFloaterWorldMap::buildAvatarIDList()
list->selectItemRange(1, -1);
list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
}
-
+
// Get all of the calling cards for avatar that are currently online
LLCollectMappableBuddies collector;
LLAvatarTracker::instance().applyFunctor(collector);
@@ -833,7 +875,7 @@ void LLFloaterWorldMap::buildAvatarIDList()
{
list->addSimpleElement((*it).first, ADD_BOTTOM, (*it).second);
}
-
+
list->setCurrentByID( LLAvatarTracker::instance().getAvatarID() );
list->selectFirstItem();
}
@@ -843,7 +885,7 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
{
LLCtrlListInterface *list = childGetListInterface("landmark combo");
if (!list) return;
-
+
// Delete all but the "None" entry
S32 list_size = list->getItemCount();
if (list_size > 1)
@@ -851,17 +893,17 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
list->selectItemRange(1, -1);
list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
}
-
+
mLandmarkItemIDList.reset();
mLandmarkAssetIDList.reset();
-
+
// Get all of the current landmarks
mLandmarkAssetIDList.put( LLUUID::null );
mLandmarkItemIDList.put( LLUUID::null );
-
+
mLandmarkAssetIDList.put( sHomeID );
mLandmarkItemIDList.put( sHomeID );
-
+
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLIsType is_landmark(LLAssetType::AT_LANDMARK);
@@ -870,20 +912,20 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
items,
LLInventoryModel::EXCLUDE_TRASH,
is_landmark);
-
+
std::sort(items.begin(), items.end(), LLViewerInventoryItem::comparePointers());
S32 count = items.count();
for(S32 i = 0; i < count; ++i)
{
LLInventoryItem* item = items.get(i);
-
+
list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID());
-
+
mLandmarkAssetIDList.put( item->getAssetUUID() );
mLandmarkItemIDList.put( item->getUUID() );
}
-
+
list->selectFirstItem();
}
@@ -949,31 +991,31 @@ void LLFloaterWorldMap::adjustZoomSliderBounds()
// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
S32 world_width_regions = MAX_VISIBLE_REGIONS;
S32 world_height_regions = MAX_VISIBLE_REGIONS;
-
+
// Find how much space we have to display the world
LLWorldMapView* map_panel;
map_panel = (LLWorldMapView*)mPanel;
LLRect view_rect = map_panel->getRect();
-
+
// View size in pixels
S32 view_width = view_rect.getWidth();
S32 view_height = view_rect.getHeight();
-
+
// Pixels per region to display entire width/height
F32 width_pixels_per_region = (F32) view_width / (F32) world_width_regions;
F32 height_pixels_per_region = (F32) view_height / (F32) world_height_regions;
-
+
F32 pixels_per_region = llmin(width_pixels_per_region,
height_pixels_per_region);
-
+
// Round pixels per region to an even number of slider increments
S32 slider_units = llfloor(pixels_per_region / 0.2f);
pixels_per_region = slider_units * 0.2f;
-
+
// Make sure the zoom slider can be moved at least a little bit.
// Likewise, less than the increment pixels per region is just silly.
pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX);
-
+
F32 min_power = log(pixels_per_region/256.f)/log(2.f);
getChild<LLSlider>("zoom slider")->setMinValue(min_power);
@@ -997,19 +1039,19 @@ void LLFloaterWorldMap::onLandmarkComboPrearrange( )
{
return;
}
-
+
LLCtrlListInterface *list = childGetListInterface("landmark combo");
if (!list) return;
-
+
LLUUID current_choice = list->getCurrentID();
-
+
buildLandmarkIDLists();
-
+
if( current_choice.isNull() || !list->setCurrentByID( current_choice ) )
{
LLTracker::stopTracking(NULL);
}
-
+
}
void LLFloaterWorldMap::onComboTextEntry()
@@ -1033,18 +1075,18 @@ void LLFloaterWorldMap::onLandmarkComboCommit()
{
return;
}
-
+
LLCtrlListInterface *list = childGetListInterface("landmark combo");
if (!list) return;
-
+
LLUUID asset_id;
LLUUID item_id = list->getCurrentID();
-
+
LLTracker::stopTracking(NULL);
-
+
//RN: stopTracking() clears current combobox selection, need to reassert it here
list->setCurrentByID(item_id);
-
+
if( item_id.isNull() )
{
}
@@ -1068,7 +1110,7 @@ void LLFloaterWorldMap::onLandmarkComboCommit()
trackLandmark( item_id);
onShowTargetBtn();
-
+
// Reset to user postion if nothing is tracked
mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
}
@@ -1080,19 +1122,19 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( )
{
return;
}
-
+
LLCtrlListInterface *list = childGetListInterface("friend combo");
if (!list) return;
-
+
LLUUID current_choice;
-
+
if( LLAvatarTracker::instance().haveTrackingInfo() )
{
current_choice = LLAvatarTracker::instance().getAvatarID();
}
-
+
buildAvatarIDList();
-
+
if( !list->setCurrentByID( current_choice ) || current_choice.isNull() )
{
LLTracker::stopTracking(NULL);
@@ -1105,10 +1147,10 @@ void LLFloaterWorldMap::onAvatarComboCommit()
{
return;
}
-
+
LLCtrlListInterface *list = childGetListInterface("friend combo");
if (!list) return;
-
+
const LLUUID& new_avatar_id = list->getCurrentID();
if (new_avatar_id.notNull())
{
@@ -1124,6 +1166,12 @@ void LLFloaterWorldMap::onAvatarComboCommit()
}
}
+void LLFloaterWorldMap::avatarTrackFromSlapp( const LLUUID& id )
+{
+ trackAvatar( id, "av" );
+ onShowTargetBtn();
+}
+
void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus )
{
updateSearchEnabled();
@@ -1148,13 +1196,13 @@ void LLFloaterWorldMap::onLocationCommit()
{
return;
}
-
+
clearLocationSelection(FALSE);
mCompletingRegionName = "";
mLastRegionName = "";
-
+
std::string str = getChild<LLUICtrl>("location")->getValue().asString();
-
+
// Trim any leading and trailing spaces in the search target
std::string saved_str = str;
LLStringUtil::trim( str );
@@ -1162,7 +1210,7 @@ void LLFloaterWorldMap::onLocationCommit()
{ // Set the value in the UI if any spaces were removed
getChild<LLUICtrl>("location")->setValue(str);
}
-
+
LLStringUtil::toLower(str);
mCompletingRegionName = str;
LLWorldMap::getInstance()->setTrackingCommit();
@@ -1183,13 +1231,13 @@ void LLFloaterWorldMap::onCoordinatesCommit()
{
return;
}
-
+
S32 x_coord = (S32)childGetValue("teleport_coordinate_x").asReal();
S32 y_coord = (S32)childGetValue("teleport_coordinate_y").asReal();
S32 z_coord = (S32)childGetValue("teleport_coordinate_z").asReal();
-
+
const std::string region_name = childGetValue("location").asString();
-
+
trackURL( region_name, x_coord, y_coord, z_coord );
}
@@ -1225,7 +1273,7 @@ void LLFloaterWorldMap::onCopySLURL()
LLSD args;
args["SLURL"] = mSLURL.getSLURLString();
-
+
LLNotificationsUtil::add("CopySLURL", args);
}
@@ -1246,26 +1294,26 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
else
{
// We've got the position finally, so we're no longer busy. JC
-// getWindow()->decBusyCount();
+ // getWindow()->decBusyCount();
pos_global = LLTracker::getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();
}
}
else if(LLWorldMap::getInstance()->isTracking())
{
pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();;
-
-
-
+
+
+
}
else
{
// default behavior = center on agent
pos_global.clearVec();
}
-
+
LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
- -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
- !animate);
+ -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
+ !animate);
mWaitingForTracker = FALSE;
}
@@ -1273,7 +1321,7 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate)
void LLFloaterWorldMap::fly()
{
LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
-
+
// Start the autopilot and close the floater,
// so we can see where we're flying
if (!pos_global.isExactlyZero())
@@ -1294,7 +1342,7 @@ void LLFloaterWorldMap::teleport()
BOOL teleport_home = FALSE;
LLVector3d pos_global;
LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
-
+
LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
if (LLTracker::TRACKING_AVATAR == tracking_status
&& av_tracker.haveTrackingInfo() )
@@ -1317,10 +1365,10 @@ void LLFloaterWorldMap::teleport()
&& landmark->getRegionID(region_id))
{
LLLandmark::requestRegionHandle(
- gMessageSystem,
- gAgent.getRegionHost(),
- region_id,
- NULL);
+ gMessageSystem,
+ gAgent.getRegionHost(),
+ region_id,
+ NULL);
}
}
}
@@ -1332,7 +1380,7 @@ void LLFloaterWorldMap::teleport()
{
make_ui_sound("UISndInvalidOp");
}
-
+
// Do the teleport, which will also close the floater
if (teleport_home)
{
@@ -1367,7 +1415,7 @@ void LLFloaterWorldMap::teleportToLandmark()
{
BOOL has_destination = FALSE;
LLUUID destination_id; // Null means "home"
-
+
if( LLTracker::getTrackedLandmarkAssetID() == sHomeID )
{
has_destination = TRUE;
@@ -1388,14 +1436,14 @@ void LLFloaterWorldMap::teleportToLandmark()
if(landmark->getRegionID(region_id))
{
LLLandmark::requestRegionHandle(
- gMessageSystem,
- gAgent.getRegionHost(),
- region_id,
- NULL);
+ gMessageSystem,
+ gAgent.getRegionHost(),
+ region_id,
+ NULL);
}
}
}
-
+
if( has_destination )
{
gAgent.teleportViaLandmark( destination_id );
@@ -1428,12 +1476,12 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
{
return;
}
-
+
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("search_results");
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
-
+
S32 name_length = mCompletingRegionName.length();
-
+
LLSD match;
S32 num_results = 0;
@@ -1443,7 +1491,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
LLSimInfo* info = it->second;
std::string sim_name_lower = info->getName();
LLStringUtil::toLower(sim_name_lower);
-
+
if (sim_name_lower.substr(0, name_length) == mCompletingRegionName)
{
if (sim_name_lower == mCompletingRegionName)
@@ -1459,12 +1507,12 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
num_results++;
}
}
-
+
if (found_null_sim)
{
mCompletingRegionName = "";
}
-
+
// if match found, highlight it and go
if (!match.isUndefined())
{
@@ -1472,7 +1520,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
getChild<LLUICtrl>("search_results")->setFocus(TRUE);
onCommitSearchResult();
}
-
+
// if we found nothing, say "none"
if (num_results == 0)
{
@@ -1486,7 +1534,7 @@ void LLFloaterWorldMap::onCommitSearchResult()
{
LLCtrlListInterface *list = childGetListInterface("search_results");
if (!list) return;
-
+
LLSD selected_value = list->getSelectedValue();
std::string sim_name = selected_value.asString();
if (sim_name.empty())
@@ -1494,19 +1542,19 @@ void LLFloaterWorldMap::onCommitSearchResult()
return;
}
LLStringUtil::toLower(sim_name);
-
+
std::map<U64, LLSimInfo*>::const_iterator it;
for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
{
LLSimInfo* info = it->second;
-
+
if (info->isName(sim_name))
{
LLVector3d pos_global = info->getGlobalOrigin();
-
+
const F64 SIM_COORD_DEFAULT = 128.0;
LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f);
-
+
// Did this value come from a trackURL() request?
if (!mCompletingRegionPos.isExactlyZero())
{
@@ -1516,14 +1564,14 @@ void LLFloaterWorldMap::onCommitSearchResult()
pos_global.mdV[VX] += (F64)pos_local.mV[VX];
pos_global.mdV[VY] += (F64)pos_local.mV[VY];
pos_global.mdV[VZ] = (F64)pos_local.mV[VZ];
-
+
getChild<LLUICtrl>("location")->setValue(sim_name);
trackLocation(pos_global);
setDefaultBtn("Teleport");
break;
}
}
-
+
onShowTargetBtn();
}
@@ -1531,15 +1579,15 @@ void LLFloaterWorldMap::onChangeMaturity()
{
bool can_access_mature = gAgent.canAccessMature();
bool can_access_adult = gAgent.canAccessAdult();
-
+
getChildView("events_mature_icon")->setVisible( can_access_mature);
getChildView("events_mature_label")->setVisible( can_access_mature);
getChildView("events_mature_chk")->setVisible( can_access_mature);
-
+
getChildView("events_adult_icon")->setVisible( can_access_adult);
getChildView("events_adult_label")->setVisible( can_access_adult);
getChildView("events_adult_chk")->setVisible( can_access_adult);
-
+
// disable mature / adult events.
if (!can_access_mature)
{
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 1628a421ec..783d9f4819 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -106,6 +106,11 @@ public:
// teleport to the tracked item, if there is one
void teleport();
void onChangeMaturity();
+
+
+ //Slapp instigated avatar tracking
+ void avatarTrackFromSlapp( const LLUUID& id );
+
protected:
void onGoHome();
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index c38cd4d090..b3b1ce5743 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1854,31 +1854,9 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
{
if (mCallbackRegistrar)
mCallbackRegistrar->pushScope();
- //menu->empty();
- const LLView::child_list_t *list = menu->getChildList();
- LLView::child_list_t::const_iterator menu_itor;
- for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
- {
- (*menu_itor)->setVisible(FALSE);
- (*menu_itor)->pushVisible(TRUE);
- (*menu_itor)->setEnabled(TRUE);
- }
-
- // Successively filter out invalid options
-
- U32 flags = FIRST_SELECTED_ITEM;
- for (selected_items_t::iterator item_itor = mSelectedItems.begin();
- item_itor != mSelectedItems.end();
- ++item_itor)
- {
- LLFolderViewItem* selected_item = (*item_itor);
- selected_item->buildContextMenu(*menu, flags);
- flags = 0x0;
- }
+ updateMenuOptions(menu);
- addNoOptions(menu);
-
menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, menu, x, y);
if (mCallbackRegistrar)
@@ -2365,6 +2343,45 @@ void LLFolderView::updateRenamerPosition()
}
}
+// Update visibility and availability (i.e. enabled/disabled) of context menu items.
+void LLFolderView::updateMenuOptions(LLMenuGL* menu)
+{
+ const LLView::child_list_t *list = menu->getChildList();
+
+ LLView::child_list_t::const_iterator menu_itor;
+ for (menu_itor = list->begin(); menu_itor != list->end(); ++menu_itor)
+ {
+ (*menu_itor)->setVisible(FALSE);
+ (*menu_itor)->pushVisible(TRUE);
+ (*menu_itor)->setEnabled(TRUE);
+ }
+
+ // Successively filter out invalid options
+
+ U32 flags = FIRST_SELECTED_ITEM;
+ for (selected_items_t::iterator item_itor = mSelectedItems.begin();
+ item_itor != mSelectedItems.end();
+ ++item_itor)
+ {
+ LLFolderViewItem* selected_item = (*item_itor);
+ selected_item->buildContextMenu(*menu, flags);
+ flags = 0x0;
+ }
+
+ addNoOptions(menu);
+}
+
+// Refresh the context menu (that is already shown).
+void LLFolderView::updateMenu()
+{
+ LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
+ if (menu && menu->getVisible())
+ {
+ updateMenuOptions(menu);
+ menu->needsArrange(); // update menu height if needed
+ }
+}
+
bool LLFolderView::selectFirstItem()
{
for (folders_t::iterator iter = mFolders.begin();
@@ -2429,6 +2446,7 @@ S32 LLFolderView::notify(const LLSD& info)
{
setFocus(true);
selectFirstItem();
+ scrollToShowSelection();
return 1;
}
@@ -2436,6 +2454,7 @@ S32 LLFolderView::notify(const LLSD& info)
{
setFocus(true);
selectLastItem();
+ scrollToShowSelection();
return 1;
}
}
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index afaac86b04..210ba9eb3c 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -269,7 +269,10 @@ public:
virtual S32 notify(const LLSD& info) ;
bool useLabelSuffix() { return mUseLabelSuffix; }
+ void updateMenu();
+
private:
+ void updateMenuOptions(LLMenuGL* menu);
void updateRenamerPosition();
protected:
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index e9f1e3bc22..11401d6c68 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -28,6 +28,7 @@
#include "llfriendcard.h"
+#include "llagent.h"
#include "llavatarnamecache.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
@@ -95,6 +96,36 @@ const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollect
}
/**
+ * Class LLFindAgentCallingCard
+ *
+ * An inventory collector functor for checking that agent's own calling card
+ * exists within the Calling Cards category and its sub-folders.
+ */
+class LLFindAgentCallingCard : public LLInventoryCollectFunctor
+{
+public:
+ LLFindAgentCallingCard() : mIsAgentCallingCardFound(false) {}
+ virtual ~LLFindAgentCallingCard() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+ bool isAgentCallingCardFound() { return mIsAgentCallingCardFound; }
+
+private:
+ bool mIsAgentCallingCardFound;
+};
+
+bool LLFindAgentCallingCard::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+ if (mIsAgentCallingCardFound) return true;
+
+ if (item && item->getType() == LLAssetType::AT_CALLINGCARD && item->getCreatorUUID() == gAgentID)
+ {
+ mIsAgentCallingCardFound = true;
+ }
+
+ return mIsAgentCallingCardFound;
+}
+
+/**
* Class for fetching initial friend cards data
*
* Implemented to fix an issue when Inventory folders are in incomplete state.
@@ -290,58 +321,6 @@ void LLFriendCardsManager::syncFriendCardsFolders()
boost::bind(&LLFriendCardsManager::ensureFriendsFolderExists, this));
}
-void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const
-{
- folderBuddiesMap.clear();
-
- static bool syncronize_friends_folders = true;
- if (syncronize_friends_folders)
- {
- // Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" folder,
- // fetches their contents if needed and synchronizes it with buddies list.
- // If the folders are not found they are created.
- LLFriendCardsManager::instance().syncFriendCardsFolders();
- syncronize_friends_folders = false;
- }
-
-
- LLInventoryModel::cat_array_t* listFolders;
- LLInventoryModel::item_array_t* items;
-
- // get folders in the Friend folder. Items should be NULL due to Cards should be in lists.
- gInventory.getDirectDescendentsOf(findFriendFolderUUIDImpl(), listFolders, items);
-
- if (NULL == listFolders)
- return;
-
- LLInventoryModel::cat_array_t::const_iterator itCats; // to iterate Friend Lists (categories)
- LLInventoryModel::item_array_t::const_iterator itBuddy; // to iterate Buddies in each List
- LLInventoryModel::cat_array_t* fakeCatsArg;
- for (itCats = listFolders->begin(); itCats != listFolders->end(); ++itCats)
- {
- if (items)
- items->clear();
-
- // *HACK: Only Friends/All content will be shown for now
- // *TODO: Remove this hack, implement sorting if it will be needded by spec.
- if ((*itCats)->getUUID() != findFriendAllSubfolderUUIDImpl())
- continue;
-
- gInventory.getDirectDescendentsOf((*itCats)->getUUID(), fakeCatsArg, items);
-
- if (NULL == items)
- continue;
-
- uuid_vec_t buddyUUIDs;
- for (itBuddy = items->begin(); itBuddy != items->end(); ++itBuddy)
- {
- buddyUUIDs.push_back((*itBuddy)->getCreatorUUID());
- }
-
- folderBuddiesMap.insert(make_pair((*itCats)->getUUID(), buddyUUIDs));
- }
-}
-
/************************************************************************/
/* Private Methods */
@@ -499,21 +478,31 @@ void LLFriendCardsManager::syncFriendsFolder()
LLAvatarTracker::buddy_map_t all_buddies;
LLAvatarTracker::instance().copyBuddyList(all_buddies);
- // 1. Remove Friend Cards for non-friends
+ // 1. Check if own calling card exists
+ const LLUUID calling_cards_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
+ LLFindAgentCallingCard collector;
+ gInventory.collectDescendentsIf(calling_cards_folder_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, collector);
- gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
-
- LLInventoryModel::item_array_t::const_iterator it;
- for (it = items.begin(); it != items.end(); ++it)
+ // Create own calling card if it was not found in Friends/All folder
+ if (!collector.isAgentCallingCardFound())
{
- lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl;
- if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID()))
- {
- lldebugs << "NONEXISTS, so remove it" << llendl;
- removeFriendCardFromInventory((*it)->getCreatorUUID());
- }
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( gAgentID, &av_name );
+
+ create_inventory_item(gAgentID,
+ gAgent.getSessionID(),
+ calling_cards_folder_id,
+ LLTransactionID::tnull,
+ av_name.getCompleteName(),
+ gAgentID.asString(),
+ LLAssetType::AT_CALLINGCARD,
+ LLInventoryType::IT_CALLINGCARD,
+ NOT_WEARABLE,
+ PERM_MOVE | PERM_TRANSFER,
+ NULL);
}
// 2. Add missing Friend Cards for friends
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index b7f0bada14..48a9f70079 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -79,19 +79,6 @@ public:
*/
void syncFriendCardsFolders();
- /*!
- * \brief
- * Collects folders' IDs with the buddies' IDs in the Inventory Calling Card/Friends folder.
- *
- * \param folderBuddiesMap
- * map into collected data will be put. It will be cleared before adding new data.
- *
- * Each item in the out map is a pair where first is an LLViewerInventoryCategory UUID,
- * second is a vector with UUID of Avatars from this folder.
- *
- */
- void collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const;
-
private:
typedef boost::function<void()> callback_t;
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/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 5393678a6b..7c56e610ce 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -53,6 +53,12 @@ public:
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableGroupInfo"))
+ {
+ LLNotificationsUtil::add("NoGroupInfo", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
if (tokens.size() < 1)
{
return false;
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 7546c070ea..ce936a9924 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -52,6 +52,7 @@
#include <boost/regex.hpp>
#if LL_MSVC
+#pragma warning(push)
// disable boost::lexical_cast warning
#pragma warning (disable:4702)
#endif
diff --git a/indra/newview/llhints.cpp b/indra/newview/llhints.cpp
index 3f0deb98cd..c4dcaf11f9 100644
--- a/indra/newview/llhints.cpp
+++ b/indra/newview/llhints.cpp
@@ -33,6 +33,7 @@
#include "lltextbox.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
+#include "lliconctrl.h"
#include "llsdparam.h"
class LLHintPopup : public LLPanel
@@ -80,7 +81,8 @@ public:
up_arrow,
right_arrow,
down_arrow,
- lower_left_arrow;
+ lower_left_arrow,
+ hint_image;
Optional<S32> left_arrow_offset,
up_arrow_offset,
@@ -96,6 +98,7 @@ public:
right_arrow("right_arrow"),
down_arrow("down_arrow"),
lower_left_arrow("lower_left_arrow"),
+ hint_image("hint_image"),
left_arrow_offset("left_arrow_offset"),
up_arrow_offset("up_arrow_offset"),
right_arrow_offset("right_arrow_offset"),
@@ -166,7 +169,15 @@ LLHintPopup::LLHintPopup(const LLHintPopup::Params& p)
mDirection = p.target_params.direction;
mTarget = p.target_params.target;
}
- buildFromFile( "panel_hint.xml", NULL, p);
+ if (p.hint_image.isProvided())
+ {
+ buildFromFile("panel_hint_image.xml", NULL, p);
+ getChild<LLIconCtrl>("hint_image")->setImage(p.hint_image());
+ }
+ else
+ {
+ buildFromFile( "panel_hint.xml", NULL, p);
+ }
}
BOOL LLHintPopup::postBuild()
diff --git a/indra/newview/llhudeffectblob.cpp b/indra/newview/llhudeffectblob.cpp
new file mode 100644
index 0000000000..d8687eed8d
--- /dev/null
+++ b/indra/newview/llhudeffectblob.cpp
@@ -0,0 +1,90 @@
+/**
+ * @file llhudeffecttrail.cpp
+ * @brief LLHUDEffectSpiral class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llhudeffectblob.h"
+
+#include "llagent.h"
+#include "llviewercamera.h"
+#include "llui.h"
+
+LLHUDEffectBlob::LLHUDEffectBlob(const U8 type)
+: LLHUDEffect(type),
+ mPixelSize(10)
+{
+ mTimer.start();
+ mImage = LLUI::getUIImage("Camera_Drag_Dot");
+}
+
+LLHUDEffectBlob::~LLHUDEffectBlob()
+{
+}
+
+void LLHUDEffectBlob::render()
+{
+ F32 time = mTimer.getElapsedTimeF32();
+ if (mDuration < time)
+ {
+ markDead();
+ }
+
+ LLVector3 pos_agent = gAgent.getPosAgentFromGlobal(mPositionGlobal);
+
+ LLVector3 pixel_up, pixel_right;
+
+ LLViewerCamera::instance().getPixelVectors(pos_agent, pixel_up, pixel_right);
+
+ LLGLSPipelineAlpha gls_pipeline_alpha;
+ gGL.getTexUnit(0)->bind(mImage->getImage());
+
+ LLColor4U color = mColor;
+ color.mV[VALPHA] = (U8)clamp_rescale(time, 0.f, mDuration, 255.f, 0.f);
+ gGL.color4ubv(color.mV);
+
+ { gGL.pushMatrix();
+ gGL.translatef(pos_agent.mV[0], pos_agent.mV[1], pos_agent.mV[2]);
+ LLVector3 u_scale = pixel_right * (F32)mPixelSize;
+ LLVector3 v_scale = pixel_up * (F32)mPixelSize;
+
+ { gGL.begin(LLRender::QUADS);
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex3fv((v_scale - u_scale).mV);
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex3fv((-v_scale - u_scale).mV);
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex3fv((-v_scale + u_scale).mV);
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex3fv((v_scale + u_scale).mV);
+ } gGL.end();
+
+ } gGL.popMatrix();
+}
+
+void LLHUDEffectBlob::renderForTimer()
+{
+}
+
diff --git a/indra/newview/llhudeffectblob.h b/indra/newview/llhudeffectblob.h
new file mode 100644
index 0000000000..f4c1691108
--- /dev/null
+++ b/indra/newview/llhudeffectblob.h
@@ -0,0 +1,52 @@
+/**
+ * @file llhudeffectblob.h
+ * @brief LLHUDEffectBlob class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLHUDEFFECTBLOB_H
+#define LL_LLHUDEFFECTBLOB_H
+
+#include "llhudeffect.h"
+#include "lluiimage.h"
+
+class LLHUDEffectBlob : public LLHUDEffect
+{
+public:
+ friend class LLHUDObject;
+
+ void setPixelSize(S32 pixels) { mPixelSize = pixels; }
+
+protected:
+ LLHUDEffectBlob(const U8 type);
+ ~LLHUDEffectBlob();
+
+ /*virtual*/ void render();
+ /*virtual*/ void renderForTimer();
+private:
+ S32 mPixelSize;
+ LLFrameTimer mTimer;
+ LLPointer<LLUIImage> mImage;
+};
+
+#endif // LL_LLHUDEFFECTBLOB_H
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..95d57d08d8 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -32,6 +32,7 @@
#include "llhudtext.h"
#include "llhudicon.h"
#include "llhudeffectbeam.h"
+#include "llhudeffectblob.h"
#include "llhudeffecttrail.h"
#include "llhudeffectlookat.h"
#include "llhudeffectpointat.h"
@@ -237,6 +238,9 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)
case LL_HUD_EFFECT_POINTAT:
hud_objectp = new LLHUDEffectPointAt(type);
break;
+ case LL_HUD_EFFECT_BLOB:
+ hud_objectp = new LLHUDEffectBlob(type);
+ break;
default:
llwarns << "Unknown type of hud effect:" << (U32) type << llendl;
}
@@ -284,27 +288,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..2f7a98c86c 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -95,7 +95,8 @@ public:
LL_HUD_EFFECT_LOOKAT,
LL_HUD_EFFECT_POINTAT,
LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella
- LL_HUD_NAME_TAG
+ LL_HUD_NAME_TAG,
+ LL_HUD_EFFECT_BLOB
};
protected:
static void sortObjects();
@@ -104,7 +105,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..24a876c59a 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;
@@ -209,9 +194,6 @@ void LLHUDText::renderText(BOOL for_select)
mRadius = (width_vec + height_vec).magVec() * 0.5f;
- LLCoordGL screen_pos;
- LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
-
LLVector2 screen_offset;
screen_offset = mPositionOffset;
@@ -594,7 +576,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..f74ae92a7b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -470,7 +470,7 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
}
//static
-bool LLIMFloater::resetAllowedRectPadding(const LLSD& newvalue)
+bool LLIMFloater::resetAllowedRectPadding()
{
//reset allowed rect right padding if "SidebarCameraMovement" option
//or sidebar state changed
@@ -482,10 +482,10 @@ void LLIMFloater::getAllowedRect(LLRect& rect)
{
if (sAllowedRectRightPadding == RECT_PADDING_NOT_INIT) //wasn't initialized
{
- gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2));
+ gSavedSettings.getControl("SidebarCameraMovement")->getSignal()->connect(boost::bind(&LLIMFloater::resetAllowedRectPadding));
LLSideTray* side_bar = LLSideTray::getInstance();
- side_bar->getCollapseSignal().connect(boost::bind(&LLIMFloater::resetAllowedRectPadding, _2));
+ side_bar->setVisibleWidthChangeCallback(boost::bind(&LLIMFloater::resetAllowedRectPadding));
sAllowedRectRightPadding = RECT_PADDING_NEED_RECALC;
}
@@ -500,10 +500,7 @@ void LLIMFloater::getAllowedRect(LLRect& rect)
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE)
{
- LLSideTray* side_bar = LLSideTray::getInstance();
-
- if (side_bar->getVisible() && !side_bar->getCollapsed())
- sAllowedRectRightPadding += side_bar->getRect().getWidth();
+ sAllowedRectRightPadding += LLSideTray::getInstance()->getVisibleWidth();
}
}
rect.mRight -= sAllowedRectRightPadding;
@@ -680,8 +677,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/llimfloater.h b/indra/newview/llimfloater.h
index e80e45e64a..5158f6c1f7 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -156,7 +156,7 @@ private:
static void closeHiddenIMToasts();
- static bool resetAllowedRectPadding(const LLSD& newvalue);
+ static bool resetAllowedRectPadding();
//need to keep this static for performance issues
static S32 sAllowedRectRightPadding;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 02a693b9a0..0ef502b81b 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())
@@ -265,9 +279,27 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name)
{
+ if (av_name.mIsTemporaryName)
+ {
+ S32 separator_index = mName.rfind(" ");
+ std::string name = mName.substr(0, separator_index);
+ ++separator_index;
+ std::string conference_word = mName.substr(separator_index, mName.length());
+
+ // additional check that session name is what we expected
+ if ("Conference" == conference_word)
+ {
LLStringUtil::format_map_t args;
- args["[AGENT_NAME]"] = av_name.getCompleteName();
+ args["[AGENT_NAME]"] = name;
LLTrans::findString(mName, "conference-title-incoming", args);
+ }
+ }
+ else
+ {
+ LLStringUtil::format_map_t args;
+ args["[AGENT_NAME]"] = av_name.getCompleteName();
+ LLTrans::findString(mName, "conference-title-incoming", args);
+ }
}
void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)
@@ -523,15 +555,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 +573,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 +1100,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()));
+ }
}
}
}
@@ -2061,7 +2107,7 @@ void LLIncomingCallDialog::onOpen(const LLSD& key)
void LLIncomingCallDialog::onAccept(void* user_data)
{
LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
- self->processCallResponse(0);
+ processCallResponse(0, self->mPayload);
self->closeFloater();
}
@@ -2069,7 +2115,7 @@ void LLIncomingCallDialog::onAccept(void* user_data)
void LLIncomingCallDialog::onReject(void* user_data)
{
LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
- self->processCallResponse(1);
+ processCallResponse(1, self->mPayload);
self->closeFloater();
}
@@ -2077,20 +2123,21 @@ void LLIncomingCallDialog::onReject(void* user_data)
void LLIncomingCallDialog::onStartIM(void* user_data)
{
LLIncomingCallDialog* self = (LLIncomingCallDialog*)user_data;
- self->processCallResponse(2);
+ processCallResponse(2, self->mPayload);
self->closeFloater();
}
-void LLIncomingCallDialog::processCallResponse(S32 response)
+// static
+void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload)
{
if (!gIMMgr || gDisconnected)
return;
- LLUUID session_id = mPayload["session_id"].asUUID();
- LLUUID caller_id = mPayload["caller_id"].asUUID();
- std::string session_name = mPayload["session_name"].asString();
- EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
- LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)mPayload["inv_type"].asInteger();
+ LLUUID session_id = payload["session_id"].asUUID();
+ LLUUID caller_id = payload["caller_id"].asUUID();
+ std::string session_name = payload["session_name"].asString();
+ EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
+ LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
bool voice = true;
switch(response)
{
@@ -2107,8 +2154,8 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
session_id = gIMMgr->addP2PSession(
session_name,
caller_id,
- mPayload["session_handle"].asString(),
- mPayload["session_uri"].asString());
+ payload["session_handle"].asString(),
+ payload["session_uri"].asString());
if (voice)
{
@@ -2142,7 +2189,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
LLAvatarName av_name;
if (LLAvatarNameCache::get(caller_id, &av_name))
{
- correct_session_name = av_name.mDisplayName + " (" + av_name.mUsername + ")";
+ correct_session_name = av_name.getCompleteName();
correct_session_name.append(ADHOC_NAME_SUFFIX);
}
}
@@ -2172,10 +2219,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
inv_type));
// send notification message to the corresponding chat
- if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc")
+ if (payload["notify_box_type"].asString() == "VoiceInviteGroup" || payload["notify_box_type"].asString() == "VoiceInviteAdHoc")
{
LLStringUtil::format_map_t string_args;
- string_args["[NAME]"] = mPayload["caller_name"].asString();
+ string_args["[NAME]"] = payload["caller_name"].asString();
std::string message = LLTrans::getString("name_started_call", string_args);
LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message);
}
@@ -2192,7 +2239,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
{
if(LLVoiceClient::getInstance())
{
- std::string s = mPayload["session_handle"].asString();
+ std::string s = payload["session_handle"].asString();
LLVoiceClient::getInstance()->declineInvite(s);
}
}
@@ -2599,16 +2646,19 @@ void LLIMMgr::inviteToSession(
std::string question_type = "VoiceInviteQuestionDefault";
BOOL ad_hoc_invite = FALSE;
+ BOOL voice_invite = FALSE;
if(type == IM_SESSION_P2P_INVITE)
{
//P2P is different...they only have voice invitations
notify_box_type = "VoiceInviteP2P";
+ voice_invite = TRUE;
}
else if ( gAgent.isInGroup(session_id) )
{
//only really old school groups have voice invitations
notify_box_type = "VoiceInviteGroup";
question_type = "VoiceInviteQuestionGroup";
+ voice_invite = TRUE;
}
else if ( inv_type == INVITATION_TYPE_VOICE )
{
@@ -2616,6 +2666,7 @@ void LLIMMgr::inviteToSession(
//and a voice ad-hoc
notify_box_type = "VoiceInviteAdHoc";
ad_hoc_invite = TRUE;
+ voice_invite = TRUE;
}
else if ( inv_type == INVITATION_TYPE_IMMEDIATE )
{
@@ -2639,23 +2690,21 @@ void LLIMMgr::inviteToSession(
if (channelp && channelp->callStarted())
{
// you have already started a call to the other user, so just accept the invite
- LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 0);
+ LLIncomingCallDialog::processCallResponse(0, payload);
return;
}
- if (type == IM_SESSION_P2P_INVITE || ad_hoc_invite)
+ if (voice_invite)
{
- // is the inviter a friend?
- if (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)
+ if ( // if we're rejecting all incoming call requests
+ gSavedSettings.getBOOL("VoiceCallsRejectAll")
+ // or we're rejecting non-friend voice calls and this isn't a friend
+ || (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL))
+ )
{
- // if not, and we are ignoring voice invites from non-friends
- // then silently decline
- if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
- {
- // invite not from a friend, so decline
- LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 1);
- return;
- }
+ // silently decline the call
+ LLIncomingCallDialog::processCallResponse(1, payload);
+ return;
}
}
@@ -2670,6 +2719,15 @@ void LLIMMgr::inviteToSession(
{
LLFloaterReg::showInstance("incoming_call", payload, FALSE);
}
+
+ // Add the caller to the Recent List here (at this point
+ // "incoming_call" floater is shown and the recipient can
+ // reject the call), because even if a recipient will reject
+ // the call, the caller should be added to the recent list
+ // anyway. STORM-507.
+ if(type == IM_SESSION_P2P_INVITE)
+ LLRecentPeople::instance().add(caller_id);
+
mPendingInvitations[session_id.asString()] = LLSD();
}
}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 650d329e18..a15776c207 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
@@ -100,7 +100,7 @@ public:
void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name);
- void onAdHocNameCache(const LLAvatarName& av_name);
+ void onAdHocNameCache(const LLAvatarName& av_name);
//*TODO make private
static std::string generateHash(const std::set<LLUUID>& sorted_uuids);
@@ -542,6 +542,7 @@ public:
static void onReject(void* user_data);
static void onStartIM(void* user_data);
+ static void processCallResponse(S32 response, const LLSD& payload);
private:
void setCallerName(const std::string& ui_title,
const std::string& ui_label,
@@ -551,7 +552,6 @@ private:
const std::string& call_type);
/*virtual*/ void onLifetimeExpired();
- void processCallResponse(S32 response);
};
class LLOutgoingCallDialog : public LLCallDialog
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 29dcb2c4d3..17d0b0ffbb 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -47,12 +47,14 @@
#include "llvoiceclient.h"
#include "llviewerobjectlist.h"
#include "lltransientfloatermgr.h"
+#include "llnotificationsutil.h"
// Linden libraries
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llmenubutton.h"
#include "lltextbox.h"
+#include "lltoggleablemenu.h"
#include "lltooltip.h" // positionViewNearMouse()
#include "lltrans.h"
#include "lluictrl.h"
@@ -125,16 +127,20 @@ private:
void onClickReport();
void onClickFreeze();
void onClickEject();
+ void onClickKick();
+ void onClickCSR();
void onClickZoomIn();
void onClickFindOnMap();
bool onVisibleFindOnMap();
- bool onVisibleFreezeEject();
+ bool onVisibleEject();
+ bool onVisibleFreeze();
bool onVisibleZoomIn();
void onClickMuteVolume();
void onVolumeChange(const LLSD& data);
bool enableMute();
bool enableUnmute();
bool enableTeleportOffer();
+ bool godModeEnabled();
// Is used to determine if "Add friend" option should be enabled in gear menu
bool isNotFriend();
@@ -213,20 +219,21 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd)
mCommitCallbackRegistrar.add("InspectAvatar.Pay", boost::bind(&LLInspectAvatar::onClickPay, this));
mCommitCallbackRegistrar.add("InspectAvatar.Share", boost::bind(&LLInspectAvatar::onClickShare, this));
mCommitCallbackRegistrar.add("InspectAvatar.ToggleMute", boost::bind(&LLInspectAvatar::onToggleMute, this));
- mCommitCallbackRegistrar.add("InspectAvatar.Freeze",
- boost::bind(&LLInspectAvatar::onClickFreeze, this));
- mCommitCallbackRegistrar.add("InspectAvatar.Eject",
- boost::bind(&LLInspectAvatar::onClickEject, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Freeze", boost::bind(&LLInspectAvatar::onClickFreeze, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Eject", boost::bind(&LLInspectAvatar::onClickEject, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.Kick", boost::bind(&LLInspectAvatar::onClickKick, this));
+ mCommitCallbackRegistrar.add("InspectAvatar.CSR", boost::bind(&LLInspectAvatar::onClickCSR, this));
mCommitCallbackRegistrar.add("InspectAvatar.Report", boost::bind(&LLInspectAvatar::onClickReport, this));
mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap", boost::bind(&LLInspectAvatar::onClickFindOnMap, this));
mCommitCallbackRegistrar.add("InspectAvatar.ZoomIn", boost::bind(&LLInspectAvatar::onClickZoomIn, this));
mCommitCallbackRegistrar.add("InspectAvatar.DisableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, false));
mCommitCallbackRegistrar.add("InspectAvatar.EnableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, true));
+
+ mEnableCallbackRegistrar.add("InspectAvatar.EnableGod", boost::bind(&LLInspectAvatar::godModeEnabled, this));
mEnableCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));
- mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreezeEject",
- boost::bind(&LLInspectAvatar::onVisibleFreezeEject, this));
- mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn",
- boost::bind(&LLInspectAvatar::onVisibleZoomIn, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.VisibleEject", boost::bind(&LLInspectAvatar::onVisibleEject, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreeze", boost::bind(&LLInspectAvatar::onVisibleFreeze, this));
+ mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", boost::bind(&LLInspectAvatar::onVisibleZoomIn, this));
mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this));
mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall));
mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableTeleportOffer", boost::bind(&LLInspectAvatar::enableTeleportOffer, this));
@@ -402,8 +409,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() )
{
@@ -655,11 +662,18 @@ bool LLInspectAvatar::onVisibleFindOnMap()
return gAgent.isGodlike() || is_agent_mappable(mAvatarID);
}
-bool LLInspectAvatar::onVisibleFreezeEject()
+bool LLInspectAvatar::onVisibleEject()
{
return enable_freeze_eject( LLSD(mAvatarID) );
}
+bool LLInspectAvatar::onVisibleFreeze()
+{
+ // either user is a god and can do long distance freeze
+ // or check for target proximity and permissions
+ return gAgent.isGodlike() || enable_freeze_eject(LLSD(mAvatarID));
+}
+
bool LLInspectAvatar::onVisibleZoomIn()
{
return gObjectList.findObject(mAvatarID);
@@ -703,7 +717,7 @@ void LLInspectAvatar::onClickShare()
void LLInspectAvatar::onToggleMute()
{
- LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT);
+ LLMute mute(mAvatarID, mAvatarName.mDisplayName, LLMute::AGENT);
if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
{
@@ -724,9 +738,41 @@ void LLInspectAvatar::onClickReport()
closeFloater();
}
+bool godlike_freeze(const LLSD& notification, const LLSD& response)
+{
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+ switch (option)
+ {
+ case 0:
+ LLAvatarActions::freeze(avatar_id);
+ break;
+ case 1:
+ LLAvatarActions::unfreeze(avatar_id);
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
void LLInspectAvatar::onClickFreeze()
{
- handle_avatar_freeze( LLSD(mAvatarID) );
+ if (gAgent.isGodlike())
+ {
+ // use godlike freeze-at-a-distance, with confirmation
+ LLNotificationsUtil::add("FreezeAvatar",
+ LLSD(),
+ LLSD().with("avatar_id", mAvatarID),
+ godlike_freeze);
+ }
+ else
+ {
+ // use default "local" version of freezing that requires avatar to be in range
+ handle_avatar_freeze( LLSD(mAvatarID) );
+ }
closeFloater();
}
@@ -736,6 +782,20 @@ void LLInspectAvatar::onClickEject()
closeFloater();
}
+void LLInspectAvatar::onClickKick()
+{
+ LLAvatarActions::kick(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickCSR()
+{
+ std::string name;
+ gCacheName->getFullName(mAvatarID, name);
+ LLAvatarActions::csr(mAvatarID, name);
+ closeFloater();
+}
+
void LLInspectAvatar::onClickZoomIn()
{
handle_zoom_to_object(mAvatarID);
@@ -784,6 +844,11 @@ bool LLInspectAvatar::enableTeleportOffer()
return LLAvatarActions::canOfferTeleport(mAvatarID);
}
+bool LLInspectAvatar::godModeEnabled()
+{
+ return gAgent.isGodlike();
+}
+
//////////////////////////////////////////////////////////////////////////////
// LLInspectAvatarUtil
//////////////////////////////////////////////////////////////////////////////
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/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp
index 58b3f0309f..d7b82667d1 100644
--- a/indra/newview/llinspecttoast.cpp
+++ b/indra/newview/llinspecttoast.cpp
@@ -46,6 +46,7 @@ public:
virtual ~LLInspectToast();
/*virtual*/ void onOpen(const LLSD& notification_id);
+ /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
private:
void onToastDestroy(LLToast * toast);
@@ -73,6 +74,7 @@ LLInspectToast::~LLInspectToast()
LLTransientFloaterMgr::getInstance()->removeControlView(this);
}
+// virtual
void LLInspectToast::onOpen(const LLSD& notification_id)
{
LLInspect::onOpen(notification_id);
@@ -103,6 +105,15 @@ void LLInspectToast::onOpen(const LLSD& notification_id)
LLUI::positionViewNearMouse(this);
}
+// virtual
+BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ // We don't like the way LLInspect handles tooltips
+ // (black tooltips look weird),
+ // so force using the default implementation (STORM-511).
+ return LLFloater::handleToolTip(x, y, mask);
+}
+
void LLInspectToast::onToastDestroy(LLToast * toast)
{
closeFloater(false);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b15dcd993a..622a5607df 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -104,6 +104,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_
bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
bool confirm_attachment_rez(const LLSD& notification, const LLSD& response);
void teleport_via_landmark(const LLUUID& asset_id);
+static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);
// +=================================================+
// | LLInvFVBridge |
@@ -1643,16 +1644,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 +1694,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 +1796,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;
}
@@ -2312,6 +2342,10 @@ void LLFolderBridge::pasteFromClipboard()
LLInventoryModel* model = getInventoryModel();
if(model && isClipboardPasteable())
{
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+
const LLUUID parent_id(mUUID);
LLDynamicArray<LLUUID> objects;
@@ -2324,7 +2358,14 @@ void LLFolderBridge::pasteFromClipboard()
LLInventoryItem *item = model->getItem(item_id);
if (item)
{
- if(LLInventoryClipboard::instance().isCutMode())
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ if (can_move_to_outfit(item, move_is_into_current_outfit))
+ {
+ dropToOutfit(item, move_is_into_current_outfit);
+ }
+ }
+ else if(LLInventoryClipboard::instance().isCutMode())
{
// move_inventory_item() is not enough,
//we have to update inventory locally too
@@ -2352,9 +2393,13 @@ void LLFolderBridge::pasteFromClipboard()
void LLFolderBridge::pasteLinkFromClipboard()
{
- const LLInventoryModel* model = getInventoryModel();
+ LLInventoryModel* model = getInventoryModel();
if(model)
{
+ const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+
const LLUUID parent_id(mUUID);
LLDynamicArray<LLUUID> objects;
@@ -2364,7 +2409,15 @@ void LLFolderBridge::pasteLinkFromClipboard()
++iter)
{
const LLUUID &object_id = (*iter);
- if (LLInventoryCategory *cat = model->getCategory(object_id))
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ LLInventoryItem *item = model->getItem(object_id);
+ if (item && can_move_to_outfit(item, move_is_into_current_outfit))
+ {
+ dropToOutfit(item, move_is_into_current_outfit);
+ }
+ }
+ else if (LLInventoryCategory *cat = model->getCategory(object_id))
{
const std::string empty_description = "";
link_inventory_item(
@@ -2661,6 +2714,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 +2731,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 +2932,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 +2946,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 +3020,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 +3036,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 +3081,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 +3116,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 +3131,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 +3196,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)
{
@@ -3128,7 +3230,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
- accept = TRUE;
+ // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder
+ // because they must contain only links to wearable items.
+ accept = !(move_is_into_current_outfit || move_is_into_outfit);
+
if(drop)
{
copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
@@ -3146,12 +3251,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);
}
@@ -4563,10 +4674,18 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
else
{
items.push_back(std::string("Wearable And Object Wear"));
- items.push_back(std::string("Wearable Add"));
disabled_items.push_back(std::string("Take Off"));
disabled_items.push_back(std::string("Wearable Edit"));
}
+
+ if (LLWearableType::getAllowMultiwear(mWearableType))
+ {
+ items.push_back(std::string("Wearable Add"));
+ if (gAgentWearables.getWearableCount(mWearableType) > 0)
+ {
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ }
break;
default:
break;
@@ -5236,11 +5355,6 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menuentry_vec_t disabled_items, items = getMenuItems();
- items.erase(std::remove(items.begin(), items.end(), std::string("New Body Parts")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Clothes")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Note")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Gesture")), items.end());
- items.erase(std::remove(items.begin(), items.end(), std::string("New Script")), items.end());
items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
hide_context_entries(menu, items, disabled_items);
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index ef4774a06d..e22363c2f6 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -393,18 +393,22 @@ void LLInventoryFilter::setFilterUUID(const LLUUID& object_id)
void LLInventoryFilter::setFilterSubString(const std::string& string)
{
- if (mFilterSubString != string)
+ std::string filter_sub_string_new = string;
+ mFilterSubStringOrig = string;
+ LLStringUtil::trimHead(filter_sub_string_new);
+ LLStringUtil::toUpper(filter_sub_string_new);
+
+ if (mFilterSubString != filter_sub_string_new)
{
// hitting BACKSPACE, for example
- const BOOL less_restrictive = mFilterSubString.size() >= string.size() && !mFilterSubString.substr(0, string.size()).compare(string);
+ const BOOL less_restrictive = mFilterSubString.size() >= filter_sub_string_new.size()
+ && !mFilterSubString.substr(0, filter_sub_string_new.size()).compare(filter_sub_string_new);
// appending new characters
- const BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString);
+ const BOOL more_restrictive = mFilterSubString.size() < filter_sub_string_new.size()
+ && !filter_sub_string_new.substr(0, mFilterSubString.size()).compare(mFilterSubString);
- mFilterSubStringOrig = string;
- LLStringUtil::trimHead(mFilterSubStringOrig);
- mFilterSubString = mFilterSubStringOrig;
- LLStringUtil::toUpper(mFilterSubString);
+ mFilterSubString = filter_sub_string_new;
if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f3d9639dee..ba9bea02b9 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -483,16 +483,10 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryIte
switch(item->getType())
{
- case LLAssetType::AT_CALLINGCARD:
- 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:
@@ -689,6 +683,12 @@ bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* it
return false;
}
+ // Skip broken links.
+ if (vitem->getIsBrokenLink())
+ {
+ return false;
+ }
+
return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
}
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 7216d61e7f..95dea219a8 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"));
@@ -82,8 +82,10 @@ LLIconDictionary::LLIconDictionary()
addEntry(LLInventoryIcon::ICONNAME_ANIMATION, new IconEntry("Inv_Animation"));
addEntry(LLInventoryIcon::ICONNAME_GESTURE, new IconEntry("Inv_Gesture"));
+ addEntry(LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, new IconEntry("Inv_Physics"));
+
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/llinventoryicon.h b/indra/newview/llinventoryicon.h
index 9a2cc08095..694b56d572 100644
--- a/indra/newview/llinventoryicon.h
+++ b/indra/newview/llinventoryicon.h
@@ -66,9 +66,11 @@ public:
ICONNAME_CLOTHING_SKIRT,
ICONNAME_CLOTHING_ALPHA,
ICONNAME_CLOTHING_TATTOO,
-
+
ICONNAME_ANIMATION,
ICONNAME_GESTURE,
+
+ ICONNAME_CLOTHING_PHYSICS,
ICONNAME_LINKITEM,
ICONNAME_LINKFOLDER,
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/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index eab8f187a7..e31360fcbc 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -181,8 +181,8 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
if (mBackgroundFetchActive && gAgent.getRegion())
{
// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
- std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
- if (!url.empty())
+ std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
+ if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty())
{
bulkFetch(url);
return;
@@ -604,7 +604,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
}
if (body_lib["folders"].size())
{
- std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
+ std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 91ff8c7867..0fd4b2bee5 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -203,8 +203,8 @@ void fetch_items_from_llsd(const LLSD& items_llsd)
{
if (!items_llsd.size() || gDisconnected) return;
LLSD body;
- body[0]["cap_name"] = "FetchInventory";
- body[1]["cap_name"] = "FetchLib";
+ body[0]["cap_name"] = "FetchInventory2";
+ body[1]["cap_name"] = "FetchLib2";
for (S32 i=0; i<items_llsd.size();i++)
{
if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 50adae09c0..1dcb91ad4d 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -60,6 +60,7 @@ static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
//
// Bridge to support knowing when the inventory has changed.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
class LLInventoryPanelObserver : public LLInventoryObserver
{
public:
@@ -73,9 +74,57 @@ protected:
LLInventoryPanel* mIP;
};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInvPanelComplObserver
+//
+// Calls specified callback when all specified items become complete.
+//
+// Usage:
+// observer = new LLInvPanelComplObserver(boost::bind(onComplete));
+// inventory->addObserver(observer);
+// observer->reset(); // (optional)
+// observer->watchItem(incomplete_item1_id);
+// observer->watchItem(incomplete_item2_id);
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInvPanelComplObserver : public LLInventoryCompletionObserver
+{
+public:
+ typedef boost::function<void()> callback_t;
+
+ LLInvPanelComplObserver(callback_t cb)
+ : mCallback(cb)
+ {
+ }
+
+ void reset();
+
+private:
+ /*virtual*/ void done();
+
+ /// Called when all the items are complete.
+ callback_t mCallback;
+};
+
+void LLInvPanelComplObserver::reset()
+{
+ mIncomplete.clear();
+ mComplete.clear();
+}
+
+void LLInvPanelComplObserver::done()
+{
+ mCallback();
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryPanel
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
LLPanel(p),
mInventoryObserver(NULL),
+ mCompletionObserver(NULL),
mFolderRoot(NULL),
mScroller(NULL),
mSortOrderSetting(p.sort_order_setting),
@@ -152,6 +201,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
mInventoryObserver = new LLInventoryPanelObserver(this);
mInventory->addObserver(mInventoryObserver);
+ mCompletionObserver = new LLInvPanelComplObserver(boost::bind(&LLInventoryPanel::onItemsCompletion, this));
+ mInventory->addObserver(mCompletionObserver);
+
// Build view of inventory if we need default full hierarchy and inventory ready,
// otherwise wait for idle callback.
if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mViewsInitialized)
@@ -189,7 +241,10 @@ LLInventoryPanel::~LLInventoryPanel()
// LLView destructor will take care of the sub-views.
mInventory->removeObserver(mInventoryObserver);
+ mInventory->removeObserver(mCompletionObserver);
delete mInventoryObserver;
+ delete mCompletionObserver;
+
mScroller = NULL;
}
@@ -290,7 +345,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
@@ -651,6 +709,11 @@ void LLInventoryPanel::openStartFolderOrMyInventory()
}
}
+void LLInventoryPanel::onItemsCompletion()
+{
+ if (mFolderRoot) mFolderRoot->updateMenu();
+}
+
void LLInventoryPanel::openSelected()
{
LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem();
@@ -754,6 +817,19 @@ void LLInventoryPanel::clearSelection()
void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
{
+ // Schedule updating the folder view context menu when all selected items become complete (STORM-373).
+ mCompletionObserver->reset();
+ for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it)
+ {
+ LLUUID id = (*it)->getListener()->getUUID();
+ LLViewerInventoryItem* inv_item = mInventory->getItem(id);
+
+ if (inv_item && !inv_item->isFinished())
+ {
+ mCompletionObserver->watchItem(id);
+ }
+ }
+
LLFolderView* fv = getRootFolder();
if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
{
@@ -918,6 +994,8 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
{
S32 z_min = S32_MAX;
LLInventoryPanel* res = NULL;
+ LLFloater* active_inv_floaterp = NULL;
+
// A. If the inventory side panel is open, use that preferably.
if (is_inventorysp_active())
{
@@ -938,6 +1016,7 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
{
res = inventorySP->getActivePanel();
z_min = gFloaterView->getZOrder(inv_floater);
+ active_inv_floaterp = inv_floater;
}
else
{
@@ -957,10 +1036,19 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
{
res = iv->getPanel();
z_min = z_order;
+ active_inv_floaterp = iv;
}
}
}
- if (res) return res;
+
+ if (res)
+ {
+ // Make sure the floater is not minimized (STORM-438).
+ if (active_inv_floaterp && active_inv_floaterp->isMinimized())
+ active_inv_floaterp->setMinimized(FALSE);
+
+ return res;
+ }
// C. If no panels are open and we don't want to force open a panel, then just abort out.
if (!auto_open) return NULL;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 6545fc0d5e..9da9f7d8ba 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -52,6 +52,7 @@ class LLIconCtrl;
class LLSaveFolderState;
class LLFilterEditor;
class LLTabContainer;
+class LLInvPanelComplObserver;
class LLInventoryPanel : public LLPanel
{
@@ -167,9 +168,11 @@ public:
protected:
void openStartFolderOrMyInventory(); // open the first level of inventory
+ void onItemsCompletion(); // called when selected items are complete
LLInventoryModel* mInventory;
LLInventoryObserver* mInventoryObserver;
+ LLInvPanelComplObserver* mCompletionObserver;
BOOL mAllowMultiSelect;
BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons
diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp
index ea744072d2..6421ab42bf 100644
--- a/indra/newview/lllistcontextmenu.cpp
+++ b/indra/newview/lllistcontextmenu.cpp
@@ -36,7 +36,6 @@
#include "llviewermenu.h" // for LLViewerMenuHolderGL
LLListContextMenu::LLListContextMenu()
-: mMenu(NULL)
{
}
@@ -51,23 +50,22 @@ LLListContextMenu::~LLListContextMenu()
// of mMenu has already been deleted except of using LLHandle. EXT-4762.
if (!mMenuHandle.isDead())
{
- mMenu->die();
- mMenu = NULL;
+ mMenuHandle.get()->die();
}
}
void LLListContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y)
{
- if (mMenu)
+ LLContextMenu* menup = mMenuHandle.get();
+ if (menup)
{
//preventing parent (menu holder) from deleting already "dead" context menus on exit
- LLView* parent = mMenu->getParent();
+ LLView* parent = menup->getParent();
if (parent)
{
- parent->removeChild(mMenu);
+ parent->removeChild(menup);
}
- delete mMenu;
- mMenu = NULL;
+ delete menup;
mUUIDs.clear();
}
@@ -79,23 +77,23 @@ void LLListContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32
mUUIDs.resize(uuids.size());
std::copy(uuids.begin(), uuids.end(), mUUIDs.begin());
- mMenu = createMenu();
- if (!mMenu)
+ menup = createMenu();
+ if (!menup)
{
llwarns << "Context menu creation failed" << llendl;
return;
}
- mMenuHandle = mMenu->getHandle();
- mMenu->show(x, y);
- LLMenuGL::showPopup(spawning_view, mMenu, x, y);
+ mMenuHandle = menup->getHandle();
+ menup->show(x, y);
+ LLMenuGL::showPopup(spawning_view, menup, x, y);
}
void LLListContextMenu::hide()
{
- if(mMenu)
+ if(mMenuHandle.get())
{
- mMenu->hide();
+ mMenuHandle.get()->hide();
}
}
diff --git a/indra/newview/lllistcontextmenu.h b/indra/newview/lllistcontextmenu.h
index 5dedc30b0c..fabd68ee20 100644
--- a/indra/newview/lllistcontextmenu.h
+++ b/indra/newview/lllistcontextmenu.h
@@ -71,8 +71,7 @@ protected:
static void handleMultiple(functor_t functor, const uuid_vec_t& ids);
uuid_vec_t mUUIDs;
- LLContextMenu* mMenu;
- LLHandle<LLView> mMenuHandle;
+ LLHandle<LLContextMenu> mMenuHandle;
};
#endif // LL_LLLISTCONTEXTMENU_H
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 1527f8f4c9..5c65dcec34 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -211,7 +211,6 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
{
// Lets replace default LLLineEditor with LLLocationLineEditor
// to make needed escaping while copying and cutting url
- this->removeChild(mTextEntry);
delete mTextEntry;
// Can't access old mTextEntry fields as they are protected, so lets build new params
@@ -547,6 +546,10 @@ void LLLocationInputCtrl::onFocusLost()
{
LLUICtrl::onFocusLost();
refreshLocation();
+
+ // Setting cursor to 0 to show the left edge of the text. See STORM-370.
+ mTextEntry->setCursor(0);
+
if(mTextEntry->hasSelection()){
mTextEntry->deselect();
}
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 8c70b1e973..2df683861a 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -41,6 +41,7 @@
#include <boost/regex/v4/match_results.hpp>
#if LL_MSVC
+#pragma warning(push)
// disable warning about boost::lexical_cast unreachable code
// when it fails to parse the string
#pragma warning (disable:4702)
@@ -89,6 +90,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 +193,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 +393,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 +592,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..33e051bfab 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -42,33 +42,441 @@
// newview
#include "llviewernetwork.h"
#include "llviewercontrol.h"
+#include "llversioninfo.h"
#include "llslurl.h"
#include "llstartup.h"
#include "llfloaterreg.h"
#include "llnotifications.h"
#include "llwindow.h"
#include "llviewerwindow.h"
+#include "llprogressview.h"
#if LL_LINUX || LL_SOLARIS
#include "lltrans.h"
#endif
#include "llsecapi.h"
#include "llstartup.h"
#include "llmachineid.h"
+#include "llupdaterservice.h"
+#include "llevents.h"
+#include "llnotificationsutil.h"
+#include "llappviewer.h"
+
+#include <boost/scoped_ptr.hpp>
+#include <sstream>
+
+class LLLoginInstance::Disposable {
+public:
+ virtual ~Disposable() {}
+};
+
+namespace {
+ class MandatoryUpdateMachine:
+ public LLLoginInstance::Disposable
+ {
+ public:
+ MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService);
+
+ void start(void);
+
+ private:
+ class State;
+ class CheckingForUpdate;
+ class Error;
+ class ReadyToInstall;
+ class StartingUpdaterService;
+ class WaitingForDownload;
+
+ LLLoginInstance & mLoginInstance;
+ boost::scoped_ptr<State> mState;
+ LLUpdaterService & mUpdaterService;
+
+ void setCurrentState(State * newState);
+ };
+
+
+ class MandatoryUpdateMachine::State {
+ public:
+ virtual ~State() {}
+ virtual void enter(void) {}
+ virtual void exit(void) {}
+ };
+
+
+ class MandatoryUpdateMachine::CheckingForUpdate:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ CheckingForUpdate(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+
+ private:
+ LLTempBoundListener mConnection;
+ MandatoryUpdateMachine & mMachine;
+ LLProgressView * mProgressView;
+
+ bool onEvent(LLSD const & event);
+ };
+
+
+ class MandatoryUpdateMachine::Error:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ Error(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+ void onButtonClicked(const LLSD &, const LLSD &);
+
+ private:
+ MandatoryUpdateMachine & mMachine;
+ };
+
+
+ class MandatoryUpdateMachine::ReadyToInstall:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ ReadyToInstall(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+
+ private:
+ MandatoryUpdateMachine & mMachine;
+ };
+
+
+ class MandatoryUpdateMachine::StartingUpdaterService:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ StartingUpdaterService(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+ void onButtonClicked(const LLSD & uiform, const LLSD & result);
+ private:
+ MandatoryUpdateMachine & mMachine;
+ };
+
+
+ class MandatoryUpdateMachine::WaitingForDownload:
+ public MandatoryUpdateMachine::State
+ {
+ public:
+ WaitingForDownload(MandatoryUpdateMachine & machine);
+
+ virtual void enter(void);
+ virtual void exit(void);
+
+ private:
+ LLTempBoundListener mConnection;
+ MandatoryUpdateMachine & mMachine;
+ LLProgressView * mProgressView;
+
+ bool onEvent(LLSD const & event);
+ };
+}
static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
std::string construct_start_string();
+
+
+// MandatoryUpdateMachine
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService):
+ mLoginInstance(loginInstance),
+ mUpdaterService(updaterService)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::start(void)
+{
+ llinfos << "starting manditory update machine" << llendl;
+
+ if(mUpdaterService.isChecking()) {
+ switch(mUpdaterService.getState()) {
+ case LLUpdaterService::UP_TO_DATE:
+ mUpdaterService.stopChecking();
+ mUpdaterService.startChecking();
+ // Fall through.
+ case LLUpdaterService::INITIAL:
+ case LLUpdaterService::CHECKING_FOR_UPDATE:
+ setCurrentState(new CheckingForUpdate(*this));
+ break;
+ case LLUpdaterService::TEMPORARY_ERROR:
+ setCurrentState(new Error(*this));
+ break;
+ case LLUpdaterService::DOWNLOADING:
+ setCurrentState(new WaitingForDownload(*this));
+ break;
+ case LLUpdaterService::TERMINAL:
+ if(LLUpdaterService::updateReadyToInstall()) {
+ setCurrentState(new ReadyToInstall(*this));
+ } else {
+ setCurrentState(new Error(*this));
+ }
+ break;
+ case LLUpdaterService::FAILURE:
+ setCurrentState(new Error(*this));
+ break;
+ default:
+ llassert(!"unpossible case");
+ break;
+ }
+ } else {
+ setCurrentState(new StartingUpdaterService(*this));
+ }
+}
+
+
+void MandatoryUpdateMachine::setCurrentState(State * newStatePointer)
+{
+ {
+ boost::scoped_ptr<State> newState(newStatePointer);
+ if(mState != 0) mState->exit();
+ mState.swap(newState);
+
+ // Old state will be deleted on exit from this block before the new state
+ // is entered.
+ }
+ if(mState != 0) mState->enter();
+}
+
+
+
+// MandatoryUpdateMachine::CheckingForUpdate
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::CheckingForUpdate::CheckingForUpdate(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::CheckingForUpdate::enter(void)
+{
+ llinfos << "entering checking for update" << llendl;
+
+ mProgressView = gViewerWindow->getProgressView();
+ mProgressView->setMessage("Looking for update...");
+ mProgressView->setText("There is a required update for your Second Life installation.");
+ mProgressView->setPercent(0);
+ mProgressView->setVisible(true);
+ mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).
+ listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::CheckingForUpdate::onEvent, this, _1));
+}
+
+
+void MandatoryUpdateMachine::CheckingForUpdate::exit(void)
+{
+}
+
+
+bool MandatoryUpdateMachine::CheckingForUpdate::onEvent(LLSD const & event)
+{
+ if(event["type"].asInteger() == LLUpdaterService::STATE_CHANGE) {
+ switch(event["state"].asInteger()) {
+ case LLUpdaterService::DOWNLOADING:
+ mMachine.setCurrentState(new WaitingForDownload(mMachine));
+ break;
+ case LLUpdaterService::TEMPORARY_ERROR:
+ case LLUpdaterService::UP_TO_DATE:
+ case LLUpdaterService::TERMINAL:
+ case LLUpdaterService::FAILURE:
+ mProgressView->setVisible(false);
+ mMachine.setCurrentState(new Error(mMachine));
+ break;
+ case LLUpdaterService::INSTALLING:
+ llassert(!"can't possibly be installing");
+ break;
+ default:
+ break;
+ }
+ } else {
+ ; // Ignore.
+ }
+
+ return false;
+}
+
+
+
+// MandatoryUpdateMachine::Error
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::Error::Error(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::Error::enter(void)
+{
+ llinfos << "entering error" << llendl;
+ LLNotificationsUtil::add("FailedRequiredUpdateInstall", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::Error::onButtonClicked, this, _1, _2));
+}
+
+
+void MandatoryUpdateMachine::Error::exit(void)
+{
+ LLAppViewer::instance()->forceQuit();
+}
+
+
+void MandatoryUpdateMachine::Error::onButtonClicked(const LLSD &, const LLSD &)
+{
+ mMachine.setCurrentState(0);
+}
+
+
+
+// MandatoryUpdateMachine::ReadyToInstall
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::ReadyToInstall::ReadyToInstall(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::ReadyToInstall::enter(void)
+{
+ llinfos << "entering ready to install" << llendl;
+ // Open update ready dialog.
+}
+
+
+void MandatoryUpdateMachine::ReadyToInstall::exit(void)
+{
+ // Restart viewer.
+}
+
+
+
+// MandatoryUpdateMachine::StartingUpdaterService
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::StartingUpdaterService::StartingUpdaterService(MandatoryUpdateMachine & machine):
+ mMachine(machine)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::StartingUpdaterService::enter(void)
+{
+ llinfos << "entering start update service" << llendl;
+ LLNotificationsUtil::add("UpdaterServiceNotRunning", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked, this, _1, _2));
+}
+
+
+void MandatoryUpdateMachine::StartingUpdaterService::exit(void)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked(const LLSD & uiform, const LLSD & result)
+{
+ if(result["OK_okcancelbuttons"].asBoolean()) {
+ mMachine.mUpdaterService.startChecking(false);
+ mMachine.setCurrentState(new CheckingForUpdate(mMachine));
+ } else {
+ LLAppViewer::instance()->forceQuit();
+ }
+}
+
+
+
+// MandatoryUpdateMachine::WaitingForDownload
+//-----------------------------------------------------------------------------
+
+
+MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMachine & machine):
+ mMachine(machine),
+ mProgressView(0)
+{
+ ; // No op.
+}
+
+
+void MandatoryUpdateMachine::WaitingForDownload::enter(void)
+{
+ llinfos << "entering waiting for download" << llendl;
+ mProgressView = gViewerWindow->getProgressView();
+ mProgressView->setMessage("Downloading update...");
+ std::ostringstream stream;
+ stream << "There is a required update for your Second Life installation." << std::endl <<
+ "Version " << mMachine.mUpdaterService.updatedVersion();
+ mProgressView->setText(stream.str());
+ mProgressView->setPercent(0);
+ mProgressView->setVisible(true);
+ mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).
+ listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::WaitingForDownload::onEvent, this, _1));
+}
+
+
+void MandatoryUpdateMachine::WaitingForDownload::exit(void)
+{
+ mProgressView->setVisible(false);
+}
+
+
+bool MandatoryUpdateMachine::WaitingForDownload::onEvent(LLSD const & event)
+{
+ switch(event["type"].asInteger()) {
+ case LLUpdaterService::DOWNLOAD_COMPLETE:
+ mMachine.setCurrentState(new ReadyToInstall(mMachine));
+ break;
+ case LLUpdaterService::DOWNLOAD_ERROR:
+ mMachine.setCurrentState(new Error(mMachine));
+ break;
+ case LLUpdaterService::PROGRESS: {
+ double downloadSize = event["download_size"].asReal();
+ double bytesDownloaded = event["bytes_downloaded"].asReal();
+ mProgressView->setPercent(100. * bytesDownloaded / downloadSize);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return false;
+}
+
+
+
+// LLLoginInstance
+//-----------------------------------------------------------------------------
+
+
LLLoginInstance::LLLoginInstance() :
mLoginModule(new LLLogin()),
mNotifications(NULL),
mLoginState("offline"),
- mUserInteraction(true),
mSkipOptionalUpdate(false),
mAttemptComplete(false),
mTransferRate(0.0f),
- mDispatcher("LLLoginInstance", "change")
+ mDispatcher("LLLoginInstance", "change"),
+ mUpdaterService(0)
{
mLoginModule->getEventPump().listen("lllogininstance",
boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
@@ -149,6 +557,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,9 +590,10 @@ 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;
+ request_params["host_id"] = gSavedSettings.getString("HostID");
mRequestData.clear();
mRequestData["method"] = "login_to_simulator";
@@ -230,64 +640,57 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
LLSD response = event["data"];
std::string reason_response = response["reason"].asString();
std::string message_response = response["message"].asString();
- if(mUserInteraction)
+ // For the cases of critical message or TOS agreement,
+ // start the TOS dialog. The dialog response will be handled
+ // by the LLLoginInstance::handleTOSResponse() callback.
+ // The callback intiates the login attempt next step, either
+ // to reconnect or to end the attempt in failure.
+ if(reason_response == "tos")
{
- // For the cases of critical message or TOS agreement,
- // start the TOS dialog. The dialog response will be handled
- // by the LLLoginInstance::handleTOSResponse() callback.
- // The callback intiates the login attempt next step, either
- // to reconnect or to end the attempt in failure.
- if(reason_response == "tos")
- {
- LLSD data(LLSD::emptyMap());
- data["message"] = message_response;
- data["reply_pump"] = TOS_REPLY_PUMP;
- gViewerWindow->setShowProgress(FALSE);
- LLFloaterReg::showInstance("message_tos", data);
- LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
- .listen(TOS_LISTENER_NAME,
- boost::bind(&LLLoginInstance::handleTOSResponse,
- this, _1, "agree_to_tos"));
- }
- else if(reason_response == "critical")
- {
- LLSD data(LLSD::emptyMap());
- data["message"] = message_response;
- data["reply_pump"] = TOS_REPLY_PUMP;
- if(response.has("error_code"))
- {
- data["error_code"] = response["error_code"];
- }
- if(response.has("certificate"))
- {
- data["certificate"] = response["certificate"];
- }
-
- gViewerWindow->setShowProgress(FALSE);
- LLFloaterReg::showInstance("message_critical", data);
- LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
- .listen(TOS_LISTENER_NAME,
- boost::bind(&LLLoginInstance::handleTOSResponse,
- this, _1, "read_critical"));
- }
- else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
+ LLSD data(LLSD::emptyMap());
+ data["message"] = message_response;
+ data["reply_pump"] = TOS_REPLY_PUMP;
+ gViewerWindow->setShowProgress(FALSE);
+ LLFloaterReg::showInstance("message_tos", data);
+ LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
+ .listen(TOS_LISTENER_NAME,
+ boost::bind(&LLLoginInstance::handleTOSResponse,
+ this, _1, "agree_to_tos"));
+ }
+ else if(reason_response == "critical")
+ {
+ LLSD data(LLSD::emptyMap());
+ data["message"] = message_response;
+ data["reply_pump"] = TOS_REPLY_PUMP;
+ if(response.has("error_code"))
{
- gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
- updateApp(true, message_response);
+ data["error_code"] = response["error_code"];
}
- else if(reason_response == "optional")
+ if(response.has("certificate"))
{
- updateApp(false, message_response);
+ data["certificate"] = response["certificate"];
}
- else
- {
- attemptComplete();
- }
+
+ gViewerWindow->setShowProgress(FALSE);
+ LLFloaterReg::showInstance("message_critical", data);
+ LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
+ .listen(TOS_LISTENER_NAME,
+ boost::bind(&LLLoginInstance::handleTOSResponse,
+ this, _1, "read_critical"));
}
- else // no user interaction
+ else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
{
- attemptComplete();
+ gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
+ updateApp(true, message_response);
+ }
+ else if(reason_response == "optional")
+ {
+ updateApp(false, message_response);
}
+ else
+ {
+ attemptComplete();
+ }
}
void LLLoginInstance::handleLoginSuccess(const LLSD& event)
@@ -351,6 +754,15 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
{
+ if(mandatory)
+ {
+ gViewerWindow->setShowProgress(false);
+ MandatoryUpdateMachine * machine = new MandatoryUpdateMachine(*this, *mUpdaterService);
+ mUpdateStateMachine.reset(machine);
+ machine->start();
+ return;
+ }
+
// store off config state, as we might quit soon
gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
LLUIColorTable::instance().saveUserSettings();
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 159e05046c..8b53431219 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -34,12 +34,15 @@
class LLLogin;
class LLEventStream;
class LLNotificationsInterface;
+class LLUpdaterService;
// This class hosts the login module and is used to
// negotiate user authentication attempts.
class LLLoginInstance : public LLSingleton<LLLoginInstance>
{
public:
+ class Disposable;
+
LLLoginInstance();
~LLLoginInstance();
@@ -58,12 +61,6 @@ public:
// Only valid when authSuccess == true.
const F64 getLastTransferRateBPS() { return mTransferRate; }
- // Set whether this class will drive user interaction.
- // If not, login failures like 'need tos agreement' will
- // end the login attempt.
- void setUserInteraction(bool state) { mUserInteraction = state; }
- bool getUserInteraction() { return mUserInteraction; }
-
// Whether to tell login to skip optional update request.
// False by default.
void setSkipOptionalUpdate(bool state) { mSkipOptionalUpdate = state; }
@@ -75,6 +72,7 @@ public:
typedef boost::function<void()> UpdaterLauncherCallback;
void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }
+ void setUpdaterService(LLUpdaterService * updaterService) { mUpdaterService = updaterService; }
private:
void constructAuthParams(LLPointer<LLCredential> user_credentials);
void updateApp(bool mandatory, const std::string& message);
@@ -96,7 +94,6 @@ private:
std::string mLoginState;
LLSD mRequestData;
LLSD mResponseData;
- bool mUserInteraction;
bool mSkipOptionalUpdate;
bool mAttemptComplete;
F64 mTransferRate;
@@ -104,6 +101,8 @@ private:
int mLastExecEvent;
UpdaterLauncherCallback mUpdaterLauncher;
LLEventDispatcher mDispatcher;
+ LLUpdaterService * mUpdaterService;
+ boost::scoped_ptr<Disposable> mUpdateStateMachine;
};
#endif
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/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index 43a16f8ed8..f1c7e952d1 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -901,32 +901,32 @@ void LLManipRotate::renderSnapGuides()
{
if (i == 0)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Forward") : LLTrans::getString("East"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white);
}
else if (i == 16)
{
if (constraint_axis.mV[VZ] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Left") : LLTrans::getString("North"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Right") : LLTrans::getString("South"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white);
}
}
else if (i == 32)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Back") : LLTrans::getString("West"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white);
}
else
{
if (constraint_axis.mV[VZ] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Right") : LLTrans::getString("South"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Left") : LLTrans::getString("North"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white);
}
}
}
@@ -934,32 +934,32 @@ void LLManipRotate::renderSnapGuides()
{
if (i == 0)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Left") : LLTrans::getString("North"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white);
}
else if (i == 16)
{
if (constraint_axis.mV[VX] > 0.f)
{
- renderTickText(text_point, LLTrans::getString("Up"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white);
}
else
{
- renderTickText(text_point, LLTrans::getString("Down"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white);
}
}
else if (i == 32)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Right") : LLTrans::getString("South"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white);
}
else
{
if (constraint_axis.mV[VX] > 0.f)
{
- renderTickText(text_point, LLTrans::getString("Down"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white);
}
else
{
- renderTickText(text_point, LLTrans::getString("Up"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white);
}
}
}
@@ -967,32 +967,32 @@ void LLManipRotate::renderSnapGuides()
{
if (i == 0)
{
- renderTickText(text_point, LLTrans::getString("Up"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white);
}
else if (i == 16)
{
if (constraint_axis.mV[VY] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Forward") : LLTrans::getString("East"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Back") : LLTrans::getString("West"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white);
}
}
else if (i == 32)
{
- renderTickText(text_point, LLTrans::getString("Down"), LLColor4::white);
+ renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white);
}
else
{
if (constraint_axis.mV[VY] > 0.f)
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Back") : LLTrans::getString("West"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white);
}
else
{
- renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Forward") : LLTrans::getString("East"), LLColor4::white);
+ renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white);
}
}
}
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/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index e84c9152b1..9493fddf50 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -25,7 +25,7 @@
*/
#include "llviewerprecompiledheaders.h"
-
+#include "lltooltip.h"
#include "llmediactrl.h"
@@ -54,6 +54,10 @@
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llnotifications.h"
+#include "lllineeditor.h"
+#include "llfloatermediabrowser.h"
+#include "llfloaterwebcontent.h"
+#include "llwindowshade.h"
extern BOOL gRestoreGL;
@@ -70,7 +74,8 @@ LLMediaCtrl::Params::Params()
caret_color("caret_color"),
initial_mime_type("initial_mime_type"),
media_id("media_id"),
- trusted_content("trusted_content", false)
+ trusted_content("trusted_content", false),
+ focus_on_click("focus_on_click", true)
{
tab_stop(false);
}
@@ -86,7 +91,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mIgnoreUIScale( true ),
mAlwaysRefresh( false ),
mMediaSource( 0 ),
- mTakeFocusOnClick( true ),
+ mTakeFocusOnClick( p.focus_on_click ),
mCurrentNavUrl( "" ),
mStretchToFill( true ),
mMaintainAspectRatio ( true ),
@@ -97,7 +102,9 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mTextureHeight ( 1024 ),
mClearCache(false),
mHomePageMimeType(p.initial_mime_type),
- mTrusted(p.trusted_content)
+ mTrusted(p.trusted_content),
+ mWindowShade(NULL),
+ mHoverTextChanged(false)
{
{
LLColor4 color = p.caret_color().get();
@@ -126,7 +133,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
setTextureSize(screen_width, screen_height);
}
- mMediaTextureID.generate();
+ mMediaTextureID = getKey();
// We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
if(!mHomePageUrl.empty())
@@ -140,8 +147,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
// addChild( mBorder );
}
-////////////////////////////////////////////////////////////////////////////////
-// note: this is now a singleton and destruction happens via initClass() now
LLMediaCtrl::~LLMediaCtrl()
{
@@ -181,6 +186,13 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
mMediaSource->mouseMove(x, y, mask);
gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
}
+
+ // TODO: Is this the right way to handle hover text changes driven by the plugin?
+ if(mHoverTextChanged)
+ {
+ mHoverTextChanged = false;
+ handleToolTip(x, y, mask);
+ }
return TRUE;
}
@@ -197,6 +209,35 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
}
////////////////////////////////////////////////////////////////////////////////
+// virtual
+BOOL LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask)
+{
+ std::string hover_text;
+
+ if (mMediaSource && mMediaSource->hasMedia())
+ hover_text = mMediaSource->getMediaPlugin()->getHoverText();
+
+ if(hover_text.empty())
+ {
+ return FALSE;
+ }
+ else
+ {
+ S32 screen_x, screen_y;
+
+ localPointToScreen(x, y, &screen_x, &screen_y);
+ LLRect sticky_rect_screen;
+ sticky_rect_screen.setCenterAndSize(screen_x, screen_y, 20, 20);
+
+ LLToolTipMgr::instance().show(LLToolTip::Params()
+ .message(hover_text)
+ .sticky_rect(sticky_rect_screen));
+ }
+
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
//
BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
{
@@ -206,14 +247,6 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
if (mMediaSource)
{
mMediaSource->mouseUp(x, y, mask);
-
- // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
- // in addition to the onFocusReceived() call below. Undo this. JC
- if (!mTakeFocusOnClick)
- {
- mMediaSource->focus(false);
- gViewerWindow->focusClient();
- }
}
gFocusMgr.setMouseCapture( NULL );
@@ -345,85 +378,6 @@ void LLMediaCtrl::onFocusLost()
//
BOOL LLMediaCtrl::postBuild ()
{
- LLLayoutStack::Params layout_p;
- layout_p.name = "notification_stack";
- layout_p.rect = LLRect(0,getLocalRect().mTop,getLocalRect().mRight, 30);
- layout_p.follows.flags = FOLLOWS_ALL;
- layout_p.mouse_opaque = false;
- layout_p.orientation = "vertical";
-
- LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p);
- addChild(stackp);
-
- LLLayoutPanel::Params panel_p;
- panel_p.rect = LLRect(0, 30, 800, 0);
- panel_p.min_height = 30;
- panel_p.name = "notification_area";
- panel_p.visible = false;
- panel_p.user_resize = false;
- panel_p.background_visible = true;
- panel_p.bg_alpha_image.name = "Yellow_Gradient";
- panel_p.auto_resize = false;
- LLLayoutPanel* notification_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(notification_panel);
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.auto_resize = true;
- panel_p.mouse_opaque = false;
- LLLayoutPanel* dummy_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(dummy_panel);
-
- layout_p = LLUICtrlFactory::getDefaultParams<LLLayoutStack>();
- layout_p.rect = LLRect(0, 30, 800, 0);
- layout_p.follows.flags = FOLLOWS_ALL;
- layout_p.orientation = "horizontal";
- stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p);
- notification_panel->addChild(stackp);
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.rect.height = 30;
- LLLayoutPanel* panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(panel);
-
- LLIconCtrl::Params icon_p;
- icon_p.name = "notification_icon";
- icon_p.rect = LLRect(5, 23, 21, 8);
- panel->addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_p));
-
- LLTextBox::Params text_p;
- text_p.rect = LLRect(31, 20, 430, 0);
- text_p.text_color = LLColor4::black;
- text_p.font = LLFontGL::getFontSansSerif();
- text_p.font.style = "BOLD";
- text_p.name = "notification_text";
- text_p.use_ellipses = true;
- panel->addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.auto_resize = false;
- panel_p.user_resize = false;
- panel_p.name="form_elements";
- panel_p.rect = LLRect(0, 30, 130, 0);
- LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(form_elements_panel);
-
- panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>();
- panel_p.auto_resize = false;
- panel_p.user_resize = false;
- panel_p.rect = LLRect(0, 30, 25, 0);
- LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p);
- stackp->addChild(close_panel);
-
- LLButton::Params button_p;
- button_p.name = "close_notification";
- button_p.rect = LLRect(5, 23, 21, 7);
- button_p.image_color=LLUIColorTable::instance().getColor("DkGray_66");
- button_p.image_unselected.name="Icon_Close_Foreground";
- button_p.image_selected.name="Icon_Close_Press";
- button_p.click_callback.function = boost::bind(&LLMediaCtrl::onCloseNotification, this);
-
- close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p));
-
setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2));
return TRUE;
}
@@ -432,13 +386,15 @@ BOOL LLMediaCtrl::postBuild ()
//
BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
{
- if (LLPanel::handleKeyHere(key, mask)) return TRUE;
BOOL result = FALSE;
if (mMediaSource)
{
result = mMediaSource->handleKeyHere(key, mask);
}
+
+ if ( ! result )
+ result = LLPanel::handleKeyHere(key, mask);
return result;
}
@@ -458,7 +414,6 @@ void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility )
//
BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
{
- if (LLPanel::handleUnicodeCharHere(uni_char)) return TRUE;
BOOL result = FALSE;
if (mMediaSource)
@@ -466,6 +421,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
result = mMediaSource->handleUnicodeCharHere(uni_char);
}
+ if ( ! result )
+ result = LLPanel::handleUnicodeCharHere(uni_char);
+
return result;
}
@@ -921,11 +879,6 @@ void LLMediaCtrl::draw()
if ( mBorder && mBorder->getVisible() )
mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
- if (mCurNotification && !mCurNotification->isActive())
- {
- hideNotification();
- }
-
LLPanel::draw();
// Restore the previous values
@@ -1033,7 +986,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
LLNotification::Params notify_params;
notify_params.name = "PopupAttempt";
- notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", getKey());
+ notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
if (mTrusted)
@@ -1088,6 +1041,31 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
}
break;
+
+ case MEDIA_EVENT_AUTH_REQUEST:
+ {
+ LLNotification::Params auth_request_params;
+ auth_request_params.name = "AuthRequest";
+
+ // pass in host name and realm for site (may be zero length but will always exist)
+ LLSD args;
+ LLURL raw_url( self->getAuthURL().c_str() );
+ args["HOST_NAME"] = raw_url.getAuthority();
+ args["REALM"] = self->getAuthRealm();
+ auth_request_params.substitutions = args;
+
+ auth_request_params.payload = LLSD().with("media_id", mMediaTextureID);
+ auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
+ LLNotifications::instance().add(auth_request_params);
+ };
+ break;
+
+ case MEDIA_EVENT_LINK_HOVERED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
+ mHoverTextChanged = true;
+ };
+ break;
};
// chain all events to any potential observers of this object.
@@ -1105,109 +1083,85 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response)
{
if (response["open"])
{
- LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
+ // name of default floater to open
+ std::string floater_name = "media_browser";
+
+ // look for parent floater name
+ if ( gFloaterView )
+ {
+ if ( gFloaterView->getParentFloater(this) )
+ {
+ floater_name = gFloaterView->getParentFloater(this)->getInstanceName();
+ }
+ else
+ {
+ lldebugs << "No gFloaterView->getParentFloater(this) for onPopuup()" << llendl;
+ };
+ }
+ else
+ {
+ lldebugs << "No gFloaterView for onPopuup()" << llendl;
+ };
+
+ // (for now) open web content floater if that's our parent, otherwise, open the current media floater
+ // (this will change soon)
+ if ( floater_name == "web_content" )
+ {
+ LLWeb::loadWebURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
+ }
+ else
+ {
+ LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
+ }
}
else
{
// Make sure the opening instance knows its window open request was denied, so it can clean things up.
LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]);
}
-
}
-void LLMediaCtrl::onCloseNotification()
-{
- LLNotifications::instance().cancel(mCurNotification);
-}
-
-void LLMediaCtrl::onClickIgnore(LLUICtrl* ctrl)
+void LLMediaCtrl::showNotification(LLNotificationPtr notify)
{
- bool check = ctrl->getValue().asBoolean();
- if (mCurNotification && mCurNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ delete mWindowShade;
+
+ LLWindowShade::Params params;
+ params.name = "notification_shade";
+ params.rect = getLocalRect();
+ params.follows.flags = FOLLOWS_ALL;
+ params.notification = notify;
+ params.modal = true;
+ //HACK: don't hardcode this
+ if (notify->getIcon() == "Popup_Caution")
{
- // question was "show again" so invert value to get "ignore"
- check = !check;
+ params.bg_image.name = "Yellow_Gradient";
+ params.text_color = LLColor4::black;
}
- mCurNotification->setIgnored(check);
-}
-
-void LLMediaCtrl::onClickNotificationButton(const std::string& name)
-{
- if (!mCurNotification) return;
-
- LLSD response = mCurNotification->getResponseTemplate();
- response[name] = true;
-
- mCurNotification->respond(response);
-}
-
-void LLMediaCtrl::showNotification(LLNotificationPtr notify)
-{
- mCurNotification = notify;
-
- // add popup here
- LLSD payload = notify->getPayload();
-
- LLNotificationFormPtr formp = notify->getForm();
- LLLayoutPanel& panel = getChildRef<LLLayoutPanel>("notification_area");
- panel.setVisible(true);
- panel.getChild<LLUICtrl>("notification_icon")->setValue(notify->getIcon());
- panel.getChild<LLUICtrl>("notification_text")->setValue(notify->getMessage());
- panel.getChild<LLUICtrl>("notification_text")->setToolTip(notify->getMessage());
- LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType();
- LLLayoutPanel& form_elements = panel.getChildRef<LLLayoutPanel>("form_elements");
- form_elements.deleteAllChildren();
-
- const S32 FORM_PADDING_HORIZONTAL = 10;
- const S32 FORM_PADDING_VERTICAL = 3;
- S32 cur_x = FORM_PADDING_HORIZONTAL;
-
- if (ignore_type != LLNotificationForm::IGNORE_NO)
+ else
+ //HACK: another one since XUI doesn't support what we need right now
+ if (notify->getName() == "AuthRequest")
{
- LLCheckBoxCtrl::Params checkbox_p;
- checkbox_p.name = "ignore_check";
- checkbox_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL);
- checkbox_p.label = formp->getIgnoreMessage();
- checkbox_p.label_text.text_color = LLColor4::black;
- checkbox_p.commit_callback.function = boost::bind(&LLMediaCtrl::onClickIgnore, this, _1);
- checkbox_p.initial_value = formp->getIgnored();
-
- LLCheckBoxCtrl* check = LLUICtrlFactory::create<LLCheckBoxCtrl>(checkbox_p);
- check->setRect(check->getBoundingRect());
- form_elements.addChild(check);
- cur_x = check->getRect().mRight + FORM_PADDING_HORIZONTAL;
+ params.bg_image.name = "Yellow_Gradient";
+ params.text_color = LLColor4::black;
+ params.can_close = false;
}
-
- for (S32 i = 0; i < formp->getNumElements(); i++)
+ else
{
- LLSD form_element = formp->getElement(i);
- if (form_element["type"].asString() == "button")
- {
- LLButton::Params button_p;
- button_p.name = form_element["name"];
- button_p.label = form_element["text"];
- button_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL);
- button_p.click_callback.function = boost::bind(&LLMediaCtrl::onClickNotificationButton, this, form_element["name"].asString());
- button_p.auto_resize = true;
-
- LLButton* button = LLUICtrlFactory::create<LLButton>(button_p);
- button->autoResize();
- form_elements.addChild(button);
-
- cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL;
- }
+ //HACK: make this a property of the notification itself, "cancellable"
+ params.can_close = false;
+ params.text_color.control = "LabelTextColor";
}
+ mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
- form_elements.reshape(cur_x, form_elements.getRect().getHeight());
-
- //LLWeb::loadURL(payload["url"], payload["target"]);
+ addChild(mWindowShade);
+ mWindowShade->show();
}
void LLMediaCtrl::hideNotification()
{
- LLLayoutPanel& panel = getChildRef<LLLayoutPanel>("notification_area");
- panel.setVisible(FALSE);
-
- mCurNotification.reset();
+ if (mWindowShade)
+ {
+ mWindowShade->hide();
+ }
}
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 65dfbbff78..38a74f90d3 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -53,7 +53,8 @@ public:
ignore_ui_scale,
hide_loading,
decouple_texture_size,
- trusted_content;
+ trusted_content,
+ focus_on_click;
Optional<S32> texture_width,
texture_height;
@@ -89,6 +90,7 @@ public:
virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+ virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
// navigation
void navigateTo( std::string url_in, std::string mime_type = "");
@@ -167,9 +169,6 @@ public:
private:
void onVisibilityChange ( const LLSD& new_visibility );
void onPopup(const LLSD& notification, const LLSD& response);
- void onCloseNotification();
- void onClickNotificationButton(const std::string& name);
- void onClickIgnore(LLUICtrl* ctrl);
const S32 mTextureDepthBytes;
LLUUID mMediaTextureID;
@@ -193,7 +192,8 @@ public:
S32 mTextureWidth;
S32 mTextureHeight;
bool mClearCache;
- boost::shared_ptr<class LLNotification> mCurNotification;
+ class LLWindowShade* mWindowShade;
+ bool mHoverTextChanged;
};
#endif // LL_LLMediaCtrl_H
diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp
index 9a244e2562..7e9c3c84a7 100644
--- a/indra/newview/llmemoryview.cpp
+++ b/indra/newview/llmemoryview.cpp
@@ -37,9 +37,11 @@
#include <sstream>
#include <boost/algorithm/string/split.hpp>
+#include "llmemory.h"
LLMemoryView::LLMemoryView(const LLMemoryView::Params& p)
: LLView(p),
+ mPaused(FALSE),
//mDelay(120),
mAlloc(NULL)
{
@@ -59,6 +61,7 @@ BOOL LLMemoryView::handleMouseDown(S32 x, S32 y, MASK mask)
}
else
{
+ mPaused = !mPaused;
}
return TRUE;
}
@@ -148,13 +151,14 @@ void LLMemoryView::draw()
// cut off lines on bottom
U32 max_lines = U32((height - 2 * line_height) / line_height);
- std::vector<LLWString>::const_iterator end = mLines.end();
+ y_pos = height - MARGIN_AMT - line_height;
+ y_off = 0.f;
+
+#if !MEM_TRACK_MEM
+ std::vector<LLWString>::const_iterator end = mLines.end();
if(mLines.size() > max_lines) {
end = mLines.begin() + max_lines;
}
-
- y_pos = height - MARGIN_AMT - line_height;
- y_off = 0.f;
for (std::vector<LLWString>::const_iterator i = mLines.begin(); i != end; ++i)
{
font->render(*i, 0, MARGIN_AMT, y_pos - y_off,
@@ -169,6 +173,47 @@ void LLMemoryView::draw()
y_off += line_height;
}
+#else
+ LLMemTracker::getInstance()->preDraw(mPaused) ;
+
+ {
+ F32 x_pos = MARGIN_AMT ;
+ U32 lines = 0 ;
+ const char* str = LLMemTracker::getInstance()->getNextLine() ;
+ while(str != NULL)
+ {
+ lines++ ;
+ font->renderUTF8(str, 0, x_pos, y_pos - y_off,
+ LLColor4::white,
+ LLFontGL::LEFT,
+ LLFontGL::BASELINE,
+ LLFontGL::NORMAL,
+ LLFontGL::DROP_SHADOW,
+ S32_MAX,
+ target_width,
+ NULL, FALSE);
+
+ str = LLMemTracker::getInstance()->getNextLine() ;
+ y_off += line_height;
+
+ if(lines >= max_lines)
+ {
+ lines = 0 ;
+ x_pos += 512.f ;
+ if(x_pos + 512.f > target_width)
+ {
+ break ;
+ }
+
+ y_pos = height - MARGIN_AMT - line_height;
+ y_off = 0.f;
+ }
+ }
+ }
+
+ LLMemTracker::getInstance()->postDraw() ;
+#endif
+
#if MEM_TRACK_TYPE
S32 left, top, right, bottom;
diff --git a/indra/newview/llmemoryview.h b/indra/newview/llmemoryview.h
index 24ea058279..9bdc59ab10 100644
--- a/indra/newview/llmemoryview.h
+++ b/indra/newview/llmemoryview.h
@@ -55,6 +55,7 @@ public:
private:
std::vector<LLWString> mLines;
LLAllocator* mAlloc;
+ BOOL mPaused ;
};
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..142ee40cc8 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();
@@ -448,17 +449,20 @@ void LLFloaterMove::updatePosition()
LLBottomTray* tray = LLBottomTray::getInstance();
if (!tray) return;
- LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
+ LLButton* movement_btn = tray->findChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
- //align centers of a button and a floater
- S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
-
- S32 y = 0;
- if (!mModeActionsPanel->getVisible())
+ if (movement_btn)
{
- y = mModeActionsPanel->getRect().getHeight();
+ //align centers of a button and a floater
+ S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+
+ S32 y = 0;
+ if (!mModeActionsPanel->getVisible())
+ {
+ y = mModeActionsPanel->getRect().getHeight();
+ }
+ setOrigin(x, y);
}
- setOrigin(x, y);
}
//static
@@ -552,7 +556,7 @@ LLPanelStandStopFlying::LLPanelStandStopFlying() :
}
// static
-inline LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
+LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
{
static LLPanelStandStopFlying* panel = getStandStopFlyingPanel();
return panel;
@@ -735,10 +739,18 @@ void LLPanelStandStopFlying::updatePosition()
LLBottomTray* tray = LLBottomTray::getInstance();
if (!tray || mAttached) return;
- LLButton* movement_btn = tray->getChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
+ LLButton* movement_btn = tray->findChild<LLButton>(BOTTOM_TRAY_BUTTON_NAME);
- // Align centers of the button and the panel.
- S32 x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+ S32 x = 0;
+ if (movement_btn)
+ {
+ // Align centers of the button and the panel.
+ x = movement_btn->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+ }
+ else
+ {
+ x = tray->calcScreenRect().getCenterX() - getRect().getWidth()/2;
+ }
setOrigin(x, 0);
}
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index af8fdb17cf..a7059eb519 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -373,17 +373,19 @@ BOOL LLMuteList::remove(const LLMute& mute, U32 flags)
// Must be after erase.
setLoaded(); // why is this here? -MG
}
-
- // Clean up any legacy mutes
- string_set_t::iterator legacy_it = mLegacyMutes.find(mute.mName);
- if (legacy_it != mLegacyMutes.end())
+ else
{
- // Database representation of legacy mute is UUID null.
- LLMute mute(LLUUID::null, *legacy_it, LLMute::BY_NAME);
- updateRemove(mute);
- mLegacyMutes.erase(legacy_it);
- // Must be after erase.
- setLoaded(); // why is this here? -MG
+ // Clean up any legacy mutes
+ string_set_t::iterator legacy_it = mLegacyMutes.find(mute.mName);
+ if (legacy_it != mLegacyMutes.end())
+ {
+ // Database representation of legacy mute is UUID null.
+ LLMute mute(LLUUID::null, *legacy_it, LLMute::BY_NAME);
+ updateRemove(mute);
+ mLegacyMutes.erase(legacy_it);
+ // Must be after erase.
+ setLoaded(); // why is this here? -MG
+ }
}
return found;
@@ -607,7 +609,8 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) c
}
// empty names can't be legacy-muted
- if (name.empty()) return FALSE;
+ bool avatar = mute_object && mute_object->isAvatar();
+ if (name.empty() || avatar) return FALSE;
// Look in legacy pile
string_set_t::const_iterator legacy_it = mLegacyMutes.find(name);
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 38100aa6c5..afceb58ccf 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -143,6 +143,30 @@ void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index )
S32 cur_index = getHighlightedItemInx();
if (cur_index != target_index)
{
+ bool is_mouse_over_name_cell = false;
+
+ S32 mouse_x, mouse_y;
+ LLUI::getMousePositionLocal(this, &mouse_x, &mouse_y);
+
+ S32 column_index = getColumnIndexFromOffset(mouse_x);
+ LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y);
+ if (hit_item && column_index == mNameColumnIndex)
+ {
+ // Get the name cell which is currently under the mouse pointer.
+ LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
+ if (hit_cell)
+ {
+ is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y);
+ }
+ }
+
+ // If the tool tip is visible and the mouse is over the currently highlighted item's name cell,
+ // we should not reset the highlighted item index i.e. set mHighlightedItem = -1
+ // and should not increase the width of the text inside the cell because it may
+ // overlap the tool tip icon.
+ if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell)
+ return;
+
if(0 <= cur_index && cur_index < (S32)getItemList().size())
{
LLScrollListItem* item = getItemList()[cur_index];
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index 58849393b4..3b160ddc8e 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -276,9 +276,6 @@ LLNavigationBar::LLNavigationBar()
// set a listener function for LoginComplete event
LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLNavigationBar::handleLoginComplete, this));
-
- // Necessary for focus movement among child controls
- setFocusRoot(TRUE);
}
LLNavigationBar::~LLNavigationBar()
@@ -639,18 +636,19 @@ void LLNavigationBar::onRegionNameResponse(
U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)
{
// Invalid location?
- if (!region_handle)
+ if (region_handle)
+ {
+ // Teleport to the location.
+ LLVector3d region_pos = from_region_handle(region_handle);
+ LLVector3d global_pos = region_pos + (LLVector3d) local_coords;
+
+ llinfos << "Teleporting to: " << LLSLURL(region_name, global_pos).getSLURLString() << llendl;
+ gAgent.teleportViaLocation(global_pos);
+ }
+ else if (gSavedSettings.getBOOL("SearchFromAddressBar"))
{
invokeSearch(typed_location);
- return;
}
-
- // Teleport to the location.
- LLVector3d region_pos = from_region_handle(region_handle);
- LLVector3d global_pos = region_pos + (LLVector3d) local_coords;
-
- llinfos << "Teleporting to: " << LLSLURL(region_name, global_pos).getSLURLString() << llendl;
- gAgent.teleportViaLocation(global_pos);
}
void LLNavigationBar::showTeleportHistoryMenu(LLUICtrl* btn_ctrl)
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/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 932ad75f29..162e465fef 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -94,15 +94,19 @@ public:
LLGestureComboList::Params::Params()
: combo_button("combo_button"),
- combo_list("combo_list")
+ combo_list("combo_list"),
+ get_more("get_more", true),
+ view_all("view_all", true)
{
}
LLGestureComboList::LLGestureComboList(const LLGestureComboList::Params& p)
-: LLUICtrl(p)
- , mLabel(p.label)
- , mViewAllItemIndex(0)
- , mGetMoreItemIndex(0)
+: LLUICtrl(p),
+ mLabel(p.label),
+ mViewAllItemIndex(-1),
+ mGetMoreItemIndex(-1),
+ mShowViewAll(p.view_all),
+ mShowGetMore(p.get_more)
{
LLBottomtrayButton::Params button_params = p.combo_button;
button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT);
@@ -153,6 +157,16 @@ BOOL LLGestureComboList::handleKeyHere(KEY key, MASK mask)
return handled;
}
+void LLGestureComboList::draw()
+{
+ LLUICtrl::draw();
+
+ if(mButton->getToggleState())
+ {
+ showList();
+ }
+}
+
void LLGestureComboList::showList()
{
LLRect rect = mList->getRect();
@@ -176,6 +190,7 @@ void LLGestureComboList::showList()
// Show the list and push the button down
mButton->setToggleState(TRUE);
mList->setVisible(TRUE);
+ sendChildToFront(mList);
LLUI::addPopup(mList);
}
@@ -286,12 +301,16 @@ void LLGestureComboList::refreshGestures()
sortByName();
// store indices for Get More and View All items (idx is the index followed by the last added Gesture)
- mGetMoreItemIndex = idx;
- mViewAllItemIndex = idx + 1;
-
- // add Get More and View All items at the bottom
- mList->addSimpleElement(LLTrans::getString("GetMoreGestures"), ADD_BOTTOM, LLSD(mGetMoreItemIndex));
- mList->addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex));
+ if (mShowGetMore)
+ {
+ mGetMoreItemIndex = idx;
+ mList->addSimpleElement(LLTrans::getString("GetMoreGestures"), ADD_BOTTOM, LLSD(mGetMoreItemIndex));
+ }
+ if (mShowViewAll)
+ {
+ mViewAllItemIndex = idx + 1;
+ mList->addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex));
+ }
// Insert label after sorting, at top, with separator below it
mList->addSeparator(ADD_TOP);
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index cc905736fd..96ab45071b 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -46,6 +46,8 @@ public:
{
Optional<LLBottomtrayButton::Params> combo_button;
Optional<LLScrollListCtrl::Params> combo_list;
+ Optional<bool> get_more,
+ view_all;
Params();
};
@@ -56,6 +58,8 @@ protected:
LLGestureComboList(const Params&);
std::vector<LLMultiGesture*> mGestures;
std::string mLabel;
+ bool mShowViewAll;
+ bool mShowGetMore;
LLSD::Integer mViewAllItemIndex;
LLSD::Integer mGetMoreItemIndex;
@@ -68,6 +72,8 @@ public:
virtual void hideList();
virtual BOOL handleKeyHere(KEY key, MASK mask);
+ virtual void draw();
+
S32 getCurrentIndex() const;
void onItemSelected(const LLSD& data);
void sortByName(bool ascending = true);
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 47d32e57fb..b56fb65a4c 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);
@@ -111,11 +123,24 @@ protected:
toast->setVisible(FALSE);
toast->stopTimer();
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();
@@ -205,6 +230,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 +296,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
{
panel->addMessage(notification);
toast->reshapeToPanel();
- toast->resetTimer();
+ toast->startTimer();
arrangeToasts();
return;
@@ -295,7 +341,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
panel->init(notification);
toast->reshapeToPanel();
- toast->resetTimer();
+ toast->startTimer();
m_active_toasts.push_back(toast->getHandle());
@@ -325,9 +371,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()
@@ -336,7 +382,10 @@ void LLNearbyChatScreenChannel::showToastsBottom()
return;
LLRect toast_rect;
- S32 bottom = getRect().mBottom;
+ updateBottom();
+ S32 channel_bottom = getRect().mBottom;
+
+ S32 bottom = channel_bottom;
S32 margin = gSavedSettings.getS32("ToastGap");
//sort active toasts
@@ -468,9 +517,22 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
}
nearby_chat->addMessage(chat_msg, true, args);
+
+ if(chat_msg.mSourceType == CHAT_SOURCE_AGENT
+ && chat_msg.mFromID.notNull()
+ && chat_msg.mFromID != gAgentID)
+ {
+ LLFirstUse::otherAvatarChatFirst();
+
+ // Add sender to the recent people list.
+ LLRecentPeople::instance().add(chat_msg.mFromID);
+
+ }
+
if( nearby_chat->getVisible()
|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
- && gSavedSettings.getBOOL("UseChatBubbles") ) )
+ && gSavedSettings.getBOOL("UseChatBubbles") )
+ || !mChannel->getShowToasts() ) // to prevent toasts in Busy mode
return;//no need in toast if chat is visible or if bubble chat is enabled
// Handle irc styled messages for toast panel
@@ -500,6 +562,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
}
*/
+ // Add a nearby chat toast.
LLUUID id;
id.generate();
@@ -525,15 +588,13 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
notification["text_color"] = r_color_name;
notification["color_alpha"] = r_color_alpha;
notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
+
+ // Pass sender info so that it can be rendered properly (STORM-1021).
+ notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);
+
channel->addNotification(notification);
}
-
- if(chat_msg.mSourceType == CHAT_SOURCE_AGENT
- && chat_msg.mFromID.notNull()
- && chat_msg.mFromID != gAgentID)
- {
- LLFirstUse::otherAvatarChatFirst();
- }
+
}
void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index f084002385..981b4dbee3 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -47,6 +47,7 @@
#include "llagentcamera.h"
#include "llappviewer.h" // for gDisconnected
#include "llcallingcard.h" // LLAvatarTracker
+#include "llfloaterworldmap.h"
#include "lltracker.h"
#include "llsurface.h"
#include "llviewercamera.h"
@@ -91,13 +92,27 @@ LLNetMap::LLNetMap (const Params & p)
mObjectImagep(),
mClosestAgentToCursor(),
mClosestAgentAtLastRightClick(),
- mToolTipMsg()
+ mToolTipMsg(),
+ mPopupMenu(NULL)
{
mDotRadius = llmax(DOT_SCALE * mPixelsPerMeter, MIN_DOT_RADIUS);
+ setScale(gSavedSettings.getF32("MiniMapScale"));
}
LLNetMap::~LLNetMap()
{
+ gSavedSettings.setF32("MiniMapScale", mScale);
+}
+
+BOOL LLNetMap::postBuild()
+{
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("Minimap.Zoom", boost::bind(&LLNetMap::handleZoom, this, _2));
+ registrar.add("Minimap.Tracker", boost::bind(&LLNetMap::handleStopTracking, this, _2));
+
+ mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ return TRUE;
}
void LLNetMap::setScale( F32 scale )
@@ -352,16 +367,49 @@ void LLNetMap::draw()
pos_map = globalPosToView(pos_global);
+ LLUUID uuid(NULL);
BOOL show_as_friend = FALSE;
if( i < regionp->mMapAvatarIDs.count())
{
- show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(regionp->mMapAvatarIDs.get(i)) != NULL);
+ uuid = regionp->mMapAvatarIDs.get(i);
+ show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL);
}
+
+ LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color;
LLWorldMapView::drawAvatar(
pos_map.mV[VX], pos_map.mV[VY],
- show_as_friend ? map_avatar_friend_color : map_avatar_color,
+ color,
pos_map.mV[VZ], mDotRadius);
+ if(uuid.notNull())
+ {
+ bool selected = false;
+ uuid_vec_t::iterator sel_iter = gmSelected.begin();
+ for (; sel_iter != gmSelected.end(); sel_iter++)
+ {
+ if(*sel_iter == uuid)
+ {
+ selected = true;
+ break;
+ }
+ }
+ if(selected)
+ {
+ if( (pos_map.mV[VX] < 0) ||
+ (pos_map.mV[VY] < 0) ||
+ (pos_map.mV[VX] >= getRect().getWidth()) ||
+ (pos_map.mV[VY] >= getRect().getHeight()) )
+ {
+ S32 x = llround( pos_map.mV[VX] );
+ S32 y = llround( pos_map.mV[VY] );
+ LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10);
+ } else
+ {
+ LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f);
+ }
+ }
+ }
+
F32 dist_to_cursor = dist_vec(LLVector2(pos_map.mV[VX], pos_map.mV[VY]),
LLVector2(local_mouse_x,local_mouse_y));
if(dist_to_cursor < min_pick_dist && dist_to_cursor < closest_dist)
@@ -598,7 +646,6 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, MASK mask )
args["[REGION]"] = region_name;
std::string msg = mToolTipMsg;
LLStringUtil::format(msg, args);
-
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(msg)
.sticky_rect(sticky_rect));
@@ -791,6 +838,9 @@ BOOL LLNetMap::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL LLNetMap::handleMouseUp( S32 x, S32 y, MASK mask )
{
+ if(abs(mMouseDown.mX-x)<3 && abs(mMouseDown.mY-y)<3)
+ handleClick(x,y,mask);
+
if (hasMouseCapture())
{
if (mPanning)
@@ -819,6 +869,60 @@ BOOL LLNetMap::handleMouseUp( S32 x, S32 y, MASK mask )
return FALSE;
}
+BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if (mPopupMenu)
+ {
+ mPopupMenu->buildDrawLabels();
+ mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+ mPopupMenu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0));
+ LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ }
+ return TRUE;
+}
+
+BOOL LLNetMap::handleClick(S32 x, S32 y, MASK mask)
+{
+ // TODO: allow clicking an avatar on minimap to select avatar in the nearby avatar list
+ // if(mClosestAgentToCursor.notNull())
+ // mNearbyList->selectUser(mClosestAgentToCursor);
+ // Needs a registered observer i guess to accomplish this without using
+ // globals to tell the mNearbyList in llpeoplepanel to select the user
+ return TRUE;
+}
+
+BOOL LLNetMap::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ LLVector3d pos_global = viewPosToGlobal(x, y);
+
+ bool double_click_teleport = gSavedSettings.getBOOL("DoubleClickTeleport");
+ bool double_click_show_world_map = gSavedSettings.getBOOL("DoubleClickShowWorldMap");
+
+ if (double_click_teleport || double_click_show_world_map)
+ {
+ // 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 (double_click_teleport)
+ {
+ // If DoubleClickTeleport is on, double clicking the minimap will teleport there
+ gAgent.teleportViaLocationLookAt(pos_global);
+ }
+ else if (double_click_show_world_map)
+ {
+ LLFloaterReg::showInstance("world_map");
+ }
+ return TRUE;
+}
+
// static
bool LLNetMap::outsideSlop( S32 x, S32 y, S32 start_x, S32 start_y, S32 slop )
{
@@ -869,3 +973,38 @@ BOOL LLNetMap::handleHover( S32 x, S32 y, MASK mask )
return TRUE;
}
+
+void LLNetMap::handleZoom(const LLSD& userdata)
+{
+ std::string level = userdata.asString();
+
+ F32 scale = 0.0f;
+ if (level == std::string("default"))
+ {
+ LLControlVariable *pvar = gSavedSettings.getControl("MiniMapScale");
+ if(pvar)
+ {
+ pvar->resetToDefault();
+ scale = gSavedSettings.getF32("MiniMapScale");
+ }
+ }
+ else if (level == std::string("close"))
+ scale = LLNetMap::MAP_SCALE_MAX;
+ else if (level == std::string("medium"))
+ scale = LLNetMap::MAP_SCALE_MID;
+ else if (level == std::string("far"))
+ scale = LLNetMap::MAP_SCALE_MIN;
+ if (scale != 0.0f)
+ {
+ setScale(scale);
+ }
+}
+
+void LLNetMap::handleStopTracking (const LLSD& userdata)
+{
+ if (mPopupMenu)
+ {
+ mPopupMenu->setItemEnabled ("Stop Tracking", false);
+ LLTracker::stopTracking ((void*)LLTracker::isTracking(NULL));
+ }
+}
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index 650bce0da4..20fcee0814 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -38,6 +38,8 @@ class LLColor4U;
class LLCoordGL;
class LLImageRaw;
class LLViewerTexture;
+class LLFloaterMap;
+class LLMenuGL;
class LLNetMap : public LLUICtrl
{
@@ -55,6 +57,7 @@ public:
protected:
LLNetMap (const Params & p);
friend class LLUICtrlFactory;
+ friend class LLFloaterMap;
public:
virtual ~LLNetMap();
@@ -70,7 +73,12 @@ public:
/*virtual*/ BOOL handleHover( S32 x, S32 y, MASK mask );
/*virtual*/ BOOL handleToolTip( S32 x, S32 y, MASK mask);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
-
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
+ /*virtual*/ BOOL handleClick(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
+
void setScale( F32 scale );
void setToolTipMsg(const std::string& msg) { mToolTipMsg = msg; }
void renderScaledPointGlobal( const LLVector3d& pos, const LLColor4U &color, F32 radius );
@@ -118,6 +126,16 @@ private:
LLUUID mClosestAgentAtLastRightClick;
std::string mToolTipMsg;
+
+public:
+ void setSelected(uuid_vec_t uuids) { gmSelected=uuids; };
+
+private:
+ void handleZoom(const LLSD& userdata);
+ void handleStopTracking (const LLSD& userdata);
+
+ LLMenuGL* mPopupMenu;
+ uuid_vec_t gmSelected;
};
diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp
index 45590c3cdb..bbb4d03768 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -88,7 +88,7 @@ bool LLScriptHandler::processNotification(const LLSD& notify)
initChannel();
}
- if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
+ if(notify["sigtype"].asString() == "add")
{
if (LLHandlerUtil::canLogToIM(notification))
{
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/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 57180f63b5..73c4722b82 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -34,6 +34,7 @@
#include "llcombobox.h"
#include "lldateutil.h" // ageFromDate()
#include "llimview.h"
+#include "llmenubutton.h"
#include "llnotificationsutil.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
@@ -340,10 +341,11 @@ LLPanelAvatarNotes::~LLPanelAvatarNotes()
if(getAvatarId().notNull())
{
LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
- }
+ }
+
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
@@ -475,11 +477,11 @@ LLPanelAvatarProfile::LLPanelAvatarProfile()
BOOL LLPanelAvatarProfile::postBuild()
{
+ childSetCommitCallback("see_profile_btn",(boost::bind(&LLPanelAvatarProfile::onSeeProfileBtnClick,this)),NULL);
childSetCommitCallback("add_friend",(boost::bind(&LLPanelAvatarProfile::onAddFriendButtonClick,this)),NULL);
childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL);
childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL);
childSetCommitCallback("teleport",(boost::bind(&LLPanelAvatarProfile::onTeleportButtonClick,this)),NULL);
- childSetCommitCallback("overflow_btn", boost::bind(&LLPanelAvatarProfile::onOverflowButtonClicked, this), NULL);
childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL);
childSetCommitCallback("show_on_map_btn", (boost::bind(
&LLPanelAvatarProfile::onMapButtonClick, this)), NULL);
@@ -500,7 +502,8 @@ BOOL LLPanelAvatarProfile::postBuild()
enable.add("Profile.EnableBlock", boost::bind(&LLPanelAvatarProfile::enableBlock, this));
enable.add("Profile.EnableUnblock", boost::bind(&LLPanelAvatarProfile::enableUnblock, this));
- mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ LLToggleableMenu* profile_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ getChild<LLMenuButton>("overflow_btn")->setMenu(profile_menu, LLMenuButton::MP_TOP_RIGHT);
LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this);
@@ -622,6 +625,40 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g
getChild<LLUICtrl>("sl_groups")->setValue(groups);
}
+static void got_full_name_callback( LLHandle<LLPanel> profile_panel_handle, const std::string& full_name )
+{
+ if (profile_panel_handle.isDead() ) return;
+
+ LLPanelAvatarProfile* profile_panel = dynamic_cast<LLPanelAvatarProfile*>(profile_panel_handle.get());
+ if ( ! profile_panel ) return;
+
+ LLStringUtil::format_map_t args;
+
+ std::string name;
+ if (LLAvatarNameCache::useDisplayNames())
+ {
+ name = LLCacheName::buildUsername(full_name);
+ }
+ else
+ {
+ name = full_name;
+ }
+
+ args["[NAME]"] = name;
+
+ std::string linden_name = profile_panel->getString("name_text_args", args);
+ profile_panel->getChild<LLUICtrl>("name_descr_text")->setValue(linden_name);
+}
+
+void LLPanelAvatarProfile::onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
+{
+ LLStringUtil::format_map_t args;
+ args["[DISPLAY_NAME]"] = av_name.mDisplayName;
+
+ std::string display_name = getString("display_name_text_args", args);
+ getChild<LLUICtrl>("display_name_descr_text")->setValue(display_name);
+}
+
void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
{
//remove avatar id from cache to get fresh info
@@ -633,6 +670,25 @@ void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
LLStringUtil::format(birth_date, LLSD().with("datetime", (S32) avatar_data->born_on.secondsSinceEpoch()));
args["[REG_DATE]"] = birth_date;
}
+
+ // ask (asynchronously) for the avatar name
+ LLHandle<LLPanel> profile_panel_handle = getHandle();
+ std::string full_name;
+ if (gCacheName->getFullName(avatar_data->agent_id, full_name))
+ {
+ // name in cache, call callback directly
+ got_full_name_callback( profile_panel_handle, full_name );
+ }
+ else
+ {
+ // not in cache, lookup name
+ gCacheName->get(avatar_data->agent_id, false, boost::bind( got_full_name_callback, profile_panel_handle, _2 ));
+ }
+
+ // get display name
+ LLAvatarNameCache::get(avatar_data->avatar_id,
+ boost::bind(&LLPanelAvatarProfile::onNameCache, this, _1, _2));
+
args["[AGE]"] = LLDateUtil::ageFromDate( avatar_data->born_on, LLDate::now());
std::string register_date = getString("RegisterDateFormat", args);
getChild<LLUICtrl>("register_date")->setValue(register_date );
@@ -732,6 +788,11 @@ void LLPanelAvatarProfile::onAddFriendButtonClick()
LLAvatarActions::requestFriendshipDialog(getAvatarId());
}
+void LLPanelAvatarProfile::onSeeProfileBtnClick()
+{
+ LLAvatarActions::showProfile(getAvatarId());
+}
+
void LLPanelAvatarProfile::onIMButtonClick()
{
LLAvatarActions::startIM(getAvatarId());
@@ -752,32 +813,16 @@ void LLPanelAvatarProfile::onShareButtonClick()
//*TODO not implemented
}
-void LLPanelAvatarProfile::onOverflowButtonClicked()
-{
- if (!mProfileMenu->toggleVisibility())
- return;
-
- LLView* btn = getChild<LLView>("overflow_btn");
-
- if (mProfileMenu->getButtonRect().isEmpty())
- {
- mProfileMenu->setButtonRect(btn);
- }
- mProfileMenu->updateParent(LLMenuGL::sMenuContainer);
-
- LLRect rect = btn->getRect();
- LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop);
-}
-
LLPanelAvatarProfile::~LLPanelAvatarProfile()
{
if(getAvatarId().notNull())
{
LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
- }
+ }
+
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index 11c7716322..e95441cd58 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -31,10 +31,10 @@
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
#include "llvoiceclient.h"
+#include "llavatarnamecache.h"
class LLComboBox;
class LLLineEditor;
-class LLToggleableMenu;
enum EOnlineStatus
{
@@ -201,20 +201,18 @@ protected:
bool enableUnblock();
bool enableGod();
-
+ void onSeeProfileBtnClick();
void onAddFriendButtonClick();
void onIMButtonClick();
void onCallButtonClick();
void onTeleportButtonClick();
void onShareButtonClick();
- void onOverflowButtonClicked();
private:
+ void onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
typedef std::map< std::string,LLUUID> group_map_t;
group_map_t mGroups;
-
- LLToggleableMenu* mProfileMenu;
};
/**
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 90ed8b9e58..4db9a154ea 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -94,7 +94,13 @@ enum ESubpart {
SUBPART_UNDERPANTS,
SUBPART_SKIRT,
SUBPART_ALPHA,
- SUBPART_TATTOO
+ SUBPART_TATTOO,
+ SUBPART_PHYSICS_BREASTS_UPDOWN,
+ SUBPART_PHYSICS_BREASTS_INOUT,
+ SUBPART_PHYSICS_BELLY_UPDOWN,
+ SUBPART_PHYSICS_BUTT_UPDOWN,
+ SUBPART_PHYSICS_BUTT_LEFTRIGHT,
+ SUBPART_PHYSICS_ADVANCED,
};
using namespace LLVOAvatarDefines;
@@ -218,7 +224,7 @@ LLEditWearableDictionary::Wearables::Wearables()
// note the subpart that is listed first is treated as "default", regardless of what order is in enum.
// Please match the order presented in XUI. -Nyx
// this will affect what camera angle is shown when first editing a wearable
- addEntry(LLWearableType::WT_SHAPE, new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9, SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS ));
+ addEntry(LLWearableType::WT_SHAPE, new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9, SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS));
addEntry(LLWearableType::WT_SKIN, new WearableEntry(LLWearableType::WT_SKIN,"edit_skin_title","skin_desc_text",0,3,4, TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL));
addEntry(LLWearableType::WT_HAIR, new WearableEntry(LLWearableType::WT_HAIR,"edit_hair_title","hair_desc_text",0,1,4, TEX_HAIR, SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL));
addEntry(LLWearableType::WT_EYES, new WearableEntry(LLWearableType::WT_EYES,"edit_eyes_title","eyes_desc_text",0,1,1, TEX_EYES_IRIS, SUBPART_EYES));
@@ -233,6 +239,7 @@ LLEditWearableDictionary::Wearables::Wearables()
addEntry(LLWearableType::WT_SKIRT, new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title","skirt_desc_text",1,1,1, TEX_SKIRT, TEX_SKIRT, SUBPART_SKIRT));
addEntry(LLWearableType::WT_ALPHA, new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title","alpha_desc_text",0,5,1, TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA, SUBPART_ALPHA));
addEntry(LLWearableType::WT_TATTOO, new WearableEntry(LLWearableType::WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1,3,1, TEX_HEAD_TATTOO, TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO, SUBPART_TATTOO));
+ addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(LLWearableType::WT_PHYSICS,"edit_physics_title","physics_desc_text",0,0,6, SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED));
}
LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType type,
@@ -303,6 +310,12 @@ LLEditWearableDictionary::Subparts::Subparts()
addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
+ addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "physics_breasts_updown_param_list", "physics_breasts_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE));
+ addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "physics_breasts_inout_param_list", "physics_breasts_inout_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE));
+ addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
+ addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
+ addEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, "mTorso", "physics_butt_leftright", "physics_butt_leftright_param_list", "physics_butt_leftright_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
+ addEntry(SUBPART_PHYSICS_ADVANCED, new SubpartEntry(SUBPART_PHYSICS_ADVANCED, "mTorso", "physics_advanced", "physics_advanced_param_list", "physics_advanced_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
}
LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
@@ -569,6 +582,7 @@ static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel,
if (color_swatch_ctrl)
{
color_swatch_ctrl->set(self->getWearable()->getClothesColor(entry->mTextureIndex));
+ color_swatch_ctrl->closeFloaterColorPicker();
}
}
@@ -739,6 +753,7 @@ BOOL LLPanelEditWearable::postBuild()
mPanelSkirt = getChild<LLPanel>("edit_skirt_panel");
mPanelAlpha = getChild<LLPanel>("edit_alpha_panel");
mPanelTattoo = getChild<LLPanel>("edit_tattoo_panel");
+ mPanelPhysics = getChild<LLPanel>("edit_physics_panel");
mTxtAvatarHeight = mPanelShape->getChild<LLTextBox>("avatar_height");
@@ -847,11 +862,11 @@ void LLPanelEditWearable::setVisible(BOOL visible)
LLPanel::setVisible(visible);
}
-void LLPanelEditWearable::setWearable(LLWearable *wearable)
+void LLPanelEditWearable::setWearable(LLWearable *wearable, BOOL disable_camera_switch)
{
- showWearable(mWearablePtr, FALSE);
+ showWearable(mWearablePtr, FALSE, disable_camera_switch);
mWearablePtr = wearable;
- showWearable(mWearablePtr, TRUE);
+ showWearable(mWearablePtr, TRUE, disable_camera_switch);
}
@@ -1051,7 +1066,7 @@ void LLPanelEditWearable::revertChanges()
gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE);
}
-void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
+void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch)
{
if (!wearable)
{
@@ -1146,7 +1161,10 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
updateScrollingPanelUI();
}
- showDefaultSubpart();
+ if (!disable_camera_switch)
+ {
+ showDefaultSubpart();
+ }
updateVerbs();
}
@@ -1154,7 +1172,7 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show)
void LLPanelEditWearable::showDefaultSubpart()
{
- changeCamera(0);
+ changeCamera(3);
}
void LLPanelEditWearable::onTabExpandedCollapsed(const LLSD& param, U8 index)
@@ -1355,6 +1373,11 @@ LLPanel* LLPanelEditWearable::getPanel(LLWearableType::EType type)
case LLWearableType::WT_TATTOO:
return mPanelTattoo;
break;
+
+ case LLWearableType::WT_PHYSICS:
+ return mPanelPhysics;
+ break;
+
default:
break;
}
@@ -1402,7 +1425,16 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value
{
LLPanel::Params p;
p.name("LLScrollingPanelParam");
- LLScrollingPanelParam* panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
+ LLWearable *wearable = this->getWearable();
+ LLScrollingPanelParamBase *panel_param = NULL;
+ if (wearable && wearable->getType() == LLWearableType::WT_PHYSICS) // Hack to show a different panel for physics. Should generalize this later.
+ {
+ panel_param = new LLScrollingPanelParamBase( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
+ }
+ else
+ {
+ panel_param = new LLScrollingPanelParam( p, NULL, (*it).second, TRUE, this->getWearable(), jointp);
+ }
height = panel_list->addPanel( panel_param );
}
}
diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h
index 43513d8ab3..692a7ce90f 100644
--- a/indra/newview/llpaneleditwearable.h
+++ b/indra/newview/llpaneleditwearable.h
@@ -55,8 +55,11 @@ public:
/*virtual*/ BOOL isDirty() const; // LLUICtrl
/*virtual*/ void draw();
+ // changes camera angle to default for selected subpart
+ void changeCamera(U8 subpart);
+
LLWearable* getWearable() { return mWearablePtr; }
- void setWearable(LLWearable *wearable);
+ void setWearable(LLWearable *wearable, BOOL disable_camera_switch = FALSE);
void saveChanges(bool force_save_as = false);
void revertChanges();
@@ -77,7 +80,7 @@ public:
private:
typedef std::map<F32, LLViewerVisualParam*> value_map_t;
- void showWearable(LLWearable* wearable, BOOL show);
+ void showWearable(LLWearable* wearable, BOOL show, BOOL disable_camera_switch = FALSE);
void updateScrollingPanelUI();
LLPanel* getPanel(LLWearableType::EType type);
void getSortedParams(value_map_t &sorted_params, const std::string &edit_group);
@@ -91,9 +94,6 @@ private:
void toggleTypeSpecificControls(LLWearableType::EType type);
void updateTypeSpecificControls(LLWearableType::EType type);
- // changes camera angle to default for selected subpart
- void changeCamera(U8 subpart);
-
//alpha mask checkboxes
void configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name);
void onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLVOAvatarDefines::ETextureIndex te);
@@ -163,6 +163,7 @@ private:
LLPanel *mPanelSkirt;
LLPanel *mPanelAlpha;
LLPanel *mPanelTattoo;
+ LLPanel *mPanelPhysics;
typedef std::map<std::string, LLVOAvatarDefines::ETextureIndex> string_texture_index_map_t;
string_texture_index_map_t mAlphaCheckbox2Index;
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..3dbc637318 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));
}
}
@@ -1786,7 +1843,8 @@ bool LLPanelGroupRolesSubTab::apply(std::string& mesg)
{
lldebugs << "LLPanelGroupRolesSubTab::apply()" << llendl;
- saveRoleChanges();
+ saveRoleChanges(true);
+
LLGroupMgr::getInstance()->sendGroupRoleChanges(mGroupID);
notifyObservers();
@@ -1965,7 +2023,7 @@ void LLPanelGroupRolesSubTab::handleRoleSelect()
return;
}
- saveRoleChanges();
+ saveRoleChanges(false);
// Check if there is anything selected.
LLScrollListItem* item = mRolesList->getFirstSelected();
@@ -2328,7 +2386,7 @@ void LLPanelGroupRolesSubTab::handleDeleteRole()
notifyObservers();
}
-void LLPanelGroupRolesSubTab::saveRoleChanges()
+void LLPanelGroupRolesSubTab::saveRoleChanges(bool select_saved_role)
{
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
@@ -2343,13 +2401,23 @@ void LLPanelGroupRolesSubTab::saveRoleChanges()
rd.mRoleDescription = mRoleDescription->getText();
rd.mRoleTitle = mRoleTitle->getText();
+ S32 role_members_count = 0;
+ if (mSelectedRole.isNull())
+ {
+ role_members_count = gdatap->mMemberCount;
+ }
+ else if(LLGroupRoleData* grd = get_ptr_in_map(gdatap->mRoles, mSelectedRole))
+ {
+ role_members_count = grd->getTotalMembersInRole();
+ }
+
gdatap->setRoleData(mSelectedRole,rd);
mRolesList->deleteSingleItem(mRolesList->getItemIndex(mSelectedRole));
- LLSD row = createRoleItem(mSelectedRole,rd.mRoleName,rd.mRoleTitle,0);
+ LLSD row = createRoleItem(mSelectedRole,rd.mRoleName,rd.mRoleTitle,role_members_count);
LLScrollListItem* item = mRolesList->addElement(row, ADD_BOTTOM, this);
- item->setSelected(TRUE);
+ item->setSelected(select_saved_role);
mHasRoleChange = FALSE;
}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 6a773f1ebb..a55e264150 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;
@@ -251,7 +257,7 @@ public:
static void onDeleteRole(void*);
void handleDeleteRole();
- void saveRoleChanges();
+ void saveRoleChanges(bool select_saved_role);
virtual void setGroupID(const LLUUID& id);
protected:
diff --git a/indra/newview/llpanellandaudio.cpp b/indra/newview/llpanellandaudio.cpp
index 5a943bc61d..f9730d9b71 100644
--- a/indra/newview/llpanellandaudio.cpp
+++ b/indra/newview/llpanellandaudio.cpp
@@ -91,9 +91,6 @@ BOOL LLPanelLandAudio::postBuild()
mMusicURLEdit = getChild<LLLineEditor>("music_url");
childSetCommitCallback("music_url", onCommitAny, this);
- mMusicUrlCheck = getChild<LLCheckBoxCtrl>("hide_music_url");
- childSetCommitCallback("hide_music_url", onCommitAny, this);
-
return TRUE;
}
@@ -117,9 +114,6 @@ void LLPanelLandAudio::refresh()
mCheckSoundLocal->set( parcel->getSoundLocal() );
mCheckSoundLocal->setEnabled( can_change_media );
- mMusicUrlCheck->set( parcel->getObscureMusic() );
- mMusicUrlCheck->setEnabled( can_change_media );
-
bool allow_voice = parcel->getParcelFlagAllowVoice();
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
@@ -148,13 +142,6 @@ void LLPanelLandAudio::refresh()
mCheckParcelEnableVoice->set(allow_voice);
mCheckParcelVoiceLocal->set(!parcel->getParcelFlagUseEstateVoiceChannel());
- // don't display urls if you're not able to change it
- // much requested change in forums so people can't 'steal' urls
- // NOTE: bug#2009 means this is still vunerable - however, bug
- // should be closed since this bug opens up major security issues elsewhere.
- bool obscure_music = ! can_change_media && parcel->getObscureMusic();
-
- mMusicURLEdit->setDrawAsterixes(obscure_music);
mMusicURLEdit->setText(parcel->getMusicURL());
mMusicURLEdit->setEnabled( can_change_media );
}
@@ -173,7 +160,6 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata)
// Extract data from UI
BOOL sound_local = self->mCheckSoundLocal->get();
std::string music_url = self->mMusicURLEdit->getText();
- U8 obscure_music = self->mMusicUrlCheck->get();
BOOL voice_enabled = self->mCheckParcelEnableVoice->get();
BOOL voice_estate_chan = !self->mCheckParcelVoiceLocal->get();
@@ -186,7 +172,6 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata)
parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan);
parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local);
parcel->setMusicURL(music_url);
- parcel->setObscureMusic(obscure_music);
// Send current parcel data upstream to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
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..80f6862169 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"
@@ -69,6 +71,7 @@ static void collapse_all_folders(LLFolderView* root_folder);
static void expand_all_folders(LLFolderView* root_folder);
static bool has_expanded_folders(LLFolderView* root_folder);
static bool has_collapsed_folders(LLFolderView* root_folder);
+static void toggle_restore_menu(LLMenuGL* menu, BOOL visible, BOOL enabled);
/**
* Functor counting expanded and collapsed folders in folder view tree to know
@@ -191,6 +194,7 @@ LLLandmarksPanel::LLLandmarksPanel()
, mLibraryInventoryPanel(NULL)
, mCurrentSelectedList(NULL)
, mListCommands(NULL)
+ , mGearButton(NULL)
, mGearFolderMenu(NULL)
, mGearLandmarkMenu(NULL)
{
@@ -517,9 +521,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 +686,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,10 +705,13 @@ 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());
+ mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
+ mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
+
mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME));
}
@@ -722,7 +728,7 @@ void LLLandmarksPanel::updateListCommands()
void LLLandmarksPanel::onActionsButtonClick()
{
- LLMenuGL* menu = mGearFolderMenu;
+ LLToggleableMenu* menu = mGearFolderMenu;
LLFolderViewItem* cur_item = NULL;
if(mCurrentSelectedList)
@@ -741,7 +747,7 @@ void LLLandmarksPanel::onActionsButtonClick()
}
}
- showActionMenu(menu,OPTIONS_BUTTON_NAME);
+ mGearButton->setMenu(menu);
}
void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
@@ -750,7 +756,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);
@@ -1074,6 +1083,60 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
{
doActionOnCurSelectedLandmark(boost::bind(&LLLandmarksPanel::doCreatePick, this, _1));
}
+ else if ("restore" == command_name && mCurrentSelectedList)
+ {
+ mCurrentSelectedList->doToSelected(userdata);
+ }
+}
+
+void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param)
+{
+ bool new_visibility = param["visibility"].asBoolean();
+
+ // We don't have to update items visibility if the menu is hiding.
+ if (!new_visibility) return;
+
+ BOOL are_any_items_in_trash = FALSE;
+ BOOL are_all_items_in_trash = TRUE;
+
+ LLFolderView* root_folder_view = mCurrentSelectedList ? mCurrentSelectedList->getRootFolder() : NULL;
+ if(root_folder_view)
+ {
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+
+ std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList();
+
+ // Iterate through selected items to find out if any of these items are in Trash
+ // or all the items are in Trash category.
+ for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter)
+ {
+ LLFolderViewItem* item = root_folder_view->getItemByID(*iter);
+
+ // If no item is found it might be a folder id.
+ if (!item)
+ {
+ item = root_folder_view->getFolderByID(*iter);
+ }
+ if (!item) continue;
+
+ LLFolderViewEventListener* listenerp = item->getListener();
+ if(!listenerp) continue;
+
+ // Trash category itself should not be included because it can't be
+ // actually restored from trash.
+ are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id;
+
+ // If there are any selected items in Trash including the Trash category itself
+ // we show "Restore Item" in context menu and hide other irrelevant items.
+ are_any_items_in_trash |= listenerp->isItemInTrash();
+ }
+ }
+
+ // Display "Restore Item" menu entry if at least one of the selected items
+ // is in Trash or the Trash category itself is among selected items.
+ // Hide other menu entries in this case.
+ // Enable this menu entry only if all selected items are in the Trash category.
+ toggle_restore_menu((LLMenuGL*)ctrl, are_any_items_in_trash, are_all_items_in_trash);
}
/*
@@ -1409,4 +1472,31 @@ static bool has_collapsed_folders(LLFolderView* root_folder)
return true;
}
+
+// Displays "Restore Item" context menu entry while hiding
+// all other entries or vice versa.
+// Sets "Restore Item" enabled state.
+void toggle_restore_menu(LLMenuGL *menu, BOOL visible, BOOL enabled)
+{
+ if (!menu) return;
+
+ const LLView::child_list_t *list = menu->getChildList();
+ for (LLView::child_list_t::const_iterator itor = list->begin();
+ itor != list->end();
+ ++itor)
+ {
+ LLView *menu_item = (*itor);
+ std::string name = menu_item->getName();
+
+ if ("restore_item" == name)
+ {
+ menu_item->setVisible(visible);
+ menu_item->setEnabled(enabled);
+ }
+ else
+ {
+ menu_item->setVisible(!visible);
+ }
+ }
+}
// EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 0d4402d8cb..b2f4e92473 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;
@@ -127,6 +129,14 @@ private:
void onCustomAction(const LLSD& command_name);
/**
+ * Updates context menu depending on the selected items location.
+ *
+ * For items in Trash category the menu includes the "Restore Item"
+ * context menu entry.
+ */
+ void onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param);
+
+ /**
* Determines if an item can be modified via context/gear menu.
*
* It validates Places Landmarks rules first. And then LLFolderView permissions.
@@ -155,8 +165,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/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp
index f17defda55..b3adfac8a2 100644
--- a/indra/newview/llpanellandmedia.cpp
+++ b/indra/newview/llpanellandmedia.cpp
@@ -68,8 +68,7 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel)
mMediaSizeCtrlLabel(NULL),
mMediaTextureCtrl(NULL),
mMediaAutoScaleCheck(NULL),
- mMediaLoopCheck(NULL),
- mMediaUrlCheck(NULL)
+ mMediaLoopCheck(NULL)
{
}
@@ -94,9 +93,6 @@ BOOL LLPanelLandMedia::postBuild()
mMediaLoopCheck = getChild<LLCheckBoxCtrl>("media_loop");
childSetCommitCallback("media_loop", onCommitAny, this );
- mMediaUrlCheck = getChild<LLCheckBoxCtrl>("hide_media_url");
- childSetCommitCallback("hide_media_url", onCommitAny, this );
-
mMediaURLEdit = getChild<LLLineEditor>("media_url");
childSetCommitCallback("media_url", onCommitAny, this );
@@ -153,25 +149,6 @@ void LLPanelLandMedia::refresh()
mMediaTypeCombo->setEnabled( can_change_media );
getChild<LLUICtrl>("mime_type")->setValue(mime_type);
- mMediaUrlCheck->set( parcel->getObscureMedia() );
- mMediaUrlCheck->setEnabled( can_change_media );
-
- // don't display urls if you're not able to change it
- // much requested change in forums so people can't 'steal' urls
- // NOTE: bug#2009 means this is still vunerable - however, bug
- // should be closed since this bug opens up major security issues elsewhere.
- bool obscure_media = ! can_change_media && parcel->getObscureMedia();
-
- // Special code to disable asterixes for html type
- if(mime_type == "text/html")
- {
- obscure_media = false;
- mMediaUrlCheck->set( 0 );
- mMediaUrlCheck->setEnabled( false );
- }
-
- mMediaURLEdit->setDrawAsterixes( obscure_media );
-
mMediaAutoScaleCheck->set( parcel->getMediaAutoScale () );
mMediaAutoScaleCheck->setEnabled ( can_change_media );
@@ -301,7 +278,6 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
std::string mime_type = self->getChild<LLUICtrl>("mime_type")->getValue().asString();
U8 media_auto_scale = self->mMediaAutoScaleCheck->get();
U8 media_loop = self->mMediaLoopCheck->get();
- U8 obscure_media = self->mMediaUrlCheck->get();
S32 media_width = (S32)self->mMediaWidthCtrl->get();
S32 media_height = (S32)self->mMediaHeightCtrl->get();
LLUUID media_id = self->mMediaTextureCtrl->getImageAssetID();
@@ -321,7 +297,6 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata)
parcel->setMediaID(media_id);
parcel->setMediaAutoScale ( media_auto_scale );
parcel->setMediaLoop ( media_loop );
- parcel->setObscureMedia( obscure_media );
// Send current parcel data upstream to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 467aefc60f..903cf4780d 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -35,6 +35,7 @@
#include "llsecondlifeurls.h"
#include "v4color.h"
+#include "llappviewer.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "llcommandhandler.h" // for secondlife:///app/login/
@@ -73,7 +74,6 @@
#endif // LL_WINDOWS
#include "llsdserialize.h"
-#define USE_VIEWER_AUTH 0
const S32 BLACK_BORDER_HEIGHT = 160;
const S32 MAX_PASSWORD = 16;
@@ -163,8 +163,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
mHtmlAvailable( TRUE ),
mListener(new LLPanelLoginListener(this))
{
- setFocusRoot(TRUE);
-
setBackgroundVisible(FALSE);
setBackgroundOpaque(TRUE);
@@ -181,18 +179,17 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
mPasswordModified = FALSE;
LLPanelLogin::sInstance = this;
- // add to front so we are the bottom-most child
- gViewerWindow->getRootView()->addChildInBack(this);
+ LLView* login_holder = gViewerWindow->getLoginPanelHolder();
+ if (login_holder)
+ {
+ login_holder->addChild(this);
+ }
// Logo
mLogoImage = LLUI::getUIImage("startup_logo");
buildFromFile( "panel_login.xml");
-#if USE_VIEWER_AUTH
- //leave room for the login menu bar
- setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0));
-#endif
// Legacy login web page is hidden under the menu bar.
// Adjust reg-in-client web browser widget to not be hidden.
if (gSavedSettings.getBOOL("RegInClient"))
@@ -204,16 +201,12 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
reshape(rect.getWidth(), rect.getHeight());
}
-#if !USE_VIEWER_AUTH
getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
// change z sort of clickable text to be behind buttons
//sendChildToBack(getChildView("channel_text"));
sendChildToBack(getChildView("forgot_password_text"));
- LLLineEditor* edit = getChild<LLLineEditor>("password_edit");
- if (edit) edit->setDrawAsterixes(TRUE);
-
if(LLStartUp::getStartSLURL().getType() != LLSLURL::LOCATION)
{
LLSLURL slurl(gSavedSettings.getString("LoginLocation"));
@@ -221,6 +214,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
}
updateLocationCombo(false);
+ gSavedSettings.getControl("SessionSettingsFile")->getSignal()->connect(boost::bind(&onModeChange));
+
LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");
server_choice_combo->setCommitCallback(onSelectServer, NULL);
server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1));
@@ -230,7 +225,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());
@@ -247,7 +242,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
LLTextBox* need_help_text = getChild<LLTextBox>("login_help");
need_help_text->setClickedCallback(onClickHelp, NULL);
-#endif
// get the web browser control
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
@@ -262,11 +256,67 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
gResponsePtr = LLIamHereLogin::build( this );
LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr );
-
+
+ // Show last logged in user favorites in "Start at" combo.
+ addUsersWithFavoritesToUsername();
+ getChild<LLComboBox>("username_combo")->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this));
+
updateLocationCombo(false);
}
+void LLPanelLogin::addUsersWithFavoritesToUsername()
+{
+ LLComboBox* combo = getChild<LLComboBox>("username_combo");
+ if (!combo) return;
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
+ LLSD fav_llsd;
+ llifstream file;
+ file.open(filename);
+ if (!file.is_open()) return;
+ LLSDSerialize::fromXML(fav_llsd, file);
+ for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
+ iter != fav_llsd.endMap(); ++iter)
+ {
+ combo->add(iter->first);
+ }
+}
+
+void LLPanelLogin::addFavoritesToStartLocation()
+{
+ LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
+ if (!combo) return;
+ int num_items = combo->getItemCount();
+ for (int i = num_items - 1; i > 2; i--)
+ {
+ combo->remove(i);
+ }
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
+ LLSD fav_llsd;
+ llifstream file;
+ file.open(filename);
+ if (!file.is_open()) return;
+ LLSDSerialize::fromXML(fav_llsd, file);
+ for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
+ iter != fav_llsd.endMap(); ++iter)
+ {
+ if(iter->first != getChild<LLComboBox>("username_combo")->getSimple()) continue;
+ combo->addSeparator();
+ LLSD user_llsd = iter->second;
+ for (LLSD::array_const_iterator iter1 = user_llsd.beginArray();
+ iter1 != user_llsd.endArray(); ++iter1)
+ {
+ std::string label = (*iter1)["name"].asString();
+ std::string value = (*iter1)["slurl"].asString();
+ if(label != "" && value != "")
+ {
+ combo->add(label, value);
+ }
+ }
+ break;
+ }
+}
+
// force the size to be correct (XML doesn't seem to be sufficient to do this)
// (with some padding so the other login screen doesn't show through)
void LLPanelLogin::reshapeBrowser()
@@ -274,15 +324,9 @@ void LLPanelLogin::reshapeBrowser()
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
LLRect rect = gViewerWindow->getWindowRectScaled();
LLRect html_rect;
-#if USE_VIEWER_AUTH
- html_rect.setCenterAndSize(
- rect.getCenterX() - 2, rect.getCenterY(),
- rect.getWidth() + 6, rect.getHeight());
-#else
html_rect.setCenterAndSize(
rect.getCenterX() - 2, rect.getCenterY() + 40,
rect.getWidth() + 6, rect.getHeight() - 78 );
-#endif
web_browser->setRect( html_rect );
web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE );
reshape( rect.getWidth(), rect.getHeight(), 1 );
@@ -305,7 +349,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive )
else
// the site is not available (missing page, server down, other badness)
{
-#if !USE_VIEWER_AUTH
if ( web_browser )
{
// hide browser control (revealing default one)
@@ -314,16 +357,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive )
// mark as unavailable
mHtmlAvailable = FALSE;
}
-#else
-
- if ( web_browser )
- {
- web_browser->navigateToLocalPage( "loading-error" , "index.html" );
-
- // mark as available
- mHtmlAvailable = TRUE;
- }
-#endif
}
}
@@ -363,7 +396,6 @@ void LLPanelLogin::draw()
if ( mHtmlAvailable )
{
-#if !USE_VIEWER_AUTH
if (getChild<LLView>("login_widgets")->getVisible())
{
// draw a background box in black
@@ -372,7 +404,6 @@ void LLPanelLogin::draw()
// just the blue background to the native client UI
mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
}
-#endif
}
else
{
@@ -418,22 +449,17 @@ void LLPanelLogin::setFocus(BOOL b)
// static
void LLPanelLogin::giveFocus()
{
-#if USE_VIEWER_AUTH
- if (sInstance)
- {
- sInstance->setFocus(TRUE);
- }
-#else
if( sInstance )
{
// Grab focus and move cursor to first blank input field
- std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString();
+ std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
BOOL have_username = !username.empty();
BOOL have_pass = !pass.empty();
LLLineEditor* edit = NULL;
+ LLComboBox* combo = NULL;
if (have_username && !have_pass)
{
// User saved his name but not his password. Move
@@ -443,7 +469,7 @@ void LLPanelLogin::giveFocus()
else
{
// User doesn't have a name, so start there.
- edit = sInstance->getChild<LLLineEditor>("username_edit");
+ combo = sInstance->getChild<LLComboBox>("username_combo");
}
if (edit)
@@ -451,21 +477,26 @@ void LLPanelLogin::giveFocus()
edit->setFocus(TRUE);
edit->selectAll();
}
+ else if (combo)
+ {
+ combo->setFocus(TRUE);
+ }
}
-#endif
}
// static
void LLPanelLogin::showLoginWidgets()
{
+ // *NOTE: Mani - This may or may not be obselete code.
+ // It seems to be part of the defunct? reg-in-client project.
sInstance->getChildView("login_widgets")->setVisible( true);
LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
sInstance->reshapeBrowser();
// *TODO: Append all the usual login parameters, like first_login=Y etc.
- std::string splash_screen_url = sInstance->getString("real_url");
+ std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
web_browser->navigateTo( splash_screen_url, "text/html" );
- LLUICtrl* username_edit = sInstance->getChild<LLUICtrl>("username_edit");
- username_edit->setFocus(TRUE);
+ LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
+ username_combo->setFocus(TRUE);
}
// static
@@ -509,16 +540,17 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
login_id += " ";
login_id += lastname;
}
- sInstance->getChild<LLUICtrl>("username_edit")->setValue(login_id);
+ sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);
}
else if((std::string)identifier["type"] == "account")
{
- sInstance->getChild<LLUICtrl>("username_edit")->setValue((std::string)identifier["account_name"]);
+ sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);
}
else
{
- sInstance->getChild<LLUICtrl>("username_edit")->setValue(std::string());
+ sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());
}
+ sInstance->addFavoritesToStartLocation();
// if the password exists in the credential, set the password field with
// a filler to get some stars
LLSD authenticator = credential->getAuthenticator();
@@ -566,7 +598,7 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
authenticator = credential->getAuthenticator();
}
- std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString();
+ std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
LLStringUtil::trim(username);
std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
@@ -658,15 +690,15 @@ BOOL LLPanelLogin::areCredentialFieldsDirty()
}
else
{
- std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString();
+ std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
LLStringUtil::trim(username);
std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
- LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("username_edit");
- if(ctrl && ctrl->isDirty())
+ LLComboBox* combo = sInstance->getChild<LLComboBox>("username_combo");
+ if(combo && combo->isDirty())
{
return true;
}
- ctrl = sInstance->getChild<LLLineEditor>("password_edit");
+ LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("password_edit");
if(ctrl && ctrl->isDirty())
{
return true;
@@ -761,7 +793,7 @@ void LLPanelLogin::closePanel()
{
if (sInstance)
{
- gViewerWindow->getRootView()->removeChild( LLPanelLogin::sInstance );
+ LLPanelLogin::sInstance->getParent()->removeChild( LLPanelLogin::sInstance );
delete sInstance;
sInstance = NULL;
@@ -817,7 +849,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;
@@ -830,75 +862,15 @@ void LLPanelLogin::loadLoginPage()
char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLabel().c_str(), 0);
oStr << "&grid=" << curl_grid;
curl_free(curl_grid);
- gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
- gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
-
-
-#if USE_VIEWER_AUTH
- LLURLSimString::sInstance.parse();
-
- std::string location;
- std::string region;
- std::string password;
-
- if (LLURLSimString::parse())
- {
- std::ostringstream oRegionStr;
- location = "specify";
- oRegionStr << LLURLSimString::sInstance.mSimName << "/" << LLURLSimString::sInstance.mX << "/"
- << LLURLSimString::sInstance.mY << "/"
- << LLURLSimString::sInstance.mZ;
- region = oRegionStr.str();
- }
- else
- {
- location = gSavedSettings.getString("LoginLocation");
- }
- std::string username;
-
- if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)
- {
- LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo");
- username = cmd_line_login[0].asString() + " " + cmd_line_login[1];
- password = cmd_line_login[2].asString();
- }
-
+ // add OS info
+ char * os_info = curl_escape(LLAppViewer::instance()->getOSInfo().getOSStringSimple().c_str(), 0);
+ oStr << "&os=" << os_info;
+ curl_free(os_info);
- char* curl_region = curl_escape(region.c_str(), 0);
-
- oStr <<"username=" << username <<
- "&location=" << location << "&region=" << curl_region;
- curl_free(curl_region);
-
- if (!password.empty())
- {
- oStr << "&password=" << password;
- }
- else if (!(password = load_password_from_disk()).empty())
- {
- oStr << "&password=$1$" << password;
- }
- if (gAutoLogin)
- {
- oStr << "&auto_login=TRUE";
- }
- if (gSavedSettings.getBOOL("ShowStartLocation"))
- {
- oStr << "&show_start_location=TRUE";
- }
- if (gSavedSettings.getBOOL("RememberPassword"))
- {
- oStr << "&remember_password=TRUE";
- }
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- oStr << "&show_grid=TRUE";
-#else
- if (gSavedSettings.getBOOL("ForceShowGrid"))
- oStr << "&show_grid=TRUE";
-#endif
-#endif
+ gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
+ gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
@@ -973,7 +945,7 @@ void LLPanelLogin::onClickConnect(void *)
return;
}
updateStartSLURL();
- std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString();
+ std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
if(username.empty())
@@ -1186,3 +1158,26 @@ void LLPanelLogin::updateLoginPanelLinks()
sInstance->getChildView("create_new_account_text")->setVisible( system_grid);
sInstance->getChildView("forgot_password_text")->setVisible( system_grid);
}
+
+//static
+void LLPanelLogin::onModeChange()
+{
+ LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&onModeChangeConfirm, _1, _2));
+}
+
+//static
+void LLPanelLogin::onModeChangeConfirm(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch (option)
+ {
+ case 0:
+ LLAppViewer::instance()->requestQuit();
+ break;
+ case 1:
+ // do nothing
+ break;
+ default:
+ break;
+ }
+}
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index 83e76a308b..1430bec832 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -85,6 +85,8 @@ public:
private:
friend class LLPanelLoginListener;
void reshapeBrowser();
+ void addFavoritesToStartLocation();
+ void addUsersWithFavoritesToUsername();
static void onClickConnect(void*);
static void onClickNewAccount(void*);
// static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response);
@@ -96,6 +98,8 @@ private:
static void onServerComboLostFocus(LLFocusableElement*);
static void updateServerCombo();
static void updateStartSLURL();
+ static void onModeChange();
+ static void onModeChangeConfirm(const LLSD& notification, const LLSD& response);
static void updateLoginPanelLinks();
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 5b07e4863b..0c3f2f3e31 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"
@@ -116,18 +118,6 @@ LLPanelMainInventory::LLPanelMainInventory()
mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2));
mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars));
- // Controls
- // *TODO: Just use persistant settings for each of these
- U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
- BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE );
- BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME );
- BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP );
-
- gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE);
- gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE);
- gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE);
- gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE);
-
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
}
@@ -192,6 +182,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
@@ -321,57 +313,41 @@ void LLPanelMainInventory::resetFilters()
void LLPanelMainInventory::setSortBy(const LLSD& userdata)
{
- std::string sort_field = userdata.asString();
- if (sort_field == "name")
+ U32 sort_order_mask = getActivePanel()->getSortOrder();
+ std::string sort_type = userdata.asString();
+ if (sort_type == "name")
{
- U32 order = getActivePanel()->getSortOrder();
- getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
-
- gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
- gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
+ sort_order_mask &= ~LLInventoryFilter::SO_DATE;
}
- else if (sort_field == "date")
+ else if (sort_type == "date")
{
- U32 order = getActivePanel()->getSortOrder();
- getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
-
- gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
- gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
+ sort_order_mask |= LLInventoryFilter::SO_DATE;
}
- else if (sort_field == "foldersalwaysbyname")
+ else if (sort_type == "foldersalwaysbyname")
{
- U32 order = getActivePanel()->getSortOrder();
- if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME )
+ if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME )
{
- order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME;
-
- gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE );
+ sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME;
}
else
{
- order |= LLInventoryFilter::SO_FOLDERS_BY_NAME;
-
- gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE );
+ sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME;
}
- getActivePanel()->setSortOrder( order );
}
- else if (sort_field == "systemfolderstotop")
+ else if (sort_type == "systemfolderstotop")
{
- U32 order = getActivePanel()->getSortOrder();
- if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP )
+ if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP )
{
- order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
-
- gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE );
+ sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
}
else
{
- order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
-
- gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
+ sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
}
- getActivePanel()->setSortOrder( order );
}
+
+ getActivePanel()->setSortOrder(sort_order_mask);
+ gSavedSettings.setU32("InventorySortOrder", sort_order_mask);
}
// static
@@ -492,9 +468,6 @@ void LLPanelMainInventory::onFilterSelected()
return;
}
- BOOL recent_active = ("Recent Items" == mActivePanel->getName());
- getChildView("add_btn_panel")->setVisible( !recent_active);
-
setFilterSubString(mFilterSubString);
LLInventoryFilter* filter = mActivePanel->getFilter();
LLFloaterInventoryFinder *finder = getFinder();
@@ -900,7 +873,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 +884,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,13 +901,13 @@ void LLPanelMainInventory::updateListCommands()
mTrashButton->setEnabled(trash_enabled);
}
-void LLPanelMainInventory::onGearButtonClick()
-{
- showActionMenu(mMenuGearDefault,"options_gear_btn");
-}
-
void LLPanelMainInventory::onAddButtonClick()
{
+// Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed
+// unless "Always show folders" is checked in the filter options.
+ bool recent_active = ("Recent Items" == mActivePanel->getName());
+ mMenuAdd->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
+
setUploadCostIfNeeded();
showActionMenu(mMenuAdd,"add_btn");
@@ -1001,6 +975,16 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
const LLSD arg = "date";
setSortBy(arg);
}
+ if (command_name == "sort_folders_by_name")
+ {
+ const LLSD arg = "foldersalwaysbyname";
+ setSortBy(arg);
+ }
+ if (command_name == "sort_system_folders_to_top")
+ {
+ const LLSD arg = "systemfolderstotop";
+ setSortBy(arg);
+ }
if (command_name == "show_filters")
{
toggleFindOptions();
@@ -1174,6 +1158,33 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
return TRUE;
}
+BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
+{
+ U32 sort_order_mask = getActivePanel()->getSortOrder();
+ const std::string command_name = userdata.asString();
+ if (command_name == "sort_by_name")
+ {
+ return ~sort_order_mask & LLInventoryFilter::SO_DATE;
+ }
+
+ if (command_name == "sort_by_recent")
+ {
+ return sort_order_mask & LLInventoryFilter::SO_DATE;
+ }
+
+ if (command_name == "sort_folders_by_name")
+ {
+ return sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME;
+ }
+
+ if (command_name == "sort_system_folders_to_top")
+ {
+ return sort_order_mask & 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/llpanelme.cpp b/indra/newview/llpanelme.cpp
index 5ea94e0611..d3c9c3e131 100644
--- a/indra/newview/llpanelme.cpp
+++ b/indra/newview/llpanelme.cpp
@@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key)
{
LLPanelProfile::onOpen(key);
- // Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068)
- bool opened = gSavedSettings.getBOOL("MePanelOpened");
- // In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this
- // is the last time onOpen() is called
- if( !opened && !LLSideTray::getInstance()->getCollapsed() )
- {
- buildEditPanel();
- openPanel(mEditPanel, getAvatarId());
-
- gSavedSettings.setBOOL("MePanelOpened", true);
- }
+ // Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab
+ // in the sidebar, they see the old profile editing panel
+ //
+ //// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068)
+ //bool opened = gSavedSettings.getBOOL("MePanelOpened");
+ //// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this
+ //// is the last time onOpen() is called
+ //if( !opened && !LLSideTray::getInstance()->getCollapsed() )
+ //{
+ // buildEditPanel();
+ // openPanel(mEditPanel, getAvatarId());
+ // gSavedSettings.setBOOL("MePanelOpened", true);
+ //}
}
bool LLPanelMe::notifyChildren(const LLSD& info)
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index fcc67d6840..a7f1ab28fd 100644
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -564,16 +564,14 @@ void LLPanelNearByMedia::refreshParcelItems()
if (NULL != mParcelMediaItem)
{
std::string name, url, tooltip;
- if (!LLViewerParcelMgr::getInstance()->getAgentParcel()->getObscureMedia())
+ getNameAndUrlHelper(LLViewerParcelMedia::getParcelMedia(), name, url, "");
+ if (name.empty() || name == url)
{
- getNameAndUrlHelper(LLViewerParcelMedia::getParcelMedia(), name, url, "");
- if (name.empty() || name == url)
- {
- tooltip = url;
- }
- else {
- tooltip = name + " : " + url;
- }
+ tooltip = url;
+ }
+ else
+ {
+ tooltip = name + " : " + url;
}
LLViewerMediaImpl *impl = LLViewerParcelMedia::getParcelMedia();
updateListItem(mParcelMediaItem,
@@ -611,10 +609,8 @@ void LLPanelNearByMedia::refreshParcelItems()
bool is_playing = LLViewerMedia::isParcelAudioPlaying();
std::string url;
- if (!LLViewerParcelMgr::getInstance()->getAgentParcel()->getObscureMusic())
- {
- url = LLViewerMedia::getParcelAudioURL();
- }
+ url = LLViewerMedia::getParcelAudioURL();
+
updateListItem(mParcelAudioItem,
mParcelAudioName,
url,
@@ -958,7 +954,7 @@ void LLPanelNearByMedia::onAdvancedButtonClick()
void LLPanelNearByMedia::onMoreLess()
{
- bool is_more = getChild<LLUICtrl>("more_btn")->getVisible();
+ bool is_more = getChild<LLButton>("more_btn")->getToggleState();
mNearbyMediaPanel->setVisible(is_more);
// enable resizing when expanded
@@ -969,8 +965,7 @@ void LLPanelNearByMedia::onMoreLess()
setShape(new_rect);
- getChild<LLUICtrl>("more_btn")->setVisible(!is_more);
- getChild<LLUICtrl>("less_btn")->setVisible(is_more);
+ getChild<LLUICtrl>("more_btn")->setVisible(true);
}
void LLPanelNearByMedia::updateControls()
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/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index 211b9cf4b1..0b6267c9e6 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -766,22 +766,12 @@ BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
{
- const LLInventoryItem *inv = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID));
- if (inv)
+ const LLInventoryObject* cat = object->getInventoryObject(mUUID);
+ if ( (cat) && (move_inv_category_world_to_agent(mUUID, LLUUID::null, FALSE)) )
{
- const LLPermissions& perm = inv->getPermissions();
- bool can_copy = gAgent.allowOperation(PERM_COPY, perm,
- GP_OBJECT_MANIPULATE);
- if((can_copy && perm.allowTransferTo(gAgent.getID()))
- || object->permYouOwner())
-// || gAgent.isGodlike())
-
- {
- *type = LLViewerAssetType::lookupDragAndDropType(inv->getType());
-
- *id = inv->getUUID();
- return TRUE;
- }
+ *type = LLViewerAssetType::lookupDragAndDropType(cat->getType());
+ *id = mUUID;
+ return TRUE;
}
}
}
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 408d4f29b7..62f582c343 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)
@@ -184,14 +186,8 @@ private:
// Populate the menu with items like "New Skin", "New Pants", etc.
static void populateCreateWearableSubmenus(LLMenuGL* menu)
{
- LLView* menu_clothes = gMenuHolder->findChildView("COF.Gear.New_Clothes", FALSE);
- LLView* menu_bp = gMenuHolder->findChildView("COF.Geear.New_Body_Parts", FALSE);
-
- if (!menu_clothes || !menu_bp)
- {
- llassert(menu_clothes && menu_bp);
- return;
- }
+ LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE);
+ LLView* menu_bp = gMenuHolder->getChildView("COF.Geear.New_Body_Parts", FALSE);
for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i)
{
@@ -218,7 +214,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 +229,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 +400,9 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()
mFolderViewFilterCmbBox(NULL),
mListViewFilterCmbBox(NULL),
mWearableListManager(NULL),
- mPlusBtn(NULL)
+ mPlusBtn(NULL),
+ mWearablesGearMenuBtn(NULL),
+ mGearMenuBtn(NULL)
{
mSavedFolderState = new LLSaveFolderState();
mSavedFolderState->setApply(FALSE);
@@ -468,6 +466,7 @@ BOOL LLPanelOutfitEdit::postBuild()
mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIRT)));
mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("alpha"), new LLFindActualWearablesOfType(LLWearableType::WT_ALPHA)));
mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("tattoo"), new LLFindActualWearablesOfType(LLWearableType::WT_TATTOO)));
+ mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("physics"), new LLFindActualWearablesOfType(LLWearableType::WT_PHYSICS)));
mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name");
mStatus = getChild<LLTextBox>("status");
@@ -480,13 +479,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 +559,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 +1265,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();
@@ -1348,19 +1324,19 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id)
void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list)
{
+ void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back;
if (mInventoryItemsPanel->getVisible())
{
std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList();
- std::for_each(item_set.begin(), item_set.end(), boost::bind( &uuid_vec_t::push_back, &uuid_list, _1));
+ std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1));
}
else if (mWearablesListViewPanel->getVisible())
{
std::vector<LLSD> item_set;
mWearableItemsList->getSelectedValues(item_set);
- std::for_each(item_set.begin(), item_set.end(), boost::bind( &uuid_vec_t::push_back, &uuid_list, boost::bind(&LLSD::asUUID, _1 )));
-
+ std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, boost::bind(&LLSD::asUUID, _1 )));
}
// return selected_id;
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 2dca986e33..5d4b8d4644 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;
@@ -96,6 +97,7 @@ public:
LVIT_SKIRT,
LVIT_ALPHA,
LVIT_TATTOO,
+ LVIT_PHYSICS,
NUM_LIST_VIEW_ITEM_TYPES
} EListViewItemType;
@@ -186,8 +188,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 +234,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..b52f33ec3b 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"
@@ -52,6 +54,7 @@
#include "llgroupactions.h"
#include "llgrouplist.h"
#include "llinventoryobserver.h"
+#include "llnetmap.h"
#include "llpanelpeoplemenus.h"
#include "llsidetray.h"
#include "llsidetraypanelcontainer.h"
@@ -229,7 +232,7 @@ public:
virtual void setActive(bool) {}
protected:
- void updateList()
+ void update()
{
mCallback();
}
@@ -237,6 +240,30 @@ protected:
callback_t mCallback;
};
+/**
+ * Update buttons on changes in our friend relations (STORM-557).
+ */
+class LLButtonsUpdater : public LLPanelPeople::Updater, public LLFriendObserver
+{
+public:
+ LLButtonsUpdater(callback_t cb)
+ : LLPanelPeople::Updater(cb)
+ {
+ LLAvatarTracker::instance().addObserver(this);
+ }
+
+ ~LLButtonsUpdater()
+ {
+ LLAvatarTracker::instance().removeObserver(this);
+ }
+
+ /*virtual*/ void changed(U32 mask)
+ {
+ (void) mask;
+ update();
+ }
+};
+
class LLAvatarListUpdater : public LLPanelPeople::Updater, public LLEventTimer
{
public:
@@ -304,7 +331,7 @@ public:
if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
{
- updateList();
+ update();
}
// Stop updates.
@@ -357,6 +384,16 @@ private:
{
lldebugs << "Inventory changed: " << mask << llendl;
+ static bool synchronize_friends_folders = true;
+ if (synchronize_friends_folders)
+ {
+ // Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" folder,
+ // fetches their contents if needed and synchronizes it with buddies list.
+ // If the folders are not found they are created.
+ LLFriendCardsManager::instance().syncFriendCardsFolders();
+ synchronize_friends_folders = false;
+ }
+
// *NOTE: deleting of InventoryItem is performed via moving to Trash.
// That means LLInventoryObserver::STRUCTURE is present in MASK instead of LLInventoryObserver::REMOVE
if ((CALLINGCARD_ADDED & mask) == CALLINGCARD_ADDED)
@@ -419,7 +456,7 @@ public:
if (val)
{
// update immediately and start regular updates
- updateList();
+ update();
mEventTimer.start();
}
else
@@ -431,7 +468,7 @@ public:
/*virtual*/ BOOL tick()
{
- updateList();
+ update();
return FALSE;
}
private:
@@ -448,7 +485,7 @@ public:
LLRecentListUpdater(callback_t cb)
: LLAvatarListUpdater(cb, 0)
{
- LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this));
+ LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::update, this));
}
};
@@ -464,16 +501,23 @@ LLPanelPeople::LLPanelPeople()
mAllFriendList(NULL),
mNearbyList(NULL),
mRecentList(NULL),
- mGroupList(NULL)
+ mGroupList(NULL),
+ mNearbyGearButton(NULL),
+ mFriendsGearButton(NULL),
+ mGroupsGearButton(NULL),
+ mRecentGearButton(NULL),
+ mMiniMap(NULL)
{
mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this));
mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this));
mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this));
+ mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this));
mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this));
}
LLPanelPeople::~LLPanelPeople()
{
+ delete mButtonsUpdater;
delete mNearbyListUpdater;
delete mFriendListUpdater;
delete mRecentListUpdater;
@@ -535,6 +579,9 @@ BOOL LLPanelPeople::postBuild()
mNearbyList->setNoItemsMsg(getString("no_one_near"));
mNearbyList->setNoFilteredItemsMsg(getString("no_one_filtered_near"));
mNearbyList->setShowIcons("NearbyListShowIcons");
+ mMiniMap = (LLNetMap*)getChildView("Net Map",true);
+ mMiniMap->setToolTipMsg(gSavedSettings.getBOOL("DoubleClickTeleport") ?
+ getString("AltMiniMapToolTipMsg") : getString("MiniMapToolTipMsg"));
mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
mRecentList->setNoItemsCommentText(getString("no_recent_people"));
@@ -600,11 +647,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 +666,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);
@@ -701,18 +760,23 @@ void LLPanelPeople::updateFriendList()
all_friendsp.clear();
online_friendsp.clear();
- LLFriendCardsManager::folderid_buddies_map_t listMap;
+ uuid_vec_t buddies_uuids;
+ LLAvatarTracker::buddy_map_t::const_iterator buddies_iter;
+
+ // Fill the avatar list with friends UUIDs
+ for (buddies_iter = all_buddies.begin(); buddies_iter != all_buddies.end(); ++buddies_iter)
+ {
+ buddies_uuids.push_back(buddies_iter->first);
+ }
- // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694.
- LLFriendCardsManager::instance().collectFriendsLists(listMap);
- if (listMap.size() > 0)
+ if (buddies_uuids.size() > 0)
{
- lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl;
- all_friendsp = listMap.begin()->second;
+ lldebugs << "Friends added to the list: " << buddies_uuids.size() << llendl;
+ all_friendsp = buddies_uuids;
}
else
{
- lldebugs << "Friends Cards were not found" << llendl;
+ lldebugs << "No friends found" << llendl;
}
LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
@@ -911,7 +975,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();
@@ -1044,6 +1108,12 @@ void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl)
void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)
{
+ if (getActiveTabName() == NEARBY_TAB_NAME)
+ {
+ uuid_vec_t selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+ mMiniMap->setSelected(selected_uuids);
+ } else
// Make sure only one of the friends lists (online/all) has selection.
if (getActiveTabName() == FRIENDS_TAB_NAME)
{
@@ -1346,44 +1416,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..46c58cd139 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();
@@ -145,6 +142,7 @@ private:
LLAvatarList* mNearbyList;
LLAvatarList* mRecentList;
LLGroupList* mGroupList;
+ LLNetMap* mMiniMap;
LLHandle<LLView> mGroupPlusMenuHandle;
LLHandle<LLView> mNearbyViewSortMenuHandle;
@@ -155,6 +153,12 @@ private:
Updater* mFriendListUpdater;
Updater* mNearbyListUpdater;
Updater* mRecentListUpdater;
+ Updater* mButtonsUpdater;
+
+ 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..ddce83c616 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -70,6 +70,118 @@ static const std::string CLASSIFIED_NAME("classified_name");
static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
+
+class LLPickHandler : public LLCommandHandler,
+ public LLAvatarPropertiesObserver
+{
+public:
+
+ std::set<LLUUID> mPickIds;
+
+ // requires trusted browser to trigger
+ LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { }
+
+ bool handle(const LLSD& params, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnablePicks"))
+ {
+ LLNotificationsUtil::add("NoPicks", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
+ // handle app/classified/create urls first
+ if (params.size() == 1 && params[0].asString() == "create")
+ {
+ createPick();
+ return true;
+ }
+
+ // then handle the general app/pick/{UUID}/{CMD} urls
+ if (params.size() < 2)
+ {
+ return false;
+ }
+
+ // get the ID for the pick_id
+ LLUUID pick_id;
+ if (!pick_id.set(params[0], FALSE))
+ {
+ return false;
+ }
+
+ // edit the pick in the side tray.
+ // need to ask the server for more info first though...
+ const std::string verb = params[1].asString();
+ if (verb == "edit")
+ {
+ mPickIds.insert(pick_id);
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(gAgent.getID(),pick_id);
+ return true;
+ }
+ else
+ {
+ llwarns << "unknown verb " << verb << llendl;
+ return false;
+ }
+ }
+
+ void createPick()
+ {
+ LLSD params;
+ params["id"] = gAgent.getID();
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "create_pick";
+ LLSideTray::getInstance()->showPanel("panel_me", params);
+ }
+
+ void editPick(LLPickData* pick_info)
+ {
+ LLSD params;
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "edit_pick";
+ params["pick_id"] = pick_info->pick_id;
+ params["avatar_id"] = pick_info->creator_id;
+ params["snapshot_id"] = pick_info->snapshot_id;
+ params["pick_name"] = pick_info->name;
+ params["pick_desc"] = pick_info->desc;
+
+ LLSideTray::getInstance()->showPanel("panel_me", params);
+ }
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type)
+ {
+ if (APT_PICK_INFO != type)
+ {
+ return;
+ }
+
+ // is this the pick that we asked for?
+ LLPickData* pick_info = static_cast<LLPickData*>(data);
+ if (!pick_info || mPickIds.find(pick_info->pick_id) == mPickIds.end())
+ {
+ return;
+ }
+
+ // open the edit side tray for this pick
+ if (pick_info->creator_id == gAgent.getID())
+ {
+ editPick(pick_info);
+ }
+ else
+ {
+ llwarns << "Can't edit a pick you did not create" << llendl;
+ }
+
+ // remove our observer now that we're done
+ mPickIds.erase(pick_info->pick_id);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this);
+ }
+};
+
+LLPickHandler gPickHandler;
+
class LLClassifiedHandler :
public LLCommandHandler,
public LLAvatarPropertiesObserver
@@ -80,8 +192,16 @@ public:
std::set<LLUUID> mClassifiedIds;
+ std::string mRequestVerb;
+
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableClassifieds"))
+ {
+ LLNotificationsUtil::add("NoClassifieds", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
// handle app/classified/create urls first
if (params.size() == 1 && params[0].asString() == "create")
{
@@ -107,6 +227,15 @@ public:
const std::string verb = params[1].asString();
if (verb == "about")
{
+ mRequestVerb = verb;
+ mClassifiedIds.insert(classified_id);
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id);
+ return true;
+ }
+ else if (verb == "edit")
+ {
+ mRequestVerb = verb;
mClassifiedIds.insert(classified_id);
LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this);
LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id);
@@ -128,18 +257,39 @@ public:
void openClassified(LLAvatarClassifiedInfo* c_info)
{
- // open the classified info panel on the Me > Picks sidetray
- LLSD params;
- params["id"] = c_info->creator_id;
- params["open_tab_name"] = "panel_picks";
- params["show_tab_panel"] = "classified_details";
- params["classified_id"] = c_info->classified_id;
- params["classified_creator_id"] = c_info->creator_id;
- params["classified_snapshot_id"] = c_info->snapshot_id;
- params["classified_name"] = c_info->name;
- params["classified_desc"] = c_info->description;
- params["from_search"] = true;
- LLSideTray::getInstance()->showPanel("panel_profile_view", params);
+ if (mRequestVerb == "about")
+ {
+ // open the classified info panel on the Me > Picks sidetray
+ LLSD params;
+ params["id"] = c_info->creator_id;
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "classified_details";
+ params["classified_id"] = c_info->classified_id;
+ params["classified_creator_id"] = c_info->creator_id;
+ params["classified_snapshot_id"] = c_info->snapshot_id;
+ params["classified_name"] = c_info->name;
+ params["classified_desc"] = c_info->description;
+ params["from_search"] = true;
+ LLSideTray::getInstance()->showPanel("panel_profile_view", params);
+ }
+ else if (mRequestVerb == "edit")
+ {
+ if (c_info->creator_id == gAgent.getID())
+ {
+ llwarns << "edit in progress" << llendl;
+ // open the new classified panel on the Me > Picks sidetray
+ LLSD params;
+ params["id"] = gAgent.getID();
+ params["open_tab_name"] = "panel_picks";
+ params["show_tab_panel"] = "edit_classified";
+ params["classified_id"] = c_info->classified_id;
+ LLSideTray::getInstance()->showPanel("panel_me", params);
+ }
+ else
+ {
+ llwarns << "Can't edit a classified you did not create" << llendl;
+ }
+ }
}
/*virtual*/ void processProperties(void* data, EAvatarProcessorType type)
@@ -212,7 +362,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());
@@ -298,7 +449,10 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
pick_value.insert(CLASSIFIED_ID, c_data.classified_id);
pick_value.insert(CLASSIFIED_NAME, c_data.name);
- mClassifiedsList->addItem(c_item, pick_value);
+ if (!findClassifiedById(c_data.classified_id))
+ {
+ mClassifiedsList->addItem(c_item, pick_value);
+ }
c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1));
c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4));
@@ -314,15 +468,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 +515,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));
@@ -771,6 +929,13 @@ void LLPanelPicks::openClassifiedInfo(const LLSD &params)
getProfilePanel()->openPanel(mPanelClassifiedInfo, params);
}
+void LLPanelPicks::openClassifiedEdit(const LLSD& params)
+{
+ LLUUID classified_id = params["classified_id"].asUUID();;
+ llinfos << "opening classified " << classified_id << " for edit" << llendl;
+ editClassified(classified_id);
+}
+
void LLPanelPicks::showAccordion(const std::string& name, bool show)
{
LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name);
@@ -781,7 +946,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)
@@ -940,6 +1105,12 @@ void LLPanelPicks::createPickEditPanel()
// getProfilePanel()->openPanel(mPanelPickInfo, params);
// }
+void LLPanelPicks::openPickEdit(const LLSD& params)
+{
+ createPickEditPanel();
+ getProfilePanel()->openPanel(mPanelPickEdit, params);
+}
+
void LLPanelPicks::onPanelPickEdit()
{
LLSD selected_value = mPicksList->getSelectedValue();
@@ -973,6 +1144,35 @@ void LLPanelPicks::onPanelClassifiedEdit()
{
return;
}
+ editClassified(c_item->getClassifiedId());
+}
+
+LLClassifiedItem *LLPanelPicks::findClassifiedById(const LLUUID& classified_id)
+{
+ // HACK - find item by classified id. Should be a better way.
+ std::vector<LLPanel*> items;
+ mClassifiedsList->getItems(items);
+ LLClassifiedItem* c_item = NULL;
+ for(std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ LLClassifiedItem *test_item = dynamic_cast<LLClassifiedItem*>(*it);
+ if (test_item && test_item->getClassifiedId() == classified_id)
+ {
+ c_item = test_item;
+ break;
+ }
+ }
+ return c_item;
+}
+
+void LLPanelPicks::editClassified(const LLUUID& classified_id)
+{
+ LLClassifiedItem* c_item = findClassifiedById(classified_id);
+ if (!c_item)
+ {
+ llwarns << "item not found for classified_id " << classified_id << llendl;
+ return;
+ }
LLSD params;
params["classified_id"] = c_item->getClassifiedId();
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 526ba48dcb..29db110523 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -76,6 +76,7 @@ public:
// returns the selected pick item
LLPickItem* getSelectedPickItem();
LLClassifiedItem* getSelectedClassifiedItem();
+ LLClassifiedItem* findClassifiedById(const LLUUID& classified_id);
//*NOTE top down approch when panel toggling is done only by
// parent panels failed to work (picks related code was in my profile panel)
@@ -106,8 +107,10 @@ private:
void onPanelPickSave(LLPanel* panel);
void onPanelClassifiedSave(LLPanelClassifiedEdit* panel);
void onPanelClassifiedClose(LLPanelClassifiedInfo* panel);
+ void openPickEdit(const LLSD& params);
void onPanelPickEdit();
void onPanelClassifiedEdit();
+ void editClassified(const LLUUID& classified_id);
void onClickMenuEdit();
bool onEnableMenuItem(const LLSD& user_data);
@@ -118,6 +121,7 @@ private:
void openPickInfo();
void openClassifiedInfo();
void openClassifiedInfo(const LLSD& params);
+ void openClassifiedEdit(const LLSD& params);
friend class LLPanelProfile;
void showAccordion(const std::string& name, bool show);
@@ -149,6 +153,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/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index f0e60386b6..00ac34efa5 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -39,6 +39,7 @@
#include "llfiltereditor.h"
#include "llfirstuse.h"
#include "llfloaterreg.h"
+#include "llmenubutton.h"
#include "llnotificationsutil.h"
#include "lltabcontainer.h"
#include "lltexteditor.h"
@@ -282,8 +283,8 @@ BOOL LLPanelPlaces::postBuild()
mCloseBtn = getChild<LLButton>("close_btn");
mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
- mOverflowBtn = getChild<LLButton>("overflow_btn");
- mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
+ mOverflowBtn = getChild<LLMenuButton>("overflow_btn");
+ mOverflowBtn->setMouseDownCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
mPlaceInfoBtn = getChild<LLButton>("profile_btn");
mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this));
@@ -330,8 +331,7 @@ BOOL LLPanelPlaces::postBuild()
mPlaceProfileBackBtn = mPlaceProfile->getChild<LLButton>("back_btn");
mPlaceProfileBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
- mLandmarkInfoBackBtn = mLandmarkInfo->getChild<LLButton>("back_btn");
- mLandmarkInfoBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+ mLandmarkInfo->getChild<LLButton>("back_btn")->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
LLLineEditor* title_editor = mLandmarkInfo->getChild<LLLineEditor>("title_editor");
title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL);
@@ -347,8 +347,6 @@ BOOL LLPanelPlaces::postBuild()
void LLPanelPlaces::onOpen(const LLSD& key)
{
- LLFirstUse::notUsingDestinationGuide(false);
-
if (!mPlaceProfile || !mLandmarkInfo)
return;
@@ -384,12 +382,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
- // Disabling "Save", "Close" and "Back" buttons to prevent closing "Create Landmark"
- // panel before created landmark is loaded.
- // These buttons will be enabled when created landmark is added to inventory.
mSaveBtn->setEnabled(FALSE);
- mCloseBtn->setEnabled(FALSE);
- mLandmarkInfoBackBtn->setEnabled(FALSE);
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
@@ -497,8 +490,6 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
mEditBtn->setEnabled(is_landmark_editable);
mSaveBtn->setEnabled(is_landmark_editable);
- mCloseBtn->setEnabled(TRUE);
- mLandmarkInfoBackBtn->setEnabled(TRUE);
if (is_landmark_editable)
{
@@ -762,6 +753,11 @@ void LLPanelPlaces::onOverflowButtonClicked()
// there is no landmark already pointing to that parcel in agent's inventory.
menu->getChild<LLMenuItemCallGL>("landmark")->setEnabled(is_agent_place_info_visible &&
!LLLandmarkActions::landmarkAlreadyExists());
+ // STORM-411
+ // Creating landmarks for remote locations is impossible.
+ // So hide menu item "Make a Landmark" in "Teleport History Profile" panel.
+ menu->setItemVisible("landmark", mPlaceInfoType != TELEPORT_HISTORY_INFO_TYPE);
+ menu->arrangeAndClear();
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE && mLandmarkMenu != NULL)
{
@@ -783,16 +779,7 @@ void LLPanelPlaces::onOverflowButtonClicked()
return;
}
- if (!menu->toggleVisibility())
- return;
-
- if (menu->getButtonRect().isEmpty())
- {
- menu->setButtonRect(mOverflowBtn);
- }
- menu->updateParent(LLMenuGL::sMenuContainer);
- LLRect rect = mOverflowBtn->getRect();
- LLMenuGL::showPopup(this, menu, rect.mRight, rect.mTop);
+ mOverflowBtn->setMenu(menu, LLMenuButton::MP_TOP_RIGHT);
}
void LLPanelPlaces::onProfileButtonClicked()
@@ -1137,13 +1124,6 @@ void LLPanelPlaces::updateVerbs()
{
mTeleportBtn->setEnabled(have_3d_pos);
}
-
- // Do not enable landmark info Back button when we are waiting
- // for newly created landmark to load.
- if (!is_create_landmark_visible)
- {
- mLandmarkInfoBackBtn->setEnabled(TRUE);
- }
}
else
{
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index c3b2ab806f..b335f88a48 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -47,6 +47,7 @@ class LLPlacesParcelObserver;
class LLRemoteParcelInfoObserver;
class LLTabContainer;
class LLToggleableMenu;
+class LLMenuButton;
typedef std::pair<LLUUID, std::string> folder_pair_t;
@@ -116,14 +117,13 @@ private:
LLToggleableMenu* mLandmarkMenu;
LLButton* mPlaceProfileBackBtn;
- LLButton* mLandmarkInfoBackBtn;
LLButton* mTeleportBtn;
LLButton* mShowOnMapBtn;
LLButton* mEditBtn;
LLButton* mSaveBtn;
LLButton* mCancelBtn;
LLButton* mCloseBtn;
- LLButton* mOverflowBtn;
+ LLMenuButton* mOverflowBtn;
LLButton* mPlaceInfoBtn;
LLPlacesInventoryObserver* mInventoryObserver;
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index b04971f980..82ff6c3487 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -59,6 +59,7 @@
#include "llvovolume.h"
#include "llweb.h"
#include "llwindow.h"
+#include "llwindowshade.h"
#include "llfloatertools.h" // to enable hide if build tools are up
// Functions pulled from pipeline.cpp
@@ -90,7 +91,9 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
mTargetObjectNormal(LLVector3::zero),
mZoomObjectID(LLUUID::null),
mZoomObjectFace(0),
- mVolumeSliderVisible(0)
+ mVolumeSliderVisible(0),
+ mWindowShade(NULL),
+ mHideImmediately(false)
{
mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
@@ -205,6 +208,11 @@ BOOL LLPanelPrimMediaControls::postBuild()
mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+ gAgent.setMouselookModeInCallback(boost::bind(&LLPanelPrimMediaControls::onMouselookModeIn, this));
+
+ LLWindowShade::Params window_shade_params;
+ window_shade_params.name = "window_shade";
+
mCurrentZoom = ZOOM_NONE;
// clicks on buttons do not remove keyboard focus from media
setIsChrome(TRUE);
@@ -519,7 +527,7 @@ void LLPanelPrimMediaControls::updateShape()
if(LLPluginClassMediaOwner::MEDIA_LOADING == media_plugin->getStatus())
{
mMediaProgressPanel->setVisible(true);
- mMediaProgressBar->setPercent(media_plugin->getProgressPercent());
+ mMediaProgressBar->setValue(media_plugin->getProgressPercent());
}
else
{
@@ -620,12 +628,12 @@ void LLPanelPrimMediaControls::updateShape()
// convert screenspace bbox to pixels (in screen coords)
LLRect window_rect = gViewerWindow->getWorldViewRectScaled();
LLCoordGL screen_min;
- screen_min.mX = llround((F32)window_rect.getWidth() * (min.mV[VX] + 1.f) * 0.5f);
- screen_min.mY = llround((F32)window_rect.getHeight() * (min.mV[VY] + 1.f) * 0.5f);
+ screen_min.mX = llround((F32)window_rect.mLeft + (F32)window_rect.getWidth() * (min.mV[VX] + 1.f) * 0.5f);
+ screen_min.mY = llround((F32)window_rect.mBottom + (F32)window_rect.getHeight() * (min.mV[VY] + 1.f) * 0.5f);
LLCoordGL screen_max;
- screen_max.mX = llround((F32)window_rect.getWidth() * (max.mV[VX] + 1.f) * 0.5f);
- screen_max.mY = llround((F32)window_rect.getHeight() * (max.mV[VY] + 1.f) * 0.5f);
+ screen_max.mX = llround((F32)window_rect.mLeft + (F32)window_rect.getWidth() * (max.mV[VX] + 1.f) * 0.5f);
+ screen_max.mY = llround((F32)window_rect.mBottom + (F32)window_rect.getHeight() * (max.mV[VY] + 1.f) * 0.5f);
// grow panel so that screenspace bounding box fits inside "media_region" element of panel
LLRect media_panel_rect;
@@ -698,27 +706,41 @@ void LLPanelPrimMediaControls::updateShape()
/*virtual*/
void LLPanelPrimMediaControls::draw()
{
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+ if (impl)
+ {
+ LLNotificationPtr notification = impl->getCurrentNotification();
+ if (notification != mActiveNotification)
+ {
+ mActiveNotification = notification;
+ if (notification)
+ {
+ showNotification(notification);
+ }
+ else
+ {
+ hideNotification();
+ }
+ }
+ }
+
F32 alpha = getDrawContext().mAlpha;
- if(mFadeTimer.getStarted())
+ if(mHideImmediately)
+ {
+ //hide this panel
+ clearFaceOnFade();
+
+ mHideImmediately = false;
+ }
+ else if(mFadeTimer.getStarted())
{
F32 time = mFadeTimer.getElapsedTimeF32();
alpha *= llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
if(time >= mControlFadeTime)
{
- if(mClearFaceOnFade)
- {
- // Hiding this object makes scroll events go missing after it fades out
- // (see DEV-41755 for a full description of the train wreck).
- // Only hide the controls when we're untargeting.
- setVisible(FALSE);
-
- mClearFaceOnFade = false;
- mVolumeSliderVisible = 0;
- mTargetImplID = LLUUID::null;
- mTargetObjectID = LLUUID::null;
- mTargetObjectFace = 0;
- }
+ //hide this panel
+ clearFaceOnFade();
}
}
@@ -1295,3 +1317,62 @@ bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible()
{
return mVolumeSliderVisible > 0;
}
+
+
+void LLPanelPrimMediaControls::clearFaceOnFade()
+{
+ if(mClearFaceOnFade)
+ {
+ // Hiding this object makes scroll events go missing after it fades out
+ // (see DEV-41755 for a full description of the train wreck).
+ // Only hide the controls when we're untargeting.
+ setVisible(FALSE);
+
+ mClearFaceOnFade = false;
+ mVolumeSliderVisible = 0;
+ mTargetImplID = LLUUID::null;
+ mTargetObjectID = LLUUID::null;
+ mTargetObjectFace = 0;
+ }
+}
+
+void LLPanelPrimMediaControls::onMouselookModeIn()
+{
+ LLViewerMediaFocus::getInstance()->clearHover();
+ mHideImmediately = true;
+}
+
+void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify)
+{
+ delete mWindowShade;
+ LLWindowShade::Params params;
+ params.rect = mMediaRegion->getLocalRect();
+ params.follows.flags = FOLLOWS_ALL;
+ params.notification = notify;
+
+ //HACK: don't hardcode this
+ if (notify->getIcon() == "Popup_Caution")
+ {
+ params.bg_image.name = "Yellow_Gradient";
+ params.text_color = LLColor4::black;
+ }
+ else
+ {
+ //HACK: make this a property of the notification itself, "cancellable"
+ params.can_close = false;
+ params.text_color.control = "LabelTextColor";
+ }
+
+ mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
+
+ mMediaRegion->addChild(mWindowShade);
+ mWindowShade->show();
+}
+
+void LLPanelPrimMediaControls::hideNotification()
+{
+ if (mWindowShade)
+ {
+ mWindowShade->hide();
+ }
+}
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 3ec24f0e24..66956181f2 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -29,6 +29,7 @@
#include "llpanel.h"
#include "llviewermedia.h"
+#include "llnotificationptr.h"
class LLButton;
class LLCoordWindow;
@@ -37,6 +38,7 @@ class LLLayoutStack;
class LLProgressBar;
class LLSliderCtrl;
class LLViewerMediaImpl;
+class LLWindowShade;
class LLPanelPrimMediaControls : public LLPanel
{
@@ -54,6 +56,10 @@ public:
void updateShape();
bool isMouseOver();
+ void showNotification(LLNotificationPtr notify);
+ void hideNotification();
+
+
enum EZoomLevel
{
ZOOM_NONE = 0,
@@ -131,7 +137,11 @@ private:
LLPluginClassMedia* getTargetMediaPlugin();
private:
-
+
+ void clearFaceOnFade();
+
+ void onMouselookModeIn();
+
LLView *mMediaRegion;
LLUICtrl *mBackCtrl;
LLUICtrl *mFwdCtrl;
@@ -162,6 +172,7 @@ private:
LLUICtrl *mRightBookend;
LLUIImage* mBackgroundImage;
LLUIImage* mVolumeSliderBackgroundImage;
+ LLWindowShade* mWindowShade;
F32 mSkipStep;
S32 mMinWidth;
S32 mMinHeight;
@@ -179,6 +190,7 @@ private:
bool mPauseFadeout;
bool mUpdateSlider;
bool mClearFaceOnFade;
+ bool mHideImmediately;
LLMatrix4 mLastCameraMat;
EZoomLevel mCurrentZoom;
@@ -204,6 +216,8 @@ private:
S32 mZoomObjectFace;
S32 mVolumeSliderVisible;
+
+ LLNotificationPtr mActiveNotification;
};
#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 4e63563979..fd5c3362bb 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -31,12 +31,54 @@
#include "llavataractions.h"
#include "llfloaterreg.h"
#include "llcommandhandler.h"
+#include "llnotificationsutil.h"
#include "llpanelpicks.h"
#include "lltabcontainer.h"
+#include "llviewercontrol.h"
+#include "llviewernetwork.h"
static const std::string PANEL_PICKS = "panel_picks";
static const std::string PANEL_PROFILE = "panel_profile";
+std::string getProfileURL(const std::string& agent_name)
+{
+ std::string url;
+
+ if (LLGridManager::getInstance()->isInProductionGrid())
+ {
+ url = gSavedSettings.getString("WebProfileURL");
+ }
+ else
+ {
+ url = gSavedSettings.getString("WebProfileNonProductionURL");
+ }
+ LLSD subs;
+ subs["AGENT_NAME"] = agent_name;
+ url = LLWeb::expandURLSubstitutions(url,subs);
+ LLStringUtil::toLower(url);
+ return url;
+}
+
+class LLProfileHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { }
+
+ bool handle(const LLSD& params, const LLSD& query_map,
+ LLMediaCtrl* web)
+ {
+ if (params.size() < 1) return false;
+ std::string agent_name = params[0];
+ llinfos << "Profile, agent_name " << agent_name << llendl;
+ std::string url = getProfileURL(agent_name);
+ LLWeb::loadWebURLInternal(url);
+
+ return true;
+ }
+};
+LLProfileHandler gProfileHandler;
+
class LLAgentHandler : public LLCommandHandler
{
public:
@@ -74,6 +116,12 @@ public:
if (verb == "pay")
{
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAvatarPay"))
+ {
+ LLNotificationsUtil::add("NoAvatarPay", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
LLAvatarActions::pay(avatar_id);
return true;
}
@@ -114,11 +162,109 @@ public:
LLAgentHandler gAgentHandler;
+//-- LLPanelProfile::ChildStack begins ----------------------------------------
+LLPanelProfile::ChildStack::ChildStack()
+: mParent(NULL)
+{
+}
+
+void LLPanelProfile::ChildStack::setParent(LLPanel* parent)
+{
+ llassert_always(parent != NULL);
+ mParent = parent;
+}
+
+/// Save current parent's child views and remove them from the child list.
+bool LLPanelProfile::ChildStack::push()
+{
+ view_list_t vlist = *mParent->getChildList();
+
+ for (view_list_t::const_iterator it = vlist.begin(); it != vlist.end(); ++it)
+ {
+ LLView* viewp = *it;
+ mParent->removeChild(viewp);
+ }
+
+ mStack.push_back(vlist);
+ dump();
+ return true;
+}
+
+/// Restore saved children (adding them back to the child list).
+bool LLPanelProfile::ChildStack::pop()
+{
+ if (mStack.size() == 0)
+ {
+ llwarns << "Empty stack" << llendl;
+ llassert(mStack.size() == 0);
+ return false;
+ }
+
+ view_list_t& top = mStack.back();
+ for (view_list_t::const_iterator it = top.begin(); it != top.end(); ++it)
+ {
+ LLView* viewp = *it;
+ mParent->addChild(viewp);
+ }
+
+ mStack.pop_back();
+ dump();
+ return true;
+}
+
+/// Temporarily add all saved children back.
+void LLPanelProfile::ChildStack::preParentReshape()
+{
+ mSavedStack = mStack;
+ while(mStack.size() > 0)
+ {
+ pop();
+ }
+}
+
+/// Add the temporarily saved children back.
+void LLPanelProfile::ChildStack::postParentReshape()
+{
+ mStack = mSavedStack;
+ mSavedStack = stack_t();
+
+ for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it)
+ {
+ const view_list_t& vlist = (*stack_it);
+ for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it)
+ {
+ LLView* viewp = *list_it;
+ lldebugs << "removing " << viewp->getName() << llendl;
+ mParent->removeChild(viewp);
+ }
+ }
+}
+
+void LLPanelProfile::ChildStack::dump()
+{
+ unsigned lvl = 0;
+ lldebugs << "child stack dump:" << llendl;
+ for (stack_t::const_iterator stack_it = mStack.begin(); stack_it != mStack.end(); ++stack_it, ++lvl)
+ {
+ std::ostringstream dbg_line;
+ dbg_line << "lvl #" << lvl << ":";
+ const view_list_t& vlist = (*stack_it);
+ for (view_list_t::const_iterator list_it = vlist.begin(); list_it != vlist.end(); ++list_it)
+ {
+ dbg_line << " " << (*list_it)->getName();
+ }
+ lldebugs << dbg_line.str() << llendl;
+ }
+}
+
+//-- LLPanelProfile::ChildStack ends ------------------------------------------
+
LLPanelProfile::LLPanelProfile()
: LLPanel()
, mTabCtrl(NULL)
, mAvatarId(LLUUID::null)
{
+ mChildStack.setParent(this);
}
BOOL LLPanelProfile::postBuild()
@@ -136,6 +282,15 @@ BOOL LLPanelProfile::postBuild()
return TRUE;
}
+// virtual
+void LLPanelProfile::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ // Temporarily add saved children back and reshape them.
+ mChildStack.preParentReshape();
+ LLPanel::reshape(width, height, called_from_parent);
+ mChildStack.postParentReshape();
+}
+
void LLPanelProfile::onOpen(const LLSD& key)
{
// open the desired panel
@@ -174,10 +329,39 @@ void LLPanelProfile::onOpen(const LLSD& key)
picks->openClassifiedInfo(params);
}
}
+ else if (panel == "edit_classified")
+ {
+ LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]);
+ if (picks)
+ {
+ LLSD params = key;
+ params.erase("show_tab_panel");
+ params.erase("open_tab_name");
+ picks->openClassifiedEdit(params);
+ }
+ }
+ else if (panel == "create_pick")
+ {
+ LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]);
+ if (picks)
+ {
+ picks->createNewPick();
+ }
+ }
+ else if (panel == "edit_pick")
+ {
+ LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]);
+ if (picks)
+ {
+ LLSD params = key;
+ params.erase("show_tab_panel");
+ params.erase("open_tab_name");
+ picks->openPickEdit(params);
+ }
+ }
}
}
-//*TODO redo panel toggling
void LLPanelProfile::togglePanel(LLPanel* panel, const LLSD& key)
{
// TRUE - we need to open/expand "panel"
@@ -204,19 +388,12 @@ void LLPanelProfile::onTabSelected(const LLSD& param)
}
}
-void LLPanelProfile::setAllChildrenVisible(BOOL visible)
-{
- const child_list_t* child_list = getChildList();
- child_list_const_iter_t child_it = child_list->begin();
- for (; child_it != child_list->end(); ++child_it)
- {
- LLView* viewp = *child_it;
- viewp->setVisible(visible);
- }
-}
-
void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params)
{
+ // Hide currently visible panel (STORM-690).
+ mChildStack.push();
+
+ // Add the panel or bring it to front.
if (panel->getParent() != this)
{
addChild(panel);
@@ -227,7 +404,7 @@ void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params)
}
panel->setVisible(TRUE);
-
+ panel->setFocus(TRUE); // prevent losing focus by the floater
panel->onOpen(params);
LLRect new_rect = getRect();
@@ -243,6 +420,20 @@ void LLPanelProfile::closePanel(LLPanel* panel)
if (panel->getParent() == this)
{
removeChild(panel);
+
+ // Make the underlying panel visible.
+ mChildStack.pop();
+
+ // Prevent losing focus by the floater
+ const child_list_t* child_list = getChildList();
+ if (child_list->size() > 0)
+ {
+ child_list->front()->setFocus(TRUE);
+ }
+ else
+ {
+ llwarns << "No underlying panel to focus." << llendl;
+ }
}
}
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index d2bcee8076..fca359f51e 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -32,6 +32,8 @@
class LLTabContainer;
+std::string getProfileURL(const std::string& agent_name);
+
/**
* Base class for Profile View and My Profile.
*/
@@ -41,7 +43,7 @@ class LLPanelProfile : public LLPanel
public:
/*virtual*/ BOOL postBuild();
-
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void onOpen(const LLSD& key);
virtual void togglePanel(LLPanel*, const LLSD& key = LLSD());
@@ -58,8 +60,6 @@ protected:
virtual void onTabSelected(const LLSD& param);
- virtual void setAllChildrenVisible(BOOL visible);
-
LLTabContainer* getTabCtrl() { return mTabCtrl; }
const LLUUID& getAvatarId() { return mAvatarId; }
@@ -72,8 +72,34 @@ protected:
private:
+ //-- ChildStack begins ----------------------------------------------------
+ class ChildStack
+ {
+ LOG_CLASS(LLPanelProfile::ChildStack);
+ public:
+ ChildStack();
+ void setParent(LLPanel* parent);
+
+ bool push();
+ bool pop();
+ void preParentReshape();
+ void postParentReshape();
+
+ private:
+ void dump();
+
+ typedef LLView::child_list_t view_list_t;
+ typedef std::list<view_list_t> stack_t;
+
+ stack_t mStack;
+ stack_t mSavedStack;
+ LLPanel* mParent;
+ };
+ //-- ChildStack ends ------------------------------------------------------
+
LLTabContainer* mTabCtrl;
profile_tabs_t mTabContainer;
+ ChildStack mChildStack;
LLUUID mAvatarId;
};
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 9b8167b15a..9b35e78134 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"
@@ -179,9 +181,11 @@ void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
void LLTeleportHistoryFlatItem::updateTitle()
{
+ static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
+
LLTextUtil::textboxSetHighlightedVal(
mTitle,
- LLStyle::Params(),
+ LLStyle::Params().color(sFgColor),
mRegionName,
mHighlight);
}
@@ -375,7 +379,8 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
mHistoryAccordion(NULL),
mAccordionTabMenu(NULL),
mLastSelectedFlatlList(NULL),
- mLastSelectedItemIndex(-1)
+ mLastSelectedItemIndex(-1),
+ mMenuGearButton(NULL)
{
buildFromFile( "panel_teleport_history.xml");
}
@@ -439,8 +444,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 +451,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 +993,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/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp
index a9ca7314ce..30949f8f02 100644
--- a/indra/newview/llpaneltopinfobar.cpp
+++ b/indra/newview/llpaneltopinfobar.cpp
@@ -38,6 +38,7 @@
#include "llsidetray.h"
#include "llslurl.h"
#include "llstatusbar.h"
+#include "lltrans.h"
#include "llviewercontrol.h"
#include "llviewerinventory.h"
#include "llviewermenu.h"
@@ -102,6 +103,13 @@ void LLPanelTopInfoBar::initParcelIcons()
mParcelIcon[SCRIPTS_ICON] = getChild<LLIconCtrl>("scripts_icon");
mParcelIcon[DAMAGE_ICON] = getChild<LLIconCtrl>("damage_icon");
+ mParcelIcon[VOICE_ICON]->setToolTip(LLTrans::getString("LocationCtrlVoiceTooltip"));
+ mParcelIcon[FLY_ICON]->setToolTip(LLTrans::getString("LocationCtrlFlyTooltip"));
+ mParcelIcon[PUSH_ICON]->setToolTip(LLTrans::getString("LocationCtrlPushTooltip"));
+ mParcelIcon[BUILD_ICON]->setToolTip(LLTrans::getString("LocationCtrlBuildTooltip"));
+ mParcelIcon[SCRIPTS_ICON]->setToolTip(LLTrans::getString("LocationCtrlScriptsTooltip"));
+ mParcelIcon[DAMAGE_ICON]->setToolTip(LLTrans::getString("LocationCtrlDamageTooltip"));
+
mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, VOICE_ICON));
mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, FLY_ICON));
mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLPanelTopInfoBar::onParcelIconClick, this, PUSH_ICON));
@@ -129,6 +137,7 @@ BOOL LLPanelTopInfoBar::postBuild()
{
mInfoBtn = getChild<LLButton>("place_info_btn");
mInfoBtn->setClickedCallback(boost::bind(&LLPanelTopInfoBar::onInfoButtonClicked, this));
+ mInfoBtn->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip"));
mParcelInfoText = getChild<LLTextBox>("parcel_info_text");
mDamageText = getChild<LLTextBox>("damage_text");
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/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
new file mode 100644
index 0000000000..73de1cef3f
--- /dev/null
+++ b/indra/newview/llphysicsmotion.cpp
@@ -0,0 +1,698 @@
+/**
+ * @file llphysicsmotion.cpp
+ * @brief Implementation of LLPhysicsMotion class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+#include "m3math.h"
+#include "v3dmath.h"
+
+#include "llphysicsmotion.h"
+#include "llcharacter.h"
+#include "llviewercontrol.h"
+#include "llviewervisualparam.h"
+#include "llvoavatarself.h"
+
+typedef std::map<std::string, std::string> controller_map_t;
+typedef std::map<std::string, F32> default_controller_map_t;
+
+#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f;
+
+inline F64 llsgn(const F64 a)
+{
+ if (a >= 0)
+ return 1;
+ return -1;
+}
+
+/*
+ At a high level, this works by setting temporary parameters that are not stored
+ in the avatar's list of params, and are not conveyed to other users. We accomplish
+ this by creating some new temporary driven params inside avatar_lad that are then driven
+ by the actual params that the user sees and sets. For example, in the old system,
+ the user sets a param called breast bouyancy, which controls the Z value of the breasts.
+ In our new system, the user still sets the breast bouyancy, but that param is redefined
+ as a driver param so that affects a new temporary driven param that the bounce is applied
+ to.
+*/
+
+class LLPhysicsMotion
+{
+public:
+ /*
+ param_user_name: The param (if any) that the user sees and controls. This is what
+ the particular property would look like without physics. For example, it may be
+ the breast gravity. This param's value should will not be altered, and is only
+ used as a reference point for the rest position of the body party. This is usually
+ a driver param and the param(s) that physics is altering are the driven params.
+
+ param_driven_name: The param whose value is actually set by the physics. If you
+ leave this blank (which should suffice normally), the physics will assume that
+ param_user_name is a driver param and will set the params that the driver is
+ in charge of (i.e. the "driven" params).
+
+ joint_name: The joint that the body part is attached to. The joint is
+ used to determine the orientation (rotation) of the body part.
+
+ character: The avatar that this physics affects.
+
+ motion_direction_vec: The direction (in world coordinates) that determines the
+ motion. For example, (0,0,1) is up-down, and means that up-down motion is what
+ determines how this joint moves.
+
+ controllers: The various settings (e.g. spring force, mass) that determine how
+ the body part behaves.
+ */
+ LLPhysicsMotion(const std::string &param_user_name,
+ const std::string &param_driven_name,
+ const std::string &joint_name,
+ LLCharacter *character,
+ const LLVector3 &motion_direction_vec,
+ const controller_map_t &controllers) :
+ mParamUserName(param_user_name),
+ mParamDrivenName(param_driven_name),
+ mJointName(joint_name),
+ mMotionDirectionVec(motion_direction_vec),
+ mParamUser(NULL),
+ mParamDriven(NULL),
+
+ mParamControllers(controllers),
+ mCharacter(character),
+ mLastTime(0),
+ mPosition_local(0),
+ mVelocityJoint_local(0),
+ mPositionLastUpdate_local(0)
+ {
+ mJointState = new LLJointState;
+ }
+
+ BOOL initialize();
+
+ ~LLPhysicsMotion() {}
+
+ BOOL onUpdate(F32 time);
+
+ LLPointer<LLJointState> getJointState()
+ {
+ return mJointState;
+ }
+protected:
+ F32 getParamValue(const std::string& controller_key)
+ {
+ const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key);
+ if (entry == mParamControllers.end())
+ {
+ return sDefaultController[controller_key];
+ }
+ const std::string& param_name = (*entry).second.c_str();
+ return mCharacter->getVisualParamWeight(param_name.c_str());
+ }
+ void setParamValue(LLViewerVisualParam *param,
+ const F32 new_value_local);
+
+ F32 toLocal(const LLVector3 &world);
+ F32 calculateVelocity_local(const F32 time_delta);
+ F32 calculateAcceleration_local(F32 velocity_local,
+ const F32 time_delta);
+private:
+ const std::string mParamDrivenName;
+ const std::string mParamUserName;
+ const LLVector3 mMotionDirectionVec;
+ const std::string mJointName;
+
+ F32 mPosition_local;
+ F32 mVelocityJoint_local; // How fast the joint is moving
+ F32 mAccelerationJoint_local; // Acceleration on the joint
+
+ F32 mVelocity_local; // How fast the param is moving
+ F32 mPositionLastUpdate_local;
+ LLVector3 mPosition_world;
+
+ LLViewerVisualParam *mParamUser;
+ LLViewerVisualParam *mParamDriven;
+ const controller_map_t mParamControllers;
+
+ LLPointer<LLJointState> mJointState;
+ LLCharacter *mCharacter;
+
+ F32 mLastTime;
+
+ static default_controller_map_t sDefaultController;
+};
+
+default_controller_map_t initDefaultController()
+{
+ default_controller_map_t controller;
+ controller["Mass"] = 0.2f;
+ controller["Smoothing"] = 2.0f;
+ controller["Gravity"] = 0.0f;
+ controller["Damping"] = .05f;
+ controller["Drag"] = 0.15f;
+ controller["MaxSpeed"] = 0.1f;
+ controller["Spring"] = 0.1f;
+ controller["Gain"] = 10.0f;
+ return controller;
+}
+
+default_controller_map_t LLPhysicsMotion::sDefaultController = initDefaultController();
+
+BOOL LLPhysicsMotion::initialize()
+{
+ if (!mJointState->setJoint(mCharacter->getJoint(mJointName.c_str())))
+ return FALSE;
+ mJointState->setUsage(LLJointState::ROT);
+
+ mParamUser = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamUserName.c_str());
+ if (mParamDrivenName != "")
+ mParamDriven = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamDrivenName.c_str());
+ if (mParamUser == NULL)
+ {
+ llinfos << "Failure reading in [ " << mParamUserName << " ]" << llendl;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+LLPhysicsMotionController::LLPhysicsMotionController(const LLUUID &id) :
+ LLMotion(id),
+ mCharacter(NULL)
+{
+ mName = "breast_motion";
+}
+
+LLPhysicsMotionController::~LLPhysicsMotionController()
+{
+ for (motion_vec_t::iterator iter = mMotions.begin();
+ iter != mMotions.end();
+ ++iter)
+ {
+ delete (*iter);
+ }
+}
+
+BOOL LLPhysicsMotionController::onActivate()
+{
+ return TRUE;
+}
+
+void LLPhysicsMotionController::onDeactivate()
+{
+}
+
+LLMotion::LLMotionInitStatus LLPhysicsMotionController::onInitialize(LLCharacter *character)
+{
+ mCharacter = character;
+
+ mMotions.clear();
+
+ // Breast Cleavage
+ {
+ controller_map_t controller;
+ controller["Mass"] = "Breast_Physics_Mass";
+ controller["Smoothing"] = "Breast_Physics_Smoothing";
+ controller["Gravity"] = "Breast_Physics_Gravity";
+ controller["Damping"] = "Breast_Physics_InOut_Damping";
+ controller["Drag"] = "Breast_Physics_InOut_Drag";
+ controller["MaxSpeed"] = "Breast_Physics_InOut_Max_Velocity";
+ controller["Spring"] = "Breast_Physics_InOut_Spring";
+ controller["Gain"] = "Breast_Physics_InOut_Gain";
+ LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_InOut_Controller",
+ "",
+ "mChest",
+ character,
+ LLVector3(-1,0,0),
+ controller);
+ if (!motion->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion);
+ }
+
+ // Breast Bounce
+ {
+ controller_map_t controller;
+ controller["Mass"] = "Breast_Physics_Mass";
+ controller["Smoothing"] = "Breast_Physics_Smoothing";
+ controller["Gravity"] = "Breast_Physics_Gravity";
+ controller["Damping"] = "Breast_Physics_UpDown_Damping";
+ controller["Drag"] = "Breast_Physics_UpDown_Drag";
+ controller["MaxSpeed"] = "Breast_Physics_UpDown_Max_Velocity";
+ controller["Spring"] = "Breast_Physics_UpDown_Spring";
+ controller["Gain"] = "Breast_Physics_UpDown_Gain";
+ LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_UpDown_Controller",
+ "",
+ "mChest",
+ character,
+ LLVector3(0,0,1),
+ controller);
+ if (!motion->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion);
+ }
+
+ // Butt Bounce
+ {
+ controller_map_t controller;
+ controller["Mass"] = "Butt_Physics_Mass";
+ controller["Smoothing"] = "Butt_Physics_Smoothing";
+ controller["Gravity"] = "Butt_Physics_Gravity";
+ controller["Damping"] = "Butt_Physics_UpDown_Damping";
+ controller["Drag"] = "Butt_Physics_UpDown_Drag";
+ controller["MaxSpeed"] = "Butt_Physics_UpDown_Max_Velocity";
+ controller["Spring"] = "Butt_Physics_UpDown_Spring";
+ controller["Gain"] = "Butt_Physics_UpDown_Gain";
+ LLPhysicsMotion *motion = new LLPhysicsMotion("Butt_Physics_UpDown_Controller",
+ "",
+ "mPelvis",
+ character,
+ LLVector3(0,0,1),
+ controller);
+ if (!motion->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion);
+ }
+
+ // Butt LeftRight
+ {
+ controller_map_t controller;
+ controller["Mass"] = "Butt_Physics_Mass";
+ controller["Smoothing"] = "Butt_Physics_Smoothing";
+ controller["Gravity"] = "Butt_Physics_Gravity";
+ controller["Damping"] = "Butt_Physics_LeftRight_Damping";
+ controller["Drag"] = "Butt_Physics_LeftRight_Drag";
+ controller["MaxSpeed"] = "Butt_Physics_LeftRight_Max_Velocity";
+ controller["Spring"] = "Butt_Physics_LeftRight_Spring";
+ controller["Gain"] = "Butt_Physics_LeftRight_Gain";
+ LLPhysicsMotion *motion = new LLPhysicsMotion("Butt_Physics_LeftRight_Controller",
+ "",
+ "mPelvis",
+ character,
+ LLVector3(0,1,0),
+ controller);
+ if (!motion->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion);
+ }
+
+ // Belly Bounce
+ {
+ controller_map_t controller;
+ controller["Mass"] = "Belly_Physics_Mass";
+ controller["Smoothing"] = "Belly_Physics_Smoothing";
+ controller["Gravity"] = "Belly_Physics_Gravity";
+ controller["Damping"] = "Belly_Physics_UpDown_Damping";
+ controller["Drag"] = "Belly_Physics_UpDown_Drag";
+ controller["MaxSpeed"] = "Belly_Physics_UpDown_Max_Velocity";
+ controller["Spring"] = "Belly_Physics_UpDown_Spring";
+ controller["Gain"] = "Belly_Physics_UpDown_Gain";
+ LLPhysicsMotion *motion = new LLPhysicsMotion("Belly_Physics_UpDown_Controller",
+ "",
+ "mPelvis",
+ character,
+ LLVector3(0,0,-1),
+ controller);
+ if (!motion->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void LLPhysicsMotionController::addMotion(LLPhysicsMotion *motion)
+{
+ addJointState(motion->getJointState());
+ mMotions.push_back(motion);
+}
+
+F32 LLPhysicsMotionController::getMinPixelArea()
+{
+ return MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION;
+}
+
+// Local space means "parameter space".
+F32 LLPhysicsMotion::toLocal(const LLVector3 &world)
+{
+ LLJoint *joint = mJointState->getJoint();
+ const LLQuaternion rotation_world = joint->getWorldRotation();
+
+ LLVector3 dir_world = mMotionDirectionVec * rotation_world;
+ dir_world.normalize();
+ return world * dir_world;
+}
+
+F32 LLPhysicsMotion::calculateVelocity_local(const F32 time_delta)
+{
+ LLJoint *joint = mJointState->getJoint();
+ const LLVector3 position_world = joint->getWorldPosition();
+ const LLQuaternion rotation_world = joint->getWorldRotation();
+ const LLVector3 last_position_world = mPosition_world;
+ const LLVector3 velocity_world = (position_world-last_position_world) / time_delta;
+ const F32 velocity_local = toLocal(velocity_world);
+ return velocity_local;
+}
+
+F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local,
+ const F32 time_delta)
+{
+ const F32 smoothing = getParamValue("Smoothing");
+ const F32 acceleration_local = velocity_local - mVelocityJoint_local;
+
+ const F32 smoothed_acceleration_local =
+ acceleration_local * 1.0/smoothing +
+ mAccelerationJoint_local * (smoothing-1.0)/smoothing;
+
+ return smoothed_acceleration_local;
+}
+
+BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask)
+{
+ // Skip if disabled globally.
+ if (!gSavedSettings.getBOOL("AvatarPhysics"))
+ {
+ return TRUE;
+ }
+
+ BOOL update_visuals = FALSE;
+ for (motion_vec_t::iterator iter = mMotions.begin();
+ iter != mMotions.end();
+ ++iter)
+ {
+ LLPhysicsMotion *motion = (*iter);
+ update_visuals |= motion->onUpdate(time);
+ }
+
+ if (update_visuals)
+ mCharacter->updateVisualParams();
+
+ return TRUE;
+}
+
+
+// Return TRUE if character has to update visual params.
+BOOL LLPhysicsMotion::onUpdate(F32 time)
+{
+ // static FILE *mFileWrite = fopen("c:\\temp\\avatar_data.txt","w");
+
+ if (!mParamUser)
+ return FALSE;
+
+ if (!mLastTime)
+ {
+ mLastTime = time;
+ return FALSE;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Get all parameters and settings
+ //
+
+ const F32 time_delta = time - mLastTime;
+ if (time_delta > 3.0 || time_delta <= 0.01)
+ {
+ mLastTime = time;
+ return FALSE;
+ }
+
+ // Higher LOD is better. This controls the granularity
+ // and frequency of updates for the motions.
+ const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor;
+ if (lod_factor == 0)
+ {
+ return TRUE;
+ }
+
+ LLJoint *joint = mJointState->getJoint();
+
+ const F32 behavior_mass = getParamValue("Mass");
+ const F32 behavior_gravity = getParamValue("Gravity");
+ const F32 behavior_spring = getParamValue("Spring");
+ const F32 behavior_gain = getParamValue("Gain");
+ const F32 behavior_damping = getParamValue("Damping");
+ const F32 behavior_drag = getParamValue("Drag");
+ const BOOL physics_test = gSavedSettings.getBOOL("AvatarPhysicsTest");
+
+ F32 behavior_maxspeed = getParamValue("MaxSpeed");
+ if (physics_test)
+ behavior_maxspeed = 100.0f;
+
+ if (behavior_maxspeed == 0)
+ return FALSE;
+
+ F32 position_current_local = llclamp(mPosition_local,
+ 0.0f,
+ 1.0f); // Normalized [0,1] range
+
+ // Normalize the param position to be from [0,1].
+ // We have to use normalized values because there may be more than one driven param,
+ // and each of these driven params may have its own range.
+ // This means we'll do all our calculations in normalized [0,1] local coordinates.
+ F32 position_user_local = mParamUser->getWeight();
+ position_user_local = (position_user_local - mParamUser->getMinWeight()) / (mParamUser->getMaxWeight() - mParamUser->getMinWeight());
+
+ //
+ // End parameters and settings
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate velocity and acceleration in parameter space.
+ //
+
+ const F32 velocity_joint_local = calculateVelocity_local(time_delta);
+ const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local, time_delta);
+
+ //
+ // End velocity and acceleration
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate the total force
+ //
+
+ // Spring force is a restoring force towards the original user-set breast position.
+ // F = kx
+ const F32 spring_length = position_current_local - position_user_local;
+ const F32 force_spring = -spring_length * behavior_spring;
+
+ // Acceleration is the force that comes from the change in velocity of the torso.
+ // F = ma
+ const F32 force_accel = behavior_gain * (acceleration_joint_local * behavior_mass);
+
+ // Gravity always points downward in world space.
+ // F = mg
+ const LLVector3 gravity_world(0,0,1);
+ const F32 force_gravity = behavior_gain * (toLocal(gravity_world) * behavior_gravity * behavior_mass);
+
+ // Damping is a restoring force that opposes the current velocity.
+ // F = -kv
+ const F32 force_damping = -behavior_damping * mVelocity_local;
+
+ // Drag is a force imparted by velocity (intuitively it is similar to wind resistance)
+ // F = .5kv^2
+ const F32 force_drag = .5*behavior_drag*velocity_joint_local*velocity_joint_local*llsgn(velocity_joint_local);
+
+ const F32 force_net = (force_accel +
+ force_gravity +
+ force_spring +
+ force_damping +
+ force_drag);
+
+ //
+ // End total force
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate new params
+ //
+
+ // Calculate the new acceleration based on the net force.
+ // a = F/m
+ const F32 acceleration_new_local = force_net / behavior_mass;
+ F32 velocity_new_local = mVelocity_local + acceleration_new_local;
+ velocity_new_local = llclamp(velocity_new_local,
+ -behavior_maxspeed, behavior_maxspeed);
+
+ // Temporary debugging setting to cause all avatars to move, for profiling purposes.
+ if (physics_test)
+ {
+ velocity_new_local = sin(time*4.0);
+ }
+ // Calculate the new parameters, or remain unchanged if max speed is 0.
+ const F32 position_new_local = (behavior_maxspeed != 0) ?
+ (position_current_local + velocity_new_local*time_delta) :
+ position_user_local;
+
+ // Zero out the velocity if the param is being pushed beyond its limits.
+ if (position_new_local < 0 || position_new_local > 1)
+ {
+ velocity_new_local = 0;
+ }
+
+ const F32 position_new_local_clamped = llclamp(position_new_local,
+ 0.0f,
+ 1.0f);
+
+ // Set the new param.
+ // If a specific param has been declared, then set that one.
+ // Otherwise, assume that the param is a driver param, and
+ // set the params that it drives.
+ if (mParamDriven)
+ {
+ setParamValue(mParamDriven,position_new_local_clamped);
+ }
+ else
+ {
+ LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamUser);
+ llassert_always(driver_param);
+ if (driver_param)
+ {
+ for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin();
+ iter != driver_param->mDriven.end();
+ ++iter)
+ {
+ LLDrivenEntry &entry = (*iter);
+ LLViewerVisualParam *driven_param = entry.mParam;
+ setParamValue(driven_param,position_new_local_clamped);
+ }
+ }
+ }
+
+ //
+ // End calculate new params
+ ////////////////////////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Conditionally update the visual params
+ //
+
+ // Updating the visual params (i.e. what the user sees) is fairly expensive.
+ // So only update if the params have changed enough, and also take into account
+ // the graphics LOD settings.
+
+ BOOL update_visuals = FALSE;
+
+ // For non-self, if the avatar is small enough visually, then don't update.
+ const F32 area_for_max_settings = 0.0;
+ const F32 area_for_min_settings = 1400.0;
+ const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor);
+ const F32 pixel_area = fsqrtf(mCharacter->getPixelArea());
+
+ const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(mCharacter) != NULL);
+ if ((pixel_area > area_for_this_setting) || is_self)
+ {
+ const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped);
+ const F32 min_delta = (1.01f-lod_factor)*0.4f;
+ if (llabs(position_diff_local) > min_delta)
+ {
+ update_visuals = TRUE;
+ mPositionLastUpdate_local = position_new_local;
+ }
+ }
+
+ //
+ // End update visual params
+ ////////////////////////////////////////////////////////////////////////////////
+
+ mVelocityJoint_local = velocity_joint_local;
+
+ mVelocity_local = velocity_new_local;
+ mAccelerationJoint_local = acceleration_joint_local;
+ mPosition_local = position_new_local;
+
+ mPosition_world = joint->getWorldPosition();
+ mLastTime = time;
+
+ /*
+ // Write out debugging info into a spreadsheet.
+ if (mFileWrite != NULL && is_self)
+ {
+ fprintf(mFileWrite,"%f\t%f\t%f \t\t%f \t\t%f\t%f\t%f\t \t\t%f\t%f\t%f\t%f\t%f \t\t%f\t%f\t%f\n",
+ position_new_local,
+ velocity_new_local,
+ acceleration_new_local,
+
+ time_delta,
+
+ mPosition_world[0],
+ mPosition_world[1],
+ mPosition_world[2],
+
+ force_net,
+ force_spring,
+ force_accel,
+ force_damping,
+ force_drag,
+
+ spring_length,
+ velocity_joint_local,
+ acceleration_joint_local
+ );
+ }
+ */
+
+ return update_visuals;
+}
+
+// Range of new_value_local is assumed to be [0 , 1] normalized.
+void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param,
+ F32 new_value_normalized)
+{
+ const F32 value_min_local = param->getMinWeight();
+ const F32 value_max_local = param->getMaxWeight();
+
+ const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_normalized;
+
+ mCharacter->setVisualParamWeight(param,
+ new_value_local,
+ FALSE);
+}
diff --git a/indra/newview/llphysicsmotion.h b/indra/newview/llphysicsmotion.h
new file mode 100644
index 0000000000..0c0087d269
--- /dev/null
+++ b/indra/newview/llphysicsmotion.h
@@ -0,0 +1,124 @@
+/**
+ * @file llphysicsmotion.h
+ * @brief Implementation of LLPhysicsMotion class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPHYSICSMOTIONCONTROLLER_H
+#define LL_LLPHYSICSMOTIONCONTROLLER_H
+
+//-----------------------------------------------------------------------------
+// Header files
+//-----------------------------------------------------------------------------
+#include "llmotion.h"
+#include "llframetimer.h"
+
+#define PHYSICS_MOTION_FADEIN_TIME 1.0f
+#define PHYSICS_MOTION_FADEOUT_TIME 1.0f
+
+class LLPhysicsMotion;
+
+//-----------------------------------------------------------------------------
+// class LLPhysicsMotion
+//-----------------------------------------------------------------------------
+class LLPhysicsMotionController :
+ public LLMotion
+{
+public:
+ // Constructor
+ LLPhysicsMotionController(const LLUUID &id);
+
+ // Destructor
+ virtual ~LLPhysicsMotionController();
+
+public:
+ //-------------------------------------------------------------------------
+ // functions to support MotionController and MotionRegistry
+ //-------------------------------------------------------------------------
+
+ // static constructor
+ // all subclasses must implement such a function and register it
+ static LLMotion *create(const LLUUID &id) { return new LLPhysicsMotionController(id); }
+
+public:
+ //-------------------------------------------------------------------------
+ // animation callbacks to be implemented by subclasses
+ //-------------------------------------------------------------------------
+
+ // motions must specify whether or not they loop
+ virtual BOOL getLoop() { return TRUE; }
+
+ // motions must report their total duration
+ virtual F32 getDuration() { return 0.0; }
+
+ // motions must report their "ease in" duration
+ virtual F32 getEaseInDuration() { return PHYSICS_MOTION_FADEIN_TIME; }
+
+ // motions must report their "ease out" duration.
+ virtual F32 getEaseOutDuration() { return PHYSICS_MOTION_FADEOUT_TIME; }
+
+ // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
+ virtual F32 getMinPixelArea();
+
+ // motions must report their priority
+ virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; }
+
+ virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; }
+
+ // run-time (post constructor) initialization,
+ // called after parameters have been set
+ // must return true to indicate success and be available for activation
+ virtual LLMotionInitStatus onInitialize(LLCharacter *character);
+
+ // called when a motion is activated
+ // must return TRUE to indicate success, or else
+ // it will be deactivated
+ virtual BOOL onActivate();
+
+ // called per time step
+ // must return TRUE while it is active, and
+ // must return FALSE when the motion is completed.
+ virtual BOOL onUpdate(F32 time, U8* joint_mask);
+
+ // called when a motion is deactivated
+ virtual void onDeactivate();
+
+ LLCharacter* getCharacter() { return mCharacter; }
+
+protected:
+ void addMotion(LLPhysicsMotion *motion);
+private:
+ LLCharacter* mCharacter;
+
+ typedef std::vector<LLPhysicsMotion *> motion_vec_t;
+ motion_vec_t mMotions;
+};
+
+#endif // LL_LLPHYSICSMOTION_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/llpolymesh.cpp b/indra/newview/llpolymesh.cpp
index 363b0b8e9d..6d6fb2fa0e 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/newview/llpolymesh.cpp
@@ -46,6 +46,10 @@
extern LLControlGroup gSavedSettings; // read only
+LLPolyMorphData *clone_morph_param(const LLPolyMorphData *src_data,
+ const LLVector3 &direction,
+ const std::string &name);
+
//-----------------------------------------------------------------------------
// Global table of loaded LLPolyMeshes
//-----------------------------------------------------------------------------
@@ -602,6 +606,40 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName )
}
mMorphData.insert(morph_data);
+
+ if (!strcmp(morphName, "Big_Belly_Torso"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.03f),
+ "Belly_Physics_Torso_UpDown_Driven"));
+ }
+
+ if (!strcmp(morphName, "Big_Belly_Legs"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.03f),
+ "Belly_Physics_Legs_UpDown_Driven"));
+ }
+
+ if (!strcmp(morphName, "skirt_belly"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.03f),
+ "Belly_Physics_Skirt_UpDown_Driven"));
+ }
+
+ if (!strcmp(morphName, "Small_Butt"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.015f),
+ "Butt_Physics_UpDown_Driven"));
+ }
+ if (!strcmp(morphName, "Small_Butt"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0.015f,0),
+ "Butt_Physics_LeftRight_Driven"));
+ }
}
S32 numRemaps;
@@ -1158,4 +1196,20 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
mLastWeight = mCurWeight;
}
+
+LLPolyMorphData *clone_morph_param(const LLPolyMorphData *src_data,
+ const LLVector3 &direction,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ cloned_morph_data->mCoords[v] = direction;
+ cloned_morph_data->mNormals[v] = LLVector3(0,0,0);
+ cloned_morph_data->mBinormals[v] = LLVector3(0,0,0);
+ }
+ return cloned_morph_data;
+}
+
// End
diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp
index 0ffe1c635f..5a67fd482a 100644
--- a/indra/newview/llpolymorph.cpp
+++ b/indra/newview/llpolymorph.cpp
@@ -59,6 +59,37 @@ LLPolyMorphData::LLPolyMorphData(const std::string& morph_name)
mMesh = NULL;
}
+LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) :
+ mName(rhs.mName),
+ mNumIndices(rhs.mNumIndices),
+ mTotalDistortion(rhs.mTotalDistortion),
+ mAvgDistortion(rhs.mAvgDistortion),
+ mMaxDistortion(rhs.mMaxDistortion),
+ mVertexIndices(NULL),
+ mCoords(NULL),
+ mNormals(NULL),
+ mBinormals(NULL),
+ mTexCoords(NULL)
+{
+ const S32 numVertices = mNumIndices;
+
+ mCoords = new LLVector3[numVertices];
+ mNormals = new LLVector3[numVertices];
+ mBinormals = new LLVector3[numVertices];
+ mTexCoords = new LLVector2[numVertices];
+ mVertexIndices = new U32[numVertices];
+
+ for (S32 v=0; v < numVertices; v++)
+ {
+ mCoords[v] = rhs.mCoords[v];
+ mNormals[v] = rhs.mNormals[v];
+ mBinormals[v] = rhs.mBinormals[v];
+ mTexCoords[v] = rhs.mTexCoords[v];
+ mVertexIndices[v] = rhs.mVertexIndices[v];
+ }
+}
+
+
//-----------------------------------------------------------------------------
// ~LLPolyMorphData()
//-----------------------------------------------------------------------------
@@ -287,10 +318,22 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
}
}
- mMorphData = mMesh->getMorphData(getInfo()->mMorphName);
+ std::string morph_param_name = getInfo()->mMorphName;
+
+ mMorphData = mMesh->getMorphData(morph_param_name);
+ if (!mMorphData)
+ {
+ const std::string driven_tag = "_Driven";
+ U32 pos = morph_param_name.find(driven_tag);
+ if (pos > 0)
+ {
+ morph_param_name = morph_param_name.substr(0,pos);
+ mMorphData = mMesh->getMorphData(morph_param_name);
+ }
+ }
if (!mMorphData)
{
- llwarns << "No morph target named " << getInfo()->mMorphName << " found in mesh." << llendl;
+ llwarns << "No morph target named " << morph_param_name << " found in mesh." << llendl;
return FALSE; // Continue, ignoring this tag
}
return TRUE;
diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h
index bc111882b7..8a024f2e9e 100644
--- a/indra/newview/llpolymorph.h
+++ b/indra/newview/llpolymorph.h
@@ -46,6 +46,7 @@ class LLPolyMorphData
public:
LLPolyMorphData(const std::string& morph_name);
~LLPolyMorphData();
+ LLPolyMorphData(const LLPolyMorphData &rhs);
BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh);
const std::string& getName() { return mName; }
diff --git a/indra/newview/llpopupview.cpp b/indra/newview/llpopupview.cpp
index 499b6a8f5f..9fbb67a63a 100644
--- a/indra/newview/llpopupview.cpp
+++ b/indra/newview/llpopupview.cpp
@@ -40,7 +40,8 @@ bool view_visible(LLView* viewp)
}
-LLPopupView::LLPopupView()
+LLPopupView::LLPopupView(const LLPopupView::Params& p)
+: LLPanel(p)
{
// register ourself as handler of UI popups
LLUI::setPopupFuncs(boost::bind(&LLPopupView::addPopup, this, _1), boost::bind(&LLPopupView::removePopup, this, _1), boost::bind(&LLPopupView::clearPopups, this));
@@ -137,64 +138,102 @@ BOOL LLPopupView::handleMouseEvent(boost::function<BOOL(LLView*, S32, S32)> func
BOOL LLPopupView::handleMouseDown(S32 x, S32 y, MASK mask)
{
- if (!handleMouseEvent(boost::bind(&LLMouseHandler::handleMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true))
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true);
+ if (!handled)
{
- return FALSE;
+ handled = LLPanel::handleMouseDown(x, y, mask);
}
- return TRUE;
+ return handled;
}
BOOL LLPopupView::handleMouseUp(S32 x, S32 y, MASK mask)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleMouseUp(x, y, mask);
+ }
+ return handled;
}
BOOL LLPopupView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
- if (!handleMouseEvent(boost::bind(&LLMouseHandler::handleMiddleMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true))
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMiddleMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true);
+ if (!handled)
{
- return FALSE;
+ handled = LLPanel::handleMiddleMouseDown(x, y, mask);
}
- return TRUE;
+ return handled;
}
BOOL LLPopupView::handleMiddleMouseUp(S32 x, S32 y, MASK mask)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleMiddleMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleMiddleMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleMiddleMouseUp(x, y, mask);
+ }
+ return handled;
}
BOOL LLPopupView::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (!handleMouseEvent(boost::bind(&LLMouseHandler::handleRightMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true))
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleRightMouseDown, _1, _2, _3, mask), view_visible_and_enabled, x, y, true);
+ if (!handled)
{
- return FALSE;
+ handled = LLPanel::handleRightMouseDown(x, y, mask);
}
- return TRUE;
+ return handled;
}
BOOL LLPopupView::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleRightMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleRightMouseUp, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleRightMouseUp(x, y, mask);
+ }
+ return handled;
}
BOOL LLPopupView::handleDoubleClick(S32 x, S32 y, MASK mask)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleDoubleClick, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleDoubleClick, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleDoubleClick(x, y, mask);
+ }
+ return handled;
}
BOOL LLPopupView::handleHover(S32 x, S32 y, MASK mask)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleHover, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleHover, _1, _2, _3, mask), view_visible_and_enabled, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleHover(x, y, mask);
+ }
+ return handled;
}
BOOL LLPopupView::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleScrollWheel, _1, _2, _3, clicks), view_visible_and_enabled, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleScrollWheel, _1, _2, _3, clicks), view_visible_and_enabled, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleScrollWheel(x, y, clicks);
+ }
+ return handled;
}
BOOL LLPopupView::handleToolTip(S32 x, S32 y, MASK mask)
{
- return handleMouseEvent(boost::bind(&LLMouseHandler::handleToolTip, _1, _2, _3, mask), view_visible, x, y, false);
+ BOOL handled = handleMouseEvent(boost::bind(&LLMouseHandler::handleToolTip, _1, _2, _3, mask), view_visible, x, y, false);
+ if (!handled)
+ {
+ handled = LLPanel::handleToolTip(x, y, mask);
+ }
+ return handled;
}
void LLPopupView::addPopup(LLView* popup)
diff --git a/indra/newview/llpopupview.h b/indra/newview/llpopupview.h
index fec4afd79c..b378f61984 100644
--- a/indra/newview/llpopupview.h
+++ b/indra/newview/llpopupview.h
@@ -32,7 +32,7 @@
class LLPopupView : public LLPanel
{
public:
- LLPopupView();
+ LLPopupView(const Params& p = LLPanel::Params());
~LLPopupView();
/*virtual*/ void draw();
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 69542764d2..a90f23d637 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -454,12 +454,13 @@ LLMultiPreview::LLMultiPreview()
{
// start with a rect in the top-left corner ; will get resized
LLRect rect;
- rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 200, 200);
+ rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 200, 400);
setRect(rect);
}
setTitle(LLTrans::getString("MultiPreviewTitle"));
buildTabContainer();
setCanResize(TRUE);
+ mAutoResize = FALSE;
}
void LLMultiPreview::onOpen(const LLSD& key)
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 16284d1a7e..8e5beb33ce 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1597,7 +1597,7 @@ std::string LLPreviewGesture::getLabel(std::vector<std::string> labels)
if(v_labels[0]=="Chat")
{
- result=LLTrans::getString("Chat");
+ result=LLTrans::getString("Chat Message");
}
else if(v_labels[0]=="Sound")
{
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index cf2ea38288..b19bf5d234 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,50 @@ static bool have_script_upload_cap(LLUUID& object_id)
}
/// ---------------------------------------------------------------------------
+/// LLLiveLSLFile
+/// ---------------------------------------------------------------------------
+class LLLiveLSLFile : public LLLiveFile
+{
+public:
+ typedef boost::function<bool (const std::string& filename)> change_callback_t;
+
+ LLLiveLSLFile(std::string file_path, change_callback_t change_cb);
+ ~LLLiveLSLFile();
+
+ void ignoreNextUpdate() { mIgnoreNextUpdate = true; }
+
+protected:
+ /*virtual*/ bool loadFile();
+
+ change_callback_t mOnChangeCallback;
+ bool mIgnoreNextUpdate;
+};
+
+LLLiveLSLFile::LLLiveLSLFile(std::string file_path, change_callback_t change_cb)
+: mOnChangeCallback(change_cb)
+, mIgnoreNextUpdate(false)
+, LLLiveFile(file_path, 1.0)
+{
+ llassert(mOnChangeCallback);
+}
+
+LLLiveLSLFile::~LLLiveLSLFile()
+{
+ LLFile::remove(filename());
+}
+
+bool LLLiveLSLFile::loadFile()
+{
+ if (mIgnoreNextUpdate)
+ {
+ mIgnoreNextUpdate = false;
+ return true;
+ }
+
+ return mOnChangeCallback(filename());
+}
+
+/// ---------------------------------------------------------------------------
/// LLFloaterScriptSearch
/// ---------------------------------------------------------------------------
class LLFloaterScriptSearch : public LLFloater
@@ -277,6 +323,7 @@ struct LLSECKeywordCompare
};
LLScriptEdCore::LLScriptEdCore(
+ LLScriptEdContainer* container,
const std::string& sample,
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void*),
@@ -296,12 +343,15 @@ LLScriptEdCore::LLScriptEdCore(
mLastHelpToken(NULL),
mLiveHelpHistorySize(0),
mEnableSave(FALSE),
+ mLiveFile(NULL),
+ mContainer(container),
mHasScriptData(FALSE)
{
setFollowsAll();
setBorderVisible(FALSE);
setXMLFilename("panel_script_ed.xml");
+ llassert_always(mContainer != NULL);
}
LLScriptEdCore::~LLScriptEdCore()
@@ -315,6 +365,8 @@ LLScriptEdCore::~LLScriptEdCore()
script_search->closeFloater();
delete script_search;
}
+
+ delete mLiveFile;
}
BOOL LLScriptEdCore::postBuild()
@@ -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::openInExternalEditor, this));
initMenu();
@@ -461,6 +514,79 @@ void LLScriptEdCore::setScriptText(const std::string& text, BOOL is_valid)
}
}
+bool LLScriptEdCore::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);
+
+ mEditor->setText(LLStringExplicit(buffer));
+ delete[] buffer;
+
+ return true;
+}
+
+bool LLScriptEdCore::writeToFile(const std::string& filename)
+{
+ LLFILE* fp = LLFile::fopen(filename, "wb");
+ if (!fp)
+ {
+ llwarns << "Unable to write to " << filename << llendl;
+
+ LLSD row;
+ row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
+ row["columns"][0]["font"] = "SANSSERIF_SMALL";
+ mErrorList->addElement(row);
+ return false;
+ }
+
+ std::string utf8text = 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)
+ {
+ utf8text = " ";
+ }
+
+ fputs(utf8text.c_str(), fp);
+ fclose(fp);
+ return true;
+}
+
+void LLScriptEdCore::sync()
+{
+ // Sync with external editor.
+ std::string tmp_file = mContainer->getTmpFileName();
+ llstat s;
+ if (LLFile::stat(tmp_file, &s) == 0) // file exists
+ {
+ if (mLiveFile) mLiveFile->ignoreNextUpdate();
+ writeToFile(tmp_file);
+ }
+}
+
bool LLScriptEdCore::hasChanged()
{
if (!mEditor) return false;
@@ -637,6 +763,12 @@ BOOL LLScriptEdCore::canClose()
}
}
+void LLScriptEdCore::setEnableEditing(bool enable)
+{
+ mEditor->setEnabled(enable);
+ getChildView("Edit_btn")->setEnabled(enable);
+}
+
bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLSD& response )
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -809,6 +941,48 @@ void LLScriptEdCore::doSave( BOOL close_after_save )
}
}
+void LLScriptEdCore::openInExternalEditor()
+{
+ delete mLiveFile; // deletes file
+
+ // Save the script to a temporary file.
+ std::string filename = mContainer->getTmpFileName();
+ writeToFile(filename);
+
+ // Start watching file changes.
+ mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLScriptEdContainer::onExternalChange, mContainer, _1));
+ mLiveFile->addToEventTimer();
+
+ // Open it in external editor.
+ {
+ LLExternalEditor ed;
+ LLExternalEditor::EErrorCode status;
+ std::string msg;
+
+ status = ed.setCommand("LL_SCRIPT_EDITOR");
+ if (status != LLExternalEditor::EC_SUCCESS)
+ {
+ if (status == LLExternalEditor::EC_NOT_SPECIFIED) // Use custom message for this error.
+ {
+ msg = getString("external_editor_not_set");
+ }
+ else
+ {
+ msg = LLExternalEditor::getErrorMessage(status);
+ }
+
+ LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
+ return;
+ }
+
+ status = ed.run(filename);
+ if (status != LLExternalEditor::EC_SUCCESS)
+ {
+ msg = LLExternalEditor::getErrorMessage(status);
+ LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
+ }
+ }
+}
void LLScriptEdCore::onBtnUndoChanges()
{
@@ -923,6 +1097,43 @@ BOOL LLScriptEdCore::handleKeyHere(KEY key, MASK mask)
}
/// ---------------------------------------------------------------------------
+/// LLScriptEdContainer
+/// ---------------------------------------------------------------------------
+
+LLScriptEdContainer::LLScriptEdContainer(const LLSD& key)
+: LLPreview(key)
+, mScriptEd(NULL)
+{
+}
+
+std::string LLScriptEdContainer::getTmpFileName()
+{
+ // Take script inventory item id (within the object inventory)
+ // to consideration so that it's possible to edit multiple scripts
+ // in the same object inventory simultaneously (STORM-781).
+ std::string script_id = mObjectUUID.asString() + "_" + mItemUUID.asString();
+
+ // Use MD5 sum to make the file name shorter and not exceed maximum path length.
+ char script_id_hash_str[33]; /* Flawfinder: ignore */
+ LLMD5 script_id_hash((const U8 *)script_id.c_str());
+ script_id_hash.hex_digest(script_id_hash_str);
+
+ return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl";
+}
+
+bool LLScriptEdContainer::onExternalChange(const std::string& filename)
+{
+ if (!mScriptEd->loadScriptText(filename))
+ {
+ return false;
+ }
+
+ // Disable sync to avoid recursive load->save->load calls.
+ saveIfNeeded(false);
+ return true;
+}
+
+/// ---------------------------------------------------------------------------
/// LLPreviewLSL
/// ---------------------------------------------------------------------------
@@ -945,6 +1156,7 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
LLPreviewLSL *self = (LLPreviewLSL*)userdata;
self->mScriptEd = new LLScriptEdCore(
+ self,
HELLO_LSL,
self->getHandle(),
LLPreviewLSL::onLoad,
@@ -958,7 +1170,7 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
LLPreviewLSL::LLPreviewLSL(const LLSD& key )
- : LLPreview( key ),
+: LLScriptEdContainer(key),
mPendingUploads(0)
{
mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
@@ -1049,7 +1261,6 @@ void LLPreviewLSL::loadAsset()
{
mScriptEd->setScriptText(mScriptEd->getString("can_not_view"), FALSE);
mScriptEd->mEditor->makePristine();
- mScriptEd->mEditor->setEnabled(FALSE);
mScriptEd->mFunctions->setEnabled(FALSE);
mAssetStatus = PREVIEW_ASSET_LOADED;
}
@@ -1059,6 +1270,7 @@ void LLPreviewLSL::loadAsset()
else
{
mScriptEd->setScriptText(std::string(HELLO_LSL), TRUE);
+ mScriptEd->setEnableEditing(TRUE);
mAssetStatus = PREVIEW_ASSET_LOADED;
}
}
@@ -1105,7 +1317,7 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)
// Save needs to compile the text in the buffer. If the compile
// succeeds, then save both assets out to the database. If the compile
// fails, go ahead and save the text anyway.
-void LLPreviewLSL::saveIfNeeded()
+void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
{
// llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl;
if(!mScriptEd->hasChanged())
@@ -1124,23 +1336,13 @@ void LLPreviewLSL::saveIfNeeded()
std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString());
std::string filename = filepath + ".lsl";
- LLFILE* fp = LLFile::fopen(filename, "wb");
- if(!fp)
- {
- llwarns << "Unable to write to " << filename << llendl;
+ mScriptEd->writeToFile(filename);
- LLSD row;
- 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;
+ if (sync)
+ {
+ mScriptEd->sync();
}
- std::string utf8text = mScriptEd->mEditor->getText();
- fputs(utf8text.c_str(), fp);
- fclose(fp);
- fp = NULL;
-
const LLInventoryItem *inv_item = getItem();
// save it out to asset server
std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent");
@@ -1372,7 +1574,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
{
is_modifiable = TRUE;
}
- preview->mScriptEd->mEditor->setEnabled(is_modifiable);
+ preview->mScriptEd->setEnableEditing(is_modifiable);
preview->mAssetStatus = PREVIEW_ASSET_LOADED;
}
else
@@ -1413,6 +1615,7 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
LLLiveLSLEditor *self = (LLLiveLSLEditor*)userdata;
self->mScriptEd = new LLScriptEdCore(
+ self,
HELLO_LSL,
self->getHandle(),
&LLLiveLSLEditor::onLoad,
@@ -1426,8 +1629,7 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
- LLPreview(key),
- mScriptEd(NULL),
+ LLScriptEdContainer(key),
mAskedForRunningInfo(FALSE),
mHaveRunningInfo(FALSE),
mCloseAfterSave(FALSE),
@@ -1456,10 +1658,6 @@ BOOL LLLiveLSLEditor::postBuild()
return LLPreview::postBuild();
}
-LLLiveLSLEditor::~LLLiveLSLEditor()
-{
-}
-
// virtual
void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id,
const LLUUID& item_id,
@@ -1516,7 +1714,6 @@ void LLLiveLSLEditor::loadAsset()
mItem = new LLViewerInventoryItem(item);
mScriptEd->setScriptText(getString("not_allowed"), FALSE);
mScriptEd->mEditor->makePristine();
- mScriptEd->mEditor->setEnabled(FALSE);
mScriptEd->enableSave(FALSE);
mAssetStatus = PREVIEW_ASSET_LOADED;
}
@@ -1554,10 +1751,6 @@ void LLLiveLSLEditor::loadAsset()
mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY,
item->getPermissions(),
GP_OBJECT_MANIPULATE);
- if(!mIsModifiable)
- {
- mScriptEd->mEditor->setEnabled(FALSE);
- }
// This is commented out, because we don't completely
// handle script exports yet.
@@ -1613,6 +1806,7 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
if( LL_ERR_NOERR == status )
{
instance->loadScriptText(vfs, asset_id, type);
+ instance->mScriptEd->setEnableEditing(TRUE);
instance->mAssetStatus = PREVIEW_ASSET_LOADED;
}
else
@@ -1639,39 +1833,6 @@ 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;
-// }
-// }
-
void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
{
LLVFile file(vfs, uuid, type);
@@ -1825,9 +1986,9 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
mItem = new LLViewerInventoryItem(item);
}
-void LLLiveLSLEditor::saveIfNeeded()
+// virtual
+void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
{
- llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
if(!object)
{
@@ -1877,29 +2038,12 @@ void LLLiveLSLEditor::saveIfNeeded()
mItem->setAssetUUID(asset_id);
mItem->setTransactionID(tid);
- // write out the data, and store it in the asset database
- LLFILE* fp = LLFile::fopen(filename, "wb");
- if(!fp)
- {
- llwarns << "Unable to write to " << filename << llendl;
+ mScriptEd->writeToFile(filename);
- LLSD row;
- 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;
- }
- 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 (sync)
{
- utf8text = " ";
+ mScriptEd->sync();
}
-
- fputs(utf8text.c_str(), fp);
- fclose(fp);
- fp = NULL;
// save it out to asset server
std::string url = object->getRegion()->getCapability("UpdateScriptTask");
@@ -2138,6 +2282,7 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
self->saveIfNeeded();
}
+
// static
void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
{
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index f4b31e5962..f86be615c4 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;
@@ -47,6 +48,7 @@ class LLFloaterScriptSearch;
class LLKeywordToken;
class LLVFS;
class LLViewerInventoryItem;
+class LLScriptEdContainer;
// Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these.
class LLScriptEdCore : public LLPanel
@@ -55,9 +57,12 @@ class LLScriptEdCore : public LLPanel
friend class LLPreviewLSL;
friend class LLLiveLSLEditor;
friend class LLFloaterScriptSearch;
+ friend class LLScriptEdContainer;
-public:
+protected:
+ // Supposed to be invoked only by the container.
LLScriptEdCore(
+ LLScriptEdContainer* container,
const std::string& sample,
const LLHandle<LLFloater>& floater_handle,
void (*load_callback)(void* userdata),
@@ -65,6 +70,7 @@ public:
void (*search_replace_callback)(void* userdata),
void* userdata,
S32 bottom_pad = 0); // pad below bottom row of buttons
+public:
~LLScriptEdCore();
void initMenu();
@@ -72,14 +78,20 @@ public:
virtual void draw();
/*virtual*/ BOOL postBuild();
BOOL canClose();
+ void setEnableEditing(bool enable);
void setScriptText(const std::string& text, BOOL is_valid);
+ bool loadScriptText(const std::string& filename);
+ bool writeToFile(const std::string& filename);
+ void sync();
void doSave( BOOL close_after_save );
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response);
+ void openInExternalEditor();
+
static void onCheckLock(LLUICtrl*, void*);
static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
static void onClickBack(void* userdata);
@@ -127,11 +139,28 @@ private:
S32 mLiveHelpHistorySize;
BOOL mEnableSave;
BOOL mHasScriptData;
+ LLLiveLSLFile* mLiveFile;
+
+ LLScriptEdContainer* mContainer; // parent view
};
+class LLScriptEdContainer : public LLPreview
+{
+ friend class LLScriptEdCore;
+
+public:
+ LLScriptEdContainer(const LLSD& key);
+
+protected:
+ std::string getTmpFileName();
+ bool onExternalChange(const std::string& filename);
+ virtual void saveIfNeeded(bool sync = true) = 0;
+
+ LLScriptEdCore* mScriptEd;
+};
// Used to view and edit a LSL from your inventory.
-class LLPreviewLSL : public LLPreview
+class LLPreviewLSL : public LLScriptEdContainer
{
public:
LLPreviewLSL(const LLSD& key );
@@ -145,7 +174,7 @@ protected:
void closeIfNeeded();
virtual void loadAsset();
- void saveIfNeeded();
+ /*virtual*/ void saveIfNeeded(bool sync = true);
void uploadAssetViaCaps(const std::string& url,
const std::string& filename,
const LLUUID& item_id);
@@ -169,7 +198,6 @@ protected:
protected:
- LLScriptEdCore* mScriptEd;
// Can safely close only after both text and bytecode are uploaded
S32 mPendingUploads;
@@ -177,11 +205,11 @@ protected:
// Used to view and edit an LSL that is attached to an object.
-class LLLiveLSLEditor : public LLPreview
+class LLLiveLSLEditor : public LLScriptEdContainer
{
+ friend class LLLiveLSLFile;
public:
LLLiveLSLEditor(const LLSD& key);
- ~LLLiveLSLEditor();
static void processScriptRunningReply(LLMessageSystem* msg, void**);
@@ -202,7 +230,7 @@ private:
virtual void loadAsset();
void loadAsset(BOOL is_new);
- void saveIfNeeded();
+ /*virtual*/ void saveIfNeeded(bool sync = true);
void uploadAssetViaCaps(const std::string& url,
const std::string& filename,
const LLUUID& task_id,
@@ -227,7 +255,6 @@ private:
static void onRunningCheckboxClicked(LLUICtrl*, void* userdata);
static void onReset(void* userdata);
-// void loadScriptText(const std::string& filename); // unused
void loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type);
static void onErrorList(LLUICtrl*, void* user_data);
@@ -238,7 +265,6 @@ private:
private:
bool mIsNew;
- LLScriptEdCore* mScriptEd;
//LLUUID mTransmitID;
LLCheckBoxCtrl* mRunningCheckbox;
BOOL mAskedForRunningInfo;
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index fd6b326ef1..6cfb708112 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -273,6 +273,8 @@ void LLPreviewTexture::saveAs()
mSaveFileName = file_picker.getFirstFile();
mLoadingFullImage = TRUE;
getWindow()->incBusyCount();
+
+ mImage->forceToSaveRawImage(0) ;//re-fetch the raw image if the old one is removed.
mImage->setLoadedCallback( LLPreviewTexture::onFileLoadedForSave,
0, TRUE, FALSE, new LLUUID( mItemUUID ), &mCallbackTextureList );
}
@@ -318,7 +320,7 @@ void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent)
}
}
- mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
+ mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
}
@@ -400,7 +402,6 @@ void LLPreviewTexture::updateDimensions()
{
return;
}
-
mUpdateDimensions = FALSE;
@@ -408,80 +409,12 @@ void LLPreviewTexture::updateDimensions()
getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", mImage->getFullHeight()));
- LLRect dim_rect(getChildView("dimensions")->getRect());
-
- S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
-
- // add space for dimensions and aspect ratio
- S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD;
-
- S32 screen_width = gFloaterView->getSnapRect().getWidth();
- S32 screen_height = gFloaterView->getSnapRect().getHeight();
-
- S32 max_image_width = screen_width - 2*horiz_pad;
- S32 max_image_height = screen_height - (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD)
- - (PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height);
-
- S32 client_width = llmin(max_image_width,mImage->getFullWidth());
- S32 client_height = llmin(max_image_height,mImage->getFullHeight());
-
- if (mAspectRatio > 0.f)
- {
- if(mAspectRatio > 1.f)
- {
- client_height = llceil((F32)client_width / mAspectRatio);
- if(client_height > max_image_height)
- {
- client_height = max_image_height;
- client_width = llceil((F32)client_height * mAspectRatio);
- }
- }
- else//mAspectRatio < 1.f
- {
- client_width = llceil((F32)client_height * mAspectRatio);
- if(client_width > max_image_width)
- {
- client_width = max_image_width;
- client_height = llceil((F32)client_width / mAspectRatio);
- }
- }
- }
- else
- {
-
- if(client_height > max_image_height)
- {
- F32 ratio = (F32)max_image_height/client_height;
- client_height = max_image_height;
- client_width = llceil((F32)client_height * ratio);
- }
-
- if(client_width > max_image_width)
- {
- F32 ratio = (F32)max_image_width/client_width;
- client_width = max_image_width;
- client_height = llceil((F32)client_width * ratio);
- }
- }
-
- //now back to whole floater
- S32 floater_width = llmax(getMinWidth(),client_width + 2*horiz_pad);
- S32 floater_height = llmax(getMinHeight(),client_height + (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD)
- + (PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height));
-
//reshape floater
- reshape( floater_width, floater_height );
- gFloaterView->adjustToFitScreen(this, FALSE);
+ reshape(getRect().getWidth(), getRect().getHeight());
- //setup image rect...
- LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0);
- client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
- client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ;
-
- mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
+ gFloaterView->adjustToFitScreen(this, FALSE);
- // Hide the aspect ratio label if the window is too narrow
- // Assumes the label should be to the right of the dimensions
+ LLRect dim_rect(getChildView("dimensions")->getRect());
LLRect aspect_label_rect(getChildView("aspect_ratio")->getRect());
getChildView("aspect_ratio")->setVisible( dim_rect.mRight < aspect_label_rect.mLeft);
}
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index e9504cbba0..31fde5d58a 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -133,13 +133,13 @@ void LLProgressView::setVisible(BOOL visible)
mFadeTimer.start();
}
// showing progress view
- else if (!getVisible() && visible)
+ else if (visible && (!getVisible() || mFadeTimer.getStarted()))
{
setFocus(TRUE);
mFadeTimer.stop();
mProgressTimer.start();
LLPanel::setVisible(TRUE);
- }
+ }
}
@@ -207,7 +207,7 @@ void LLProgressView::setText(const std::string& text)
void LLProgressView::setPercent(const F32 percent)
{
- mProgressBar->setPercent(percent);
+ mProgressBar->setValue(percent);
}
void LLProgressView::setMessage(const std::string& msg)
diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp
index 959fd51bbf..7689cd1a52 100644
--- a/indra/newview/llrecentpeople.cpp
+++ b/indra/newview/llrecentpeople.cpp
@@ -33,7 +33,7 @@
using namespace LLOldEvents;
-bool LLRecentPeople::add(const LLUUID& id)
+bool LLRecentPeople::add(const LLUUID& id, const LLSD& userdata)
{
if (id == gAgent.getID())
return false;
@@ -42,10 +42,16 @@ bool LLRecentPeople::add(const LLUUID& id)
if (is_not_group_id)
{
- LLDate date_added = LLDate::now();
+ // For each avaline call the id of caller is different even if
+ // the phone number is the same.
+ // To avoid duplication of avaline list items in the recent list
+ // of panel People, deleting id's with similar phone number.
+ const LLUUID& caller_id = getIDByPhoneNumber(userdata);
+ if (caller_id.notNull())
+ mPeople.erase(caller_id);
- //[] instead of insert to replace existing id->date with new date value
- mPeople[id] = date_added;
+ //[] instead of insert to replace existing id->llsd["date"] with new date value
+ mPeople[id] = userdata;
mChangedSignal();
}
@@ -64,15 +70,55 @@ void LLRecentPeople::get(uuid_vec_t& result) const
result.push_back((*pos).first);
}
-const LLDate& LLRecentPeople::getDate(const LLUUID& id) const
+const LLDate LLRecentPeople::getDate(const LLUUID& id) const
{
recent_people_t::const_iterator it = mPeople.find(id);
- if (it!= mPeople.end()) return (*it).second;
+ if (it!= mPeople.end()) return it->second["date"].asDate();
static LLDate no_date = LLDate();
return no_date;
}
+const LLSD& LLRecentPeople::getData(const LLUUID& id) const
+{
+ recent_people_t::const_iterator it = mPeople.find(id);
+
+ if (it != mPeople.end())
+ return it->second;
+
+ static LLSD no_data = LLSD();
+ return no_data;
+}
+
+bool LLRecentPeople::isAvalineCaller(const LLUUID& id) const
+{
+ recent_people_t::const_iterator it = mPeople.find(id);
+
+ if (it != mPeople.end())
+ {
+ const LLSD& user = it->second;
+ return user["avaline_call"].asBoolean();
+ }
+
+ return false;
+}
+
+const LLUUID& LLRecentPeople::getIDByPhoneNumber(const LLSD& userdata)
+{
+ if (!userdata["avaline_call"].asBoolean())
+ return LLUUID::null;
+
+ for (recent_people_t::const_iterator it = mPeople.begin(); it != mPeople.end(); ++it)
+ {
+ const LLSD& user_info = it->second;
+
+ if (user_info["call_number"].asString() == userdata["call_number"].asString())
+ return it->first;
+ }
+
+ return LLUUID::null;
+}
+
// virtual
bool LLRecentPeople::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index 852a92ff80..d0d6376867 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -58,9 +58,15 @@ public:
* Add specified avatar to the list if it's not there already.
*
* @param id avatar to add.
+ *
+ * @param userdata additional information about last interaction party.
+ * For example when last interaction party is not an avatar
+ * but an avaline caller, additional info (such as phone
+ * number, session id and etc.) should be added.
+ *
* @return false if the avatar is in the list already, true otherwise
*/
- bool add(const LLUUID& id);
+ bool add(const LLUUID& id, const LLSD& userdata = LLSD().with("date", LLDate::now()));
/**
* @param id avatar to search.
@@ -75,7 +81,25 @@ public:
*/
void get(uuid_vec_t& result) const;
- const LLDate& getDate(const LLUUID& id) const;
+ /**
+ * Returns last interaction time with specified participant
+ *
+ */
+ const LLDate getDate(const LLUUID& id) const;
+
+ /**
+ * Returns data about specified participant
+ *
+ * @param id identifier of specific participant
+ */
+ const LLSD& getData(const LLUUID& id) const;
+
+ /**
+ * Checks whether specific participant is an avaline caller
+ *
+ * @param id identifier of specific participant
+ */
+ bool isAvalineCaller(const LLUUID& id) const;
/**
* Set callback to be called when the list changed.
@@ -92,7 +116,10 @@ public:
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
private:
- typedef std::map<LLUUID, LLDate> recent_people_t;
+
+ const LLUUID& getIDByPhoneNumber(const LLSD& userdata);
+
+ typedef std::map<LLUUID, LLSD> recent_people_t;
recent_people_t mPeople;
signal_t mChangedSignal;
};
diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp
index d63a48647d..3862dac340 100644
--- a/indra/newview/llremoteparcelrequest.cpp
+++ b/indra/newview/llremoteparcelrequest.cpp
@@ -33,6 +33,7 @@
#include "llpanel.h"
#include "llhttpclient.h"
#include "llsdserialize.h"
+#include "llurlentry.h"
#include "llviewerregion.h"
#include "llview.h"
@@ -77,23 +78,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 +102,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,14 +136,51 @@ 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;
- observer_multimap_t::iterator oi = observers.find(parcel_data.parcel_id);
+ typedef std::vector<observer_multimap_t::iterator> deadlist_t;
+ deadlist_t dead_iters;
+
+ observer_multimap_t::iterator oi = observers.lower_bound(parcel_data.parcel_id);
observer_multimap_t::iterator end = observers.upper_bound(parcel_data.parcel_id);
- for (; oi != end; ++oi)
+
+ while (oi != end)
{
- oi->second->processParcelInfo(parcel_data);
+ // increment the loop iterator now since it may become invalid below
+ observer_multimap_t::iterator cur_oi = oi++;
+
+ LLRemoteParcelInfoObserver * observer = cur_oi->second.get();
+ if(observer)
+ {
+ // may invalidate cur_oi if the observer removes itself
+ observer->processParcelInfo(parcel_data);
+ }
+ else
+ {
+ // the handle points to an expired observer, so don't keep it
+ // around anymore
+ dead_iters.push_back(cur_oi);
+ }
}
+
+ deadlist_t::iterator i;
+ deadlist_t::iterator end_dead = dead_iters.end();
+ for(i = dead_iters.begin(); i != end_dead; ++i)
+ {
+ observers.erase(*i);
+ }
+
+ LLUrlEntryParcel::LLParcelData url_data;
+ url_data.parcel_id = parcel_data.parcel_id;
+ url_data.name = parcel_data.name;
+ url_data.sim_name = parcel_data.sim_name;
+ url_data.global_x = parcel_data.global_x;
+ url_data.global_y = parcel_data.global_y;
+ url_data.global_z = parcel_data.global_z;
+
+ // Pass the parcel data to LLUrlEntryParcel to render
+ // human readable parcel name.
+ LLUrlEntryParcel::processParcelInfo(url_data);
}
void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id)
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/llrootview.h b/indra/newview/llrootview.h
index 4b1ba15a0b..5223a314f3 100644
--- a/indra/newview/llrootview.h
+++ b/indra/newview/llrootview.h
@@ -42,27 +42,5 @@ public:
LLRootView(const Params& p)
: LLView(p)
{}
-
- // added to provide possibility to handle mouse click event inside all application
- // window without creating any floater
- typedef boost::signals2::signal<void(S32 x, S32 y, MASK mask)>
- mouse_signal_t;
-
- private:
- mouse_signal_t mMouseDownSignal;
-
- public:
- /*virtual*/
- BOOL handleMouseDown(S32 x, S32 y, MASK mask)
- {
- mMouseDownSignal(x, y, mask);
- return LLView::handleMouseDown(x, y, mask);
- }
-
- boost::signals2::connection addMouseDownCallback(
- const mouse_signal_t::slot_type& cb)
- {
- return mMouseDownSignal.connect(cb);
- }
};
#endif //LL_LLROOTVIEW_H
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 18c9ac28c1..e3bc67a414 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -83,11 +83,10 @@ bool LLScreenChannelBase::isHovering()
return mHoveredToast->isHovered();
}
-bool LLScreenChannelBase::resetPositionAndSize(const LLSD& newvalue)
+void LLScreenChannelBase::resetPositionAndSize()
{
LLRect rc = gViewerWindow->getWorldViewRectScaled();
updatePositionAndSize(rc, rc);
- return true;
}
void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
@@ -99,10 +98,7 @@ void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect ne
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE
&& LLSideTray::instanceCreated ())
{
- LLSideTray* side_bar = LLSideTray::getInstance();
-
- if (side_bar->getVisible() && !side_bar->getCollapsed())
- world_rect_padding += side_bar->getRect().getWidth();
+ world_rect_padding += LLSideTray::getInstance()->getVisibleWidth();
}
@@ -133,15 +129,25 @@ void LLScreenChannelBase::init(S32 channel_left, S32 channel_right)
if(LLSideTray::instanceCreated())
{
LLSideTray* side_bar = LLSideTray::getInstance();
- side_bar->getCollapseSignal().connect(boost::bind(&LLScreenChannelBase::resetPositionAndSize, this, _2));
+ side_bar->setVisibleWidthChangeCallback(boost::bind(&LLScreenChannelBase::resetPositionAndSize, this));
}
+ // top and bottom set by updateBottom()
+ setRect(LLRect(channel_left, 0, channel_right, 0));
+ updateBottom();
+ setVisible(TRUE);
+}
+
+void LLScreenChannelBase::updateBottom()
+{
S32 channel_top = gViewerWindow->getWorldViewRectScaled().getHeight();
- S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
+ S32 channel_bottom = gSavedSettings.getS32("ChannelBottomPanelMargin");
+ S32 channel_left = getRect().mLeft;
+ S32 channel_right = getRect().mRight;
setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
- setVisible(TRUE);
}
+
//--------------------------------------------------------------------------
//////////////////////
// LLScreenChannel
@@ -204,10 +210,7 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo
if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE
&& LLSideTray::instanceCreated ())
{
- LLSideTray* side_bar = LLSideTray::getInstance();
-
- if (side_bar->getVisible() && !side_bar->getCollapsed())
- world_rect_padding += side_bar->getRect().getWidth();
+ world_rect_padding += LLSideTray::getInstance()->getVisibleWidth();
}
@@ -253,8 +256,8 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
if(mControlHovering)
{
new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
- new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopFadingToast, this, new_toast_elem.toast));
- new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startFadingToast, this, new_toast_elem.toast));
+ new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, new_toast_elem.toast));
+ new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, new_toast_elem.toast));
}
if(show_toast)
@@ -369,7 +372,7 @@ void LLScreenChannel::loadStoredToastsToChannel()
for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
{
(*it).toast->setIsHidden(false);
- (*it).toast->resetTimer();
+ (*it).toast->startTimer();
mToastList.push_back((*it));
}
@@ -394,7 +397,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
}
toast->setIsHidden(false);
- toast->resetTimer();
+ toast->startTimer();
mToastList.push_back((*it));
redrawToasts();
@@ -477,7 +480,7 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
toast->removeChild(old_panel);
delete old_panel;
toast->insertPanel(panel);
- toast->resetTimer();
+ toast->startTimer();
redrawToasts();
}
}
@@ -485,7 +488,7 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
//--------------------------------------------------------------------------
void LLScreenChannel::redrawToasts()
{
- if(mToastList.size() == 0 || isHovering())
+ if(mToastList.size() == 0)
return;
switch(mToastAlignment)
@@ -511,6 +514,8 @@ void LLScreenChannel::showToastsBottom()
S32 toast_margin = 0;
std::vector<ToastElem>::reverse_iterator it;
+ updateBottom();
+
LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
@@ -583,20 +588,15 @@ void LLScreenChannel::showToastsBottom()
}
}
+ // Dismiss toasts we don't have space for (STORM-391).
if(it != mToastList.rend())
{
mHiddenToastsNum = 0;
for(; it != mToastList.rend(); it++)
{
- (*it).toast->stopTimer();
- (*it).toast->setVisible(FALSE);
- mHiddenToastsNum++;
+ (*it).toast->hide();
}
}
- else
- {
- closeOverflowToastPanel();
- }
}
//--------------------------------------------------------------------------
@@ -697,15 +697,15 @@ void LLScreenChannel::closeStartUpToast()
}
}
-void LLNotificationsUI::LLScreenChannel::stopFadingToast(LLToast* toast)
+void LLNotificationsUI::LLScreenChannel::stopToastTimer(LLToast* toast)
{
if (!toast || toast != mHoveredToast) return;
// Pause fade timer of the hovered toast.
- toast->stopFading();
+ toast->stopTimer();
}
-void LLNotificationsUI::LLScreenChannel::startFadingToast(LLToast* toast)
+void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast)
{
if (!toast || toast == mHoveredToast)
{
@@ -713,13 +713,12 @@ void LLNotificationsUI::LLScreenChannel::startFadingToast(LLToast* toast)
}
// Reset its fade timer.
- toast->startFading();
+ toast->startTimer();
}
//--------------------------------------------------------------------------
void LLScreenChannel::hideToastsFromScreen()
{
- closeOverflowToastPanel();
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
(*it).toast->setVisible(FALSE);
}
@@ -835,8 +834,7 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
}
}
- if(!isHovering())
- redrawToasts();
+ redrawToasts();
}
//--------------------------------------------------------------------------
@@ -850,13 +848,7 @@ void LLScreenChannel::updateShowToastsState()
return;
}
- S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
- LLRect this_rect = getRect();
-
- if(channel_bottom != this_rect.mBottom)
- {
- setRect(LLRect(this_rect.mLeft, this_rect.mTop, this_rect.mRight, channel_bottom));
- }
+ updateBottom();
}
//--------------------------------------------------------------------------
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index a1fdd6e32c..d207d13981 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -59,8 +59,8 @@ public:
// Channel's outfit-functions
// update channel's size and position in the World View
virtual void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect);
+ void resetPositionAndSize();
- bool resetPositionAndSize(const LLSD& newvalue);
// initialization of channel's shape and position
virtual void init(S32 channel_left, S32 channel_right);
@@ -81,9 +81,6 @@ public:
// show all toasts in a channel
virtual void redrawToasts() {};
- virtual void closeOverflowToastPanel() {};
- virtual void hideOverflowToastPanel() {};
-
// Channel's behavior-functions
// set whether a channel will control hovering inside itself or not
@@ -111,6 +108,8 @@ public:
LLUUID getChannelID() { return mID; }
protected:
+ void updateBottom();
+
// Channel's flags
bool mControlHovering;
LLToast* mHoveredToast;
@@ -194,10 +193,10 @@ public:
/** Stop fading given toast */
- virtual void stopFadingToast(LLToast* toast);
+ virtual void stopToastTimer(LLToast* toast);
/** Start fading given toast */
- virtual void startFadingToast(LLToast* toast);
+ virtual void startToastTimer(LLToast* toast);
// get StartUp Toast's state
static bool getStartUpToastShown() { return mWasStartUpToastShown; }
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..8e959a3d0e 100644
--- a/indra/newview/llscriptfloater.h
+++ b/indra/newview/llscriptfloater.h
@@ -28,8 +28,9 @@
#define LL_SCRIPTFLOATER_H
#include "lltransientdockablefloater.h"
+#include "llnotificationptr.h"
-class LLToastNotifyPanel;
+class LLToastPanel;
/**
* Handles script notifications ("ScriptDialog" and "ScriptDialogGroup")
@@ -203,7 +204,9 @@ protected:
void dockToChiclet(bool dock);
private:
- LLToastNotifyPanel* mScriptForm;
+ bool isScriptTextbox(LLNotificationPtr notification);
+
+ LLToastPanel* mScriptForm;
LLUUID mNotificationId;
LLUUID mObjectId;
bool mSaveFloaterPosition;
diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
index 05b273cd29..05b82ba967 100644
--- a/indra/newview/llscrollingpanelparam.cpp
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -50,14 +50,9 @@ const S32 LLScrollingPanelParam::PARAM_HINT_HEIGHT = 128;
S32 LLScrollingPanelParam::sUpdateDelayFrames = 0;
LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_params,
- LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp )
- : LLScrollingPanel( panel_params ),
- mParam(param),
- mAllowModify(allow_modify),
- mWearable(wearable)
+ LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints )
+ : LLScrollingPanelParamBase( panel_params, mesh, param, allow_modify, wearable, jointp, use_hints)
{
- buildFromFile( "panel_scrolling_param.xml");
-
// *HACK To avoid hard coding texture position, lets use border's position for texture.
LLViewBorder* left_border = getChild<LLViewBorder>("left_border");
@@ -73,12 +68,6 @@ LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_param
mHintMin->setAllowsUpdates( FALSE );
mHintMax->setAllowsUpdates( FALSE );
- getChild<LLUICtrl>("param slider")->setValue(weightToPercent(param->getWeight()));
-
- std::string display_name = LLTrans::getString(param->getDisplayName());
- getChild<LLUICtrl>("param slider")->setLabelArg("[DESC]", display_name);
- getChildView("param slider")->setEnabled(mAllowModify);
- childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this);
std::string min_name = LLTrans::getString(param->getMinDisplayName());
std::string max_name = LLTrans::getString(param->getMaxDisplayName());
@@ -112,20 +101,15 @@ LLScrollingPanelParam::~LLScrollingPanelParam()
}
void LLScrollingPanelParam::updatePanel(BOOL allow_modify)
{
- LLViewerVisualParam* param = mHintMin->getVisualParam();
-
if (!mWearable)
{
// not editing a wearable just now, no update necessary
return;
}
- F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
- getChild<LLUICtrl>("param slider")->setValue(weightToPercent( current_weight ) );
+ LLScrollingPanelParamBase::updatePanel(allow_modify);
+
mHintMin->requestUpdate( sUpdateDelayFrames++ );
mHintMax->requestUpdate( sUpdateDelayFrames++ );
-
- mAllowModify = allow_modify;
- getChildView("param slider")->setEnabled(mAllowModify);
getChildView("less")->setEnabled(mAllowModify);
getChildView("more")->setEnabled(mAllowModify);
}
@@ -135,13 +119,17 @@ void LLScrollingPanelParam::setVisible( BOOL visible )
if( getVisible() != visible )
{
LLPanel::setVisible( visible );
- mHintMin->setAllowsUpdates( visible );
- mHintMax->setAllowsUpdates( visible );
+ if (mHintMin)
+ mHintMin->setAllowsUpdates( visible );
+ if (mHintMax)
+ mHintMax->setAllowsUpdates( visible );
if( visible )
{
- mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ );
- mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ );
+ if (mHintMin)
+ mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ );
+ if (mHintMax)
+ mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ );
}
}
}
@@ -164,13 +152,17 @@ void LLScrollingPanelParam::draw()
getChildView("min param text")->setVisible( FALSE );
getChildView("max param text")->setVisible( FALSE );
LLPanel::draw();
+
+ // If we're in a focused floater, don't apply the floater's alpha to visual param hint,
+ // making its behavior similar to texture controls'.
+ F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
// Draw the hints over the "less" and "more" buttons.
gGL.pushUIMatrix();
{
const LLRect& r = mHintMin->getRect();
gGL.translateUI((F32)r.mLeft, (F32)r.mBottom, 0.f);
- mHintMin->draw();
+ mHintMin->draw(alpha);
}
gGL.popUIMatrix();
@@ -178,7 +170,7 @@ void LLScrollingPanelParam::draw()
{
const LLRect& r = mHintMax->getRect();
gGL.translateUI((F32)r.mLeft, (F32)r.mBottom, 0.f);
- mHintMax->draw();
+ mHintMax->draw(alpha);
}
gGL.popUIMatrix();
@@ -192,23 +184,6 @@ void LLScrollingPanelParam::draw()
}
// static
-void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata)
-{
- LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
- LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
- LLViewerVisualParam* param = self->mParam;
-
- F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
- F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
- if (current_weight != new_weight )
- {
- self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
- self->mWearable->writeToAvatar();
- gAgentAvatarp->updateVisualParams();
- }
-}
-
-// static
void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
{
}
@@ -217,7 +192,6 @@ void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
void LLScrollingPanelParam::onSliderMouseUp(LLUICtrl* ctrl, void* userdata)
{
LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
-
LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
}
diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h
index 1cbc64f45a..c7a47d5c7a 100644
--- a/indra/newview/llscrollingpanelparam.h
+++ b/indra/newview/llscrollingpanelparam.h
@@ -28,8 +28,7 @@
#ifndef LL_SCROLLINGPANELPARAM_H
#define LL_SCROLLINGPANELPARAM_H
-#include "llpanel.h"
-#include "llscrollingpanellist.h"
+#include "llscrollingpanelparambase.h"
class LLViewerJointMesh;
class LLViewerVisualParam;
@@ -38,11 +37,11 @@ class LLVisualParamHint;
class LLViewerVisualParam;
class LLJoint;
-class LLScrollingPanelParam : public LLScrollingPanel
+class LLScrollingPanelParam : public LLScrollingPanelParamBase
{
public:
LLScrollingPanelParam( const LLPanel::Params& panel_params,
- LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp );
+ LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints = TRUE );
virtual ~LLScrollingPanelParam();
virtual void draw();
@@ -50,7 +49,6 @@ public:
virtual void updatePanel(BOOL allow_modify);
static void onSliderMouseDown(LLUICtrl* ctrl, void* userdata);
- static void onSliderMoved(LLUICtrl* ctrl, void* userdata);
static void onSliderMouseUp(LLUICtrl* ctrl, void* userdata);
static void onHintMinMouseDown(void* userdata);
@@ -74,7 +72,6 @@ public:
const static S32 PARAM_HINT_HEIGHT;
public:
- LLViewerVisualParam* mParam;
LLPointer<LLVisualParamHint> mHintMin;
LLPointer<LLVisualParamHint> mHintMax;
static S32 sUpdateDelayFrames;
@@ -82,9 +79,7 @@ public:
protected:
LLTimer mMouseDownTimer; // timer for how long mouse has been held down on a hint.
F32 mLastHeldTime;
-
BOOL mAllowModify;
- LLWearable *mWearable;
};
#endif
diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp
new file mode 100644
index 0000000000..62e3039d2f
--- /dev/null
+++ b/indra/newview/llscrollingpanelparambase.cpp
@@ -0,0 +1,112 @@
+/**
+ * @file llscrollingpanelparam.cpp
+ * @brief UI panel for a list of visual param panels
+ *
+ * $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 "llscrollingpanelparambase.h"
+#include "llviewerjointmesh.h"
+#include "llviewervisualparam.h"
+#include "llwearable.h"
+#include "llviewervisualparam.h"
+#include "lltoolmorph.h"
+#include "lltrans.h"
+#include "llbutton.h"
+#include "llsliderctrl.h"
+#include "llagent.h"
+#include "llviewborder.h"
+#include "llvoavatarself.h"
+
+LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& panel_params,
+ LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints)
+ : LLScrollingPanel( panel_params ),
+ mParam(param),
+ mAllowModify(allow_modify),
+ mWearable(wearable)
+{
+ if (use_hints)
+ buildFromFile( "panel_scrolling_param.xml");
+ else
+ buildFromFile( "panel_scrolling_param_base.xml");
+
+ getChild<LLUICtrl>("param slider")->setValue(weightToPercent(param->getWeight()));
+
+ std::string display_name = LLTrans::getString(param->getDisplayName());
+ getChild<LLUICtrl>("param slider")->setLabelArg("[DESC]", display_name);
+ getChildView("param slider")->setEnabled(mAllowModify);
+ childSetCommitCallback("param slider", LLScrollingPanelParamBase::onSliderMoved, this);
+
+ setVisible(FALSE);
+ setBorderVisible( FALSE );
+}
+
+LLScrollingPanelParamBase::~LLScrollingPanelParamBase()
+{
+}
+
+void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify)
+{
+ LLViewerVisualParam* param = mParam;
+
+ if (!mWearable)
+ {
+ // not editing a wearable just now, no update necessary
+ return;
+ }
+
+ F32 current_weight = mWearable->getVisualParamWeight( param->getID() );
+ getChild<LLUICtrl>("param slider")->setValue(weightToPercent( current_weight ) );
+ mAllowModify = allow_modify;
+ getChildView("param slider")->setEnabled(mAllowModify);
+}
+
+// static
+void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata)
+{
+ LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
+ LLScrollingPanelParamBase* self = (LLScrollingPanelParamBase*) userdata;
+ LLViewerVisualParam* param = self->mParam;
+
+ F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() );
+ F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
+ if (current_weight != new_weight )
+ {
+ self->mWearable->setVisualParamWeight( param->getID(), new_weight, FALSE );
+ self->mWearable->writeToAvatar();
+ gAgentAvatarp->updateVisualParams();
+ }
+}
+
+F32 LLScrollingPanelParamBase::weightToPercent( F32 weight )
+{
+ LLViewerVisualParam* param = mParam;
+ return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f;
+}
+
+F32 LLScrollingPanelParamBase::percentToWeight( F32 percent )
+{
+ LLViewerVisualParam* param = mParam;
+ return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
+}
diff --git a/indra/newview/llscrollingpanelparambase.h b/indra/newview/llscrollingpanelparambase.h
new file mode 100644
index 0000000000..9538826251
--- /dev/null
+++ b/indra/newview/llscrollingpanelparambase.h
@@ -0,0 +1,62 @@
+/**
+ * @file llscrollingpanelparam.h
+ * @brief the scrolling panel containing a list of visual param
+ * panels
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SCROLLINGPANELPARAMBASE_H
+#define LL_SCROLLINGPANELPARAMBASE_H
+
+#include "llpanel.h"
+#include "llscrollingpanellist.h"
+
+class LLViewerJointMesh;
+class LLViewerVisualParam;
+class LLWearable;
+class LLVisualParamHint;
+class LLViewerVisualParam;
+class LLJoint;
+
+class LLScrollingPanelParamBase : public LLScrollingPanel
+{
+public:
+ LLScrollingPanelParamBase( const LLPanel::Params& panel_params,
+ LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints = FALSE );
+ virtual ~LLScrollingPanelParamBase();
+
+ virtual void updatePanel(BOOL allow_modify);
+
+ static void onSliderMoved(LLUICtrl* ctrl, void* userdata);
+
+ F32 weightToPercent( F32 weight );
+ F32 percentToWeight( F32 percent );
+
+public:
+ LLViewerVisualParam* mParam;
+protected:
+ BOOL mAllowModify;
+ LLWearable *mWearable;
+};
+
+#endif
diff --git a/indra/newview/llsearchcombobox.cpp b/indra/newview/llsearchcombobox.cpp
index db531b5695..6558c9a7fa 100644
--- a/indra/newview/llsearchcombobox.cpp
+++ b/indra/newview/llsearchcombobox.cpp
@@ -131,6 +131,9 @@ void LLSearchComboBox::focusTextEntry()
if (mTextEntry)
{
gFocusMgr.setKeyboardFocus(mTextEntry);
+
+ // Let the editor handle editing hotkeys (STORM-431).
+ LLEditMenuHandler::gEditMenuHandler = mTextEntry;
}
}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index da891d1c51..50bc0b4a98 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -65,6 +65,7 @@
#include "llinventorymodel.h"
#include "llmenugl.h"
#include "llmutelist.h"
+#include "llnotificationsutil.h"
#include "llsidepaneltaskinfo.h"
#include "llslurl.h"
#include "llstatusbar.h"
@@ -562,6 +563,103 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
return object_found;
}
+bool LLSelectMgr::linkObjects()
+{
+ if (!LLSelectMgr::getInstance()->selectGetAllRootsValid())
+ {
+ LLNotificationsUtil::add("UnableToLinkWhileDownloading");
+ return true;
+ }
+
+ S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (object_count > MAX_CHILDREN_PER_TASK + 1)
+ {
+ LLSD args;
+ args["COUNT"] = llformat("%d", object_count);
+ int max = MAX_CHILDREN_PER_TASK+1;
+ args["MAX"] = llformat("%d", max);
+ LLNotificationsUtil::add("UnableToLinkObjects", args);
+ return true;
+ }
+
+ if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2)
+ {
+ LLNotificationsUtil::add("CannotLinkIncompleteSet");
+ return true;
+ }
+
+ if (!LLSelectMgr::getInstance()->selectGetRootsModify())
+ {
+ LLNotificationsUtil::add("CannotLinkModify");
+ return true;
+ }
+
+ LLUUID owner_id;
+ std::string owner_name;
+ if (!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name))
+ {
+ // we don't actually care if you're the owner, but novices are
+ // the most likely to be stumped by this one, so offer the
+ // easiest and most likely solution.
+ LLNotificationsUtil::add("CannotLinkDifferentOwners");
+ return true;
+ }
+
+ LLSelectMgr::getInstance()->sendLink();
+
+ return true;
+}
+
+bool LLSelectMgr::unlinkObjects()
+{
+ LLSelectMgr::getInstance()->sendDelink();
+ return true;
+}
+
+// in order to link, all objects must have the same owner, and the
+// agent must have the ability to modify all of the objects. However,
+// we're not answering that question with this method. The question
+// we're answering is: does the user have a reasonable expectation
+// that a link operation should work? If so, return true, false
+// otherwise. this allows the handle_link method to more finely check
+// the selection and give an error message when the uer has a
+// reasonable expectation for the link to work, but it will fail.
+bool LLSelectMgr::enableLinkObjects()
+{
+ bool new_value = false;
+ // check if there are at least 2 objects selected, and that the
+ // user can modify at least one of the selected objects.
+
+ // in component mode, can't link
+ if (!gSavedSettings.getBOOL("EditLinkedParts"))
+ {
+ if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2)
+ {
+ struct f : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* object)
+ {
+ return object->permModify();
+ }
+ } func;
+ const bool firstonly = true;
+ new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+ }
+ }
+ return new_value;
+}
+
+bool LLSelectMgr::enableUnlinkObjects()
+{
+ LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject();
+
+ bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() &&
+ first_editable_object &&
+ !first_editable_object->isAttachment();
+
+ return new_value;
+}
+
void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object)
{
// bail if nothing selected or if object wasn't selected in the first place
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 7478ed5f9a..cb387f5c3c 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -235,7 +235,7 @@ public:
{
bool operator()(LLSelectNode* node);
};
- typedef boost::filter_iterator<is_root, list_t::iterator > valid_root_iterator;
+ typedef boost::filter_iterator<is_valid_root, list_t::iterator > valid_root_iterator;
valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); }
valid_root_iterator valid_root_end() { return valid_root_iterator(mList.end(), mList.end()); }
@@ -440,6 +440,17 @@ public:
BOOL removeObjectFromSelections(const LLUUID &id);
////////////////////////////////////////////////////////////////
+ // Selection editing
+ ////////////////////////////////////////////////////////////////
+ bool linkObjects();
+
+ bool unlinkObjects();
+
+ bool enableLinkObjects();
+
+ bool enableUnlinkObjects();
+
+ ////////////////////////////////////////////////////////////////
// Selection accessors
////////////////////////////////////////////////////////////////
LLObjectSelectionHandle getSelection() { return mSelectedObjects; }
diff --git a/indra/newview/llshareavatarhandler.cpp b/indra/newview/llshareavatarhandler.cpp
new file mode 100644
index 0000000000..6b4f1d3dc6
--- /dev/null
+++ b/indra/newview/llshareavatarhandler.cpp
@@ -0,0 +1,67 @@
+/**
+ * @file llshareavatarhandler.cpp
+ * @brief slapp to handle sharing with an avatar
+ *
+ * $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 "llcommandhandler.h"
+#include "llavataractions.h"
+#include "llnotificationsutil.h"
+#include "llui.h"
+
+class LLShareWithAvatarHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLShareWithAvatarHandler() : LLCommandHandler("sharewithavatar", UNTRUSTED_THROTTLE)
+ {
+ }
+
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAvatarShare"))
+ {
+ LLNotificationsUtil::add("NoAvatarShare", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
+ //Make sure we have some parameters
+ if (params.size() == 0)
+ {
+ return false;
+ }
+
+ //Get the ID
+ LLUUID id;
+ if (!id.set( params[0], FALSE ))
+ {
+ return false;
+ }
+
+ //instigate share with this avatar
+ LLAvatarActions::share( id );
+ return true;
+ }
+};
+LLShareWithAvatarHandler gShareWithAvatar;
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 1999f14828..16729f045a 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -183,25 +183,38 @@ void LLSidepanelAppearance::onOpen(const LLSD& key)
void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
{
- updateToVisibility(new_visibility);
+ LLSD visibility;
+ visibility["visible"] = new_visibility.asBoolean();
+ visibility["reset_accordion"] = false;
+ updateToVisibility(visibility);
}
void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
{
- if (new_visibility.asBoolean())
+ if (new_visibility["visible"].asBoolean())
{
- bool is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
- bool is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
+ const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
+ const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
if (is_outfit_edit_visible || is_wearable_edit_visible)
{
- if (!gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
+ const LLWearable *wearable_ptr = mEditWearable->getWearable();
+ if (!wearable_ptr)
+ {
+ llwarns << "Visibility change to invalid wearable" << llendl;
+ return;
+ }
+ // Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar
+ // when editing its physics.
+ const BOOL disable_camera_motion = LLWearableType::getDisableCameraSwitch(wearable_ptr->getType());
+ if (!gAgentCamera.cameraCustomizeAvatar() &&
+ !disable_camera_motion &&
+ gSavedSettings.getBOOL("AppearanceCameraMovement"))
{
gAgentCamera.changeCameraToCustomizeAvatar();
}
if (is_wearable_edit_visible)
{
- LLWearable *wearable_ptr = mEditWearable->getWearable();
if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
{
// we're no longer wearing the wearable we were last editing, switch back to outfit editor
@@ -209,7 +222,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
}
}
- if (is_outfit_edit_visible)
+ if (is_outfit_edit_visible && new_visibility["reset_accordion"].asBoolean())
{
mOutfitEdit->resetAccordionState();
}
@@ -286,7 +299,7 @@ void LLSidepanelAppearance::showOutfitsInventoryPanel()
{
toggleWearableEditPanel(FALSE);
toggleOutfitEditPanel(FALSE);
- togglMyOutfitsPanel(TRUE);
+ toggleMyOutfitsPanel(TRUE);
}
void LLSidepanelAppearance::showOutfitEditPanel()
@@ -302,19 +315,28 @@ void LLSidepanelAppearance::showOutfitEditPanel()
mOutfitEdit->resetAccordionState();
}
- togglMyOutfitsPanel(FALSE);
+ // If we're exiting the edit wearable view, and the camera was not focused on the avatar
+ // (e.g. such as if we were editing a physics param), then skip the outfits edit mode since
+ // otherwise this would trigger the camera focus mode.
+ if (mEditWearable != NULL && mEditWearable->getVisible() && !gAgentCamera.cameraCustomizeAvatar())
+ {
+ showOutfitsInventoryPanel();
+ return;
+ }
+
+ toggleMyOutfitsPanel(FALSE);
toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode
toggleOutfitEditPanel(TRUE);
}
-void LLSidepanelAppearance::showWearableEditPanel(LLWearable *wearable /* = NULL*/)
+void LLSidepanelAppearance::showWearableEditPanel(LLWearable *wearable /* = NULL*/, BOOL disable_camera_switch)
{
- togglMyOutfitsPanel(FALSE);
+ toggleMyOutfitsPanel(FALSE);
toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode
- toggleWearableEditPanel(TRUE, wearable);
+ toggleWearableEditPanel(TRUE, wearable, disable_camera_switch);
}
-void LLSidepanelAppearance::togglMyOutfitsPanel(BOOL visible)
+void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible)
{
if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible)
{
@@ -387,7 +409,7 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we
{
gAgentCamera.changeCameraToCustomizeAvatar();
}
- mEditWearable->setWearable(wearable);
+ mEditWearable->setWearable(wearable, disable_camera_switch);
mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency
}
else
@@ -431,14 +453,14 @@ void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
}
//static
-void LLSidepanelAppearance::editWearable(LLWearable *wearable, LLView *data)
+void LLSidepanelAppearance::editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch)
{
LLSideTray::getInstance()->showPanel("sidepanel_appearance");
LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data);
if (panel)
{
- panel->showWearableEditPanel(wearable);
+ panel->showWearableEditPanel(wearable, disable_camera_switch);
}
}
diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h
index 2a83dfbc9d..6dd3520266 100644
--- a/indra/newview/llsidepanelappearance.h
+++ b/indra/newview/llsidepanelappearance.h
@@ -51,7 +51,7 @@ public:
void refreshCurrentOutfitName(const std::string& name = "");
- static void editWearable(LLWearable *wearable, LLView *data);
+ static void editWearable(LLWearable *wearable, LLView *data, BOOL disable_camera_switch = FALSE);
void fetchInventory();
void inventoryFetched();
@@ -59,7 +59,7 @@ public:
void showOutfitsInventoryPanel();
void showOutfitEditPanel();
- void showWearableEditPanel(LLWearable *wearable = NULL);
+ void showWearableEditPanel(LLWearable *wearable = NULL, BOOL disable_camera_switch = FALSE);
void setWearablesLoading(bool val);
void showDefaultSubpart();
void updateScrollingPanelList();
@@ -72,7 +72,7 @@ private:
void onOpenOutfitButtonClicked();
void onEditAppearanceButtonClicked();
- void togglMyOutfitsPanel(BOOL visible);
+ void toggleMyOutfitsPanel(BOOL visible);
void toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch = FALSE);
void toggleWearableEditPanel(BOOL visible, LLWearable* wearable = NULL, BOOL disable_camera_switch = FALSE);
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index f9c0fd398e..c8c6858b81 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& item_id = mFloater->getItemID();
+
+ 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 == item_id)
+ {
+ // if there's a change we're interested in.
+ if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
+ {
+ mFloater->dirty();
+ }
+ }
}
}
@@ -179,6 +191,16 @@ void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
mItemID = item_id;
}
+const LLUUID& LLSidepanelItemInfo::getObjectID() const
+{
+ return mObjectID;
+}
+
+const LLUUID& LLSidepanelItemInfo::getItemID() const
+{
+ return mItemID;
+}
+
void LLSidepanelItemInfo::reset()
{
LLSidepanelInventorySubpanel::reset();
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 10e93dd7de..25be145f64 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -54,6 +54,9 @@ public:
void setItemID(const LLUUID& item_id);
void setEditMode(BOOL edit);
+ const LLUUID& getObjectID() const;
+ const LLUUID& getItemID() const;
+
protected:
/*virtual*/ void refresh();
/*virtual*/ void save();
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 47d904dfcc..8774482acd 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -1120,17 +1120,17 @@ void LLSidepanelTaskInfo::updateVerbs()
*/
LLSafeHandle<LLObjectSelection> object_selection = LLSelectMgr::getInstance()->getSelection();
- const BOOL multi_select = (object_selection->getNumNodes() > 1);
+ const BOOL any_selected = (object_selection->getNumNodes() > 0);
- mOpenBtn->setVisible(!multi_select);
- mPayBtn->setVisible(!multi_select);
- mBuyBtn->setVisible(!multi_select);
- mDetailsBtn->setVisible(multi_select);
- mDetailsBtn->setEnabled(multi_select);
+ mOpenBtn->setVisible(true);
+ mPayBtn->setVisible(true);
+ mBuyBtn->setVisible(true);
+ mDetailsBtn->setVisible(true);
mOpenBtn->setEnabled(enable_object_open());
mPayBtn->setEnabled(enable_pay_object());
mBuyBtn->setEnabled(enable_buy_object());
+ mDetailsBtn->setEnabled(any_selected);
}
void LLSidepanelTaskInfo::onOpenButtonClicked()
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 81b2fc0ae0..fcd200d24a 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -96,6 +96,7 @@ bool LLSideTray::instanceCreated ()
class LLSideTrayTab: public LLPanel
{
+ LOG_CLASS(LLSideTrayTab);
friend class LLUICtrlFactory;
friend class LLSideTray;
public:
@@ -118,10 +119,12 @@ public:
protected:
LLSideTrayTab(const Params& params);
- void dock();
+ void dock(LLFloater* floater_tab);
void undock(LLFloater* floater_tab);
LLSideTray* getSideTray();
+
+ void onFloaterClose(LLSD::Boolean app_quitting);
public:
virtual ~LLSideTrayTab();
@@ -140,6 +143,10 @@ public:
void onOpen (const LLSD& key);
void toggleTabDocked();
+ void setDocked(bool dock);
+ bool isDocked() const;
+
+ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
LLPanel *getPanel();
private:
@@ -149,6 +156,7 @@ private:
std::string mDescription;
LLView* mMainPanel;
+ boost::signals2::connection mFloaterCloseConn;
};
LLSideTrayTab::LLSideTrayTab(const Params& p)
@@ -159,8 +167,6 @@ LLSideTrayTab::LLSideTrayTab(const Params& p)
mDescription(p.description),
mMainPanel(NULL)
{
- // Necessary for focus movement among child controls
- setFocusRoot(TRUE);
}
LLSideTrayTab::~LLSideTrayTab()
@@ -259,7 +265,7 @@ void LLSideTrayTab::toggleTabDocked()
if (docking)
{
- dock();
+ dock(floater_tab);
}
else
{
@@ -271,17 +277,59 @@ void LLSideTrayTab::toggleTabDocked()
LLFloaterReg::toggleInstance("side_bar_tab", tab_name);
}
-void LLSideTrayTab::dock()
+// Same as toggleTabDocked() apart from making sure that we do exactly what we want.
+void LLSideTrayTab::setDocked(bool dock)
+{
+ if (isDocked() == dock)
+ {
+ llwarns << "Tab " << getName() << " is already " << (dock ? "docked" : "undocked") << llendl;
+ return;
+ }
+
+ toggleTabDocked();
+}
+
+bool LLSideTrayTab::isDocked() const
+{
+ return dynamic_cast<LLSideTray*>(getParent()) != NULL;
+}
+
+void LLSideTrayTab::onFloaterClose(LLSD::Boolean app_quitting)
+{
+ // If user presses Ctrl-Shift-W, handle that gracefully by docking all
+ // undocked tabs before their floaters get destroyed (STORM-1016).
+
+ // Don't dock on quit for the current dock state to be correctly saved.
+ if (app_quitting) return;
+
+ lldebugs << "Forcibly docking tab " << getName() << llendl;
+ setDocked(true);
+}
+
+BOOL LLSideTrayTab::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ // Let children handle the event
+ LLUICtrl::handleScrollWheel(x, y, clicks);
+
+ // and then eat it to prevent in-world scrolling (STORM-351).
+ return TRUE;
+}
+
+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;
return;
}
+ mFloaterCloseConn.disconnect();
setRect(side_tray->getLocalRect());
reshape(getRect().getWidth(), getRect().getHeight());
@@ -298,7 +346,11 @@ static void on_minimize(LLSidepanelAppearance* panel, LLSD minimized)
{
if (!panel) return;
bool visible = !minimized.asBoolean();
- panel->updateToVisibility(LLSD(visible));
+ LLSD visibility;
+ visibility["visible"] = visible;
+ // Do not reset accordion state on minimize (STORM-375)
+ visibility["reset_accordion"] = false;
+ panel->updateToVisibility(visibility);
}
void LLSideTrayTab::undock(LLFloater* floater_tab)
@@ -326,6 +378,7 @@ void LLSideTrayTab::undock(LLFloater* floater_tab)
}
floater_tab->addChild(this);
+ mFloaterCloseConn = floater_tab->setCloseCallback(boost::bind(&LLSideTrayTab::onFloaterClose, this, _2));
floater_tab->setTitle(mTabTitle);
floater_tab->setName(getName());
@@ -493,8 +546,8 @@ private:
LLSideTray::Params::Params()
: collapsed("collapsed",false),
- tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")),
- tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")),
+ tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")),
+ tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")),
default_button_width("tab_btn_width",32),
default_button_height("tab_btn_height",32),
default_button_margin("tab_btn_margin",0)
@@ -556,7 +609,7 @@ BOOL LLSideTray::postBuild()
{
if ((*it).channel)
{
- getCollapseSignal().connect(boost::bind(&LLScreenChannelBase::resetPositionAndSize, (*it).channel, _2));
+ setVisibleWidthChangeCallback(boost::bind(&LLScreenChannelBase::resetPositionAndSize, (*it).channel));
}
}
@@ -613,8 +666,16 @@ LLPanel* LLSideTray::openChildPanel(LLSideTrayTab* tab, const std::string& panel
std::string tab_name = tab->getName();
+ bool tab_attached = isTabAttached(tab_name);
+
+ if (tab_attached && LLUI::sSettingGroups["config"]->getBOOL("OpenSidePanelsInFloaters"))
+ {
+ tab->toggleTabDocked();
+ tab_attached = false;
+ }
+
// Select tab and expand Side Tray only when a tab is attached.
- if (isTabAttached(tab_name))
+ if (tab_attached)
{
selectTabByName(tab_name);
if (mCollapsed)
@@ -625,14 +686,7 @@ LLPanel* LLSideTray::openChildPanel(LLSideTrayTab* tab, const std::string& panel
LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab_name);
if (!floater_tab) return NULL;
- // Restore the floater if it was minimized.
- if (floater_tab->isMinimized())
- {
- floater_tab->setMinimized(FALSE);
- }
-
- // Send the floater to the front.
- floater_tab->setFrontmost();
+ floater_tab->openFloater(tab_name);
}
LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());
@@ -910,7 +964,6 @@ void LLSideTray::createButtons ()
}
}
LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle());
- LLHints::registerHintTarget("dest_guide_btn", mTabButtons["sidebar_places"]->getHandle());
}
void LLSideTray::processTriState ()
@@ -964,21 +1017,9 @@ void LLSideTray::reflectCollapseChange()
{
updateSidetrayVisibility();
- if(mCollapsed)
- {
- gFloaterView->setSnapOffsetRight(0);
- setFocus(FALSE);
- }
- else
- {
- gFloaterView->setSnapOffsetRight(getRect().getWidth());
- setFocus(TRUE);
- }
+ setFocus(!mCollapsed);
gFloaterView->refresh();
-
- LLSD new_value = mCollapsed;
- mCollapseSignal(this,new_value);
}
void LLSideTray::arrange()
@@ -1028,7 +1069,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.
@@ -1148,23 +1190,43 @@ void LLSideTray::reshape(S32 width, S32 height, BOOL called_from_parent)
*/
LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& params)
{
+ LLPanel* new_panel = NULL;
+
// Look up the tab in the list of detached tabs.
child_vector_const_iter_t child_it;
for ( child_it = mDetachedTabs.begin(); child_it != mDetachedTabs.end(); ++child_it)
{
- LLPanel* panel = openChildPanel(*child_it, panel_name, params);
- if (panel) return panel;
- }
+ new_panel = openChildPanel(*child_it, panel_name, params);
+ if (new_panel) break;
+ }
// Look up the tab in the list of attached tabs.
for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
- {
- LLPanel* panel = openChildPanel(*child_it, panel_name, params);
- if (panel) return panel;
+ {
+ new_panel = openChildPanel(*child_it, panel_name, params);
+ if (new_panel) break;
}
- return NULL;
+
+ return new_panel;
}
+void LLSideTray::hidePanel(const std::string& panel_name)
+{
+ LLPanel* panelp = getPanel(panel_name);
+ if (panelp)
+ {
+ if(isTabAttached(panel_name))
+ {
+ collapseSideBar();
+ }
+ else
+ {
+ LLFloaterReg::hideInstance("side_bar_tab", panel_name);
+ }
+ }
+}
+
+
void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params)
{
if(!sub_panel)
@@ -1254,12 +1316,68 @@ bool LLSideTray::isPanelActive(const std::string& panel_name)
return (panel->getName() == panel_name);
}
+void LLSideTray::setTabDocked(const std::string& tab_name, bool dock)
+{
+ LLSideTrayTab* tab = getTab(tab_name);
+ if (!tab)
+ { // not a docked tab, look through detached tabs
+ for(child_vector_iter_t tab_it = mDetachedTabs.begin(), tab_end_it = mDetachedTabs.end();
+ tab_it != tab_end_it;
+ ++tab_it)
+ {
+ if ((*tab_it)->getName() == tab_name)
+ {
+ tab = *tab_it;
+ break;
+ }
+ }
+
+ }
+
+ if (tab)
+ {
+ bool tab_attached = isTabAttached(tab_name);
+ LLFloater* floater_tab = LLFloaterReg::getInstance("side_bar_tab", tab_name);
+ if (!floater_tab) return;
+
+ if (dock && !tab_attached)
+ {
+ tab->dock(floater_tab);
+ }
+ else if (!dock && tab_attached)
+ {
+ tab->undock(floater_tab);
+ }
+ }
+}
+
+
void LLSideTray::updateSidetrayVisibility()
{
// set visibility of parent container based on collapsed state
- if (getParent())
+ LLView* parent = getParent();
+ if (parent)
{
- getParent()->setVisible(!mCollapsed && !gAgentCamera.cameraMouselook());
+ bool old_visibility = parent->getVisible();
+ bool new_visibility = !mCollapsed && !gAgentCamera.cameraMouselook();
+
+ if (old_visibility != new_visibility)
+ {
+ parent->setVisible(new_visibility);
+
+ // Signal change of visible width.
+ llinfos << "Visible: " << new_visibility << llendl;
+ mVisibleWidthChangeSignal(this, new_visibility);
+ }
}
}
+S32 LLSideTray::getVisibleWidth()
+{
+ return (isInVisibleChain() && !mCollapsed) ? getRect().getWidth() : 0;
+}
+
+void LLSideTray::setVisibleWidthChangeCallback(const commit_signal_t::slot_type& cb)
+{
+ mVisibleWidthChangeSignal.connect(cb);
+}
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 4c23a1920b..2516b5689f 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);
@@ -95,6 +97,8 @@ public:
*/
LLPanel* showPanel (const std::string& panel_name, const LLSD& params = LLSD());
+ void hidePanel (const std::string& panel_name);
+
/**
* Toggling Side Tray tab which contains "sub_panel" child of "panel_name" panel.
* If "sub_panel" is not visible Side Tray is opened to display it,
@@ -110,6 +114,8 @@ public:
LLPanel* getActivePanel ();
bool isPanelActive (const std::string& panel_name);
+ void setTabDocked(const std::string& tab_name, bool dock);
+
/*
* get the panel of given type T (don't show it or do anything else with it)
*/
@@ -126,11 +132,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 +164,37 @@ 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; }
+ /**
+ * @return side tray width if it's visible and expanded, 0 otherwise.
+ *
+ * Not that width of the tab buttons is not included.
+ *
+ * @see setVisibleWidthChangeCallback()
+ */
+ S32 getVisibleWidth();
- void handleLoginComplete();
+ void setVisibleWidthChangeCallback(const commit_signal_t::slot_type& cb);
+
+ void updateSidetrayVisibility();
- LLSideTrayTab* getTab (const std::string& name);
+ void handleLoginComplete();
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 +202,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()
@@ -209,7 +219,7 @@ private:
if (LLSideTray::instanceCreated())
LLSideTray::getInstance()->setEnabled(FALSE);
}
-
+
private:
LLPanel* mButtonsPanel;
typedef std::map<std::string,LLButton*> button_map_t;
@@ -219,7 +229,7 @@ private:
tab_order_vector_t mOriginalTabOrder;
LLSideTrayTab* mActiveTab;
- commit_signal_t mCollapseSignal;
+ commit_signal_t mVisibleWidthChangeSignal;
LLButton* mCollapseButton;
bool mCollapsed;
diff --git a/indra/newview/llsimplestat.h b/indra/newview/llsimplestat.h
new file mode 100644
index 0000000000..9d7780c4f9
--- /dev/null
+++ b/indra/newview/llsimplestat.h
@@ -0,0 +1,152 @@
+/**
+ * @file llsimplestat.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $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_SIMPLESTAT_H
+#define LL_SIMPLESTAT_H
+
+// History
+//
+// The original source for this code is the server repositories'
+// llcommon/llstat.h file. This particular code was added after the
+// viewer/server code schism but before the effort to convert common
+// code to libraries was complete. Rather than add to merge issues,
+// the needed code was cut'n'pasted into this new header as it isn't
+// too awful a burden. Post-modularization, we can look at removing
+// this redundancy.
+
+
+/**
+ * @class LLSimpleStatCounter
+ * @brief Just counts events.
+ *
+ * Really not needed but have a pattern in mind in the future.
+ * Interface limits what can be done at that's just fine.
+ *
+ * *TODO: Update/transfer unit tests
+ * Unit tests: indra/test/llcommon_llstat_tut.cpp
+ */
+class LLSimpleStatCounter
+{
+public:
+ inline LLSimpleStatCounter() { reset(); }
+ // Default destructor and assignment operator are valid
+
+ inline void reset() { mCount = 0; }
+
+ inline void merge(const LLSimpleStatCounter & src)
+ { mCount += src.mCount; }
+
+ inline U32 operator++() { return ++mCount; }
+
+ inline U32 getCount() const { return mCount; }
+
+protected:
+ U32 mCount;
+};
+
+
+/**
+ * @class LLSimpleStatMMM
+ * @brief Templated collector of min, max and mean data for stats.
+ *
+ * Fed a stream of data samples, keeps a running account of the
+ * min, max and mean seen since construction or the last reset()
+ * call. A freshly-constructed or reset instance returns counts
+ * and values of zero.
+ *
+ * Overflows and underflows (integer, inf or -inf) and NaN's
+ * are the caller's problem. As is loss of precision when
+ * the running sum's exponent (when parameterized by a floating
+ * point of some type) differs from a given data sample's.
+ *
+ * Unit tests: indra/test/llcommon_llstat_tut.cpp
+ */
+template <typename VALUE_T = F32>
+class LLSimpleStatMMM
+{
+public:
+ typedef VALUE_T Value;
+
+public:
+ LLSimpleStatMMM() { reset(); }
+ // Default destructor and assignment operator are valid
+
+ /**
+ * Resets the object returning all counts and derived
+ * values back to zero.
+ */
+ void reset()
+ {
+ mCount = 0;
+ mMin = Value(0);
+ mMax = Value(0);
+ mTotal = Value(0);
+ }
+
+ void record(Value v)
+ {
+ if (mCount)
+ {
+ mMin = llmin(mMin, v);
+ mMax = llmax(mMax, v);
+ }
+ else
+ {
+ mMin = v;
+ mMax = v;
+ }
+ mTotal += v;
+ ++mCount;
+ }
+
+ void merge(const LLSimpleStatMMM<VALUE_T> & src)
+ {
+ if (! mCount)
+ {
+ *this = src;
+ }
+ else if (src.mCount)
+ {
+ mMin = llmin(mMin, src.mMin);
+ mMax = llmax(mMax, src.mMax);
+ mCount += src.mCount;
+ mTotal += src.mTotal;
+ }
+ }
+
+ inline U32 getCount() const { return mCount; }
+ inline Value getMin() const { return mMin; }
+ inline Value getMax() const { return mMax; }
+ inline Value getMean() const { return mCount ? mTotal / mCount : mTotal; }
+
+protected:
+ U32 mCount;
+ Value mMin;
+ Value mMax;
+ Value mTotal;
+};
+
+#endif // LL_SIMPLESTAT_H
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index fb984a7c62..8adb8c30e0 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);
@@ -2560,6 +2578,49 @@ void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)
gGL.end();
}
+void renderUpdateType(LLDrawable* drawablep)
+{
+ LLViewerObject* vobj = drawablep->getVObj();
+ if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType())
+ {
+ return;
+ }
+ LLGLEnable blend(GL_BLEND);
+ switch (vobj->getLastUpdateType())
+ {
+ case OUT_FULL:
+ glColor4f(0,1,0,0.5f);
+ break;
+ case OUT_TERSE_IMPROVED:
+ glColor4f(0,1,1,0.5f);
+ break;
+ case OUT_FULL_COMPRESSED:
+ if (vobj->getLastUpdateCached())
+ {
+ glColor4f(1,0,0,0.5f);
+ }
+ else
+ {
+ glColor4f(1,1,0,0.5f);
+ }
+ break;
+ case OUT_FULL_CACHED:
+ glColor4f(0,0,1,0.5f);
+ break;
+ default:
+ llwarns << "Unknown update_type " << vobj->getLastUpdateType() << llendl;
+ break;
+ };
+ S32 num_faces = drawablep->getNumFaces();
+ if (num_faces)
+ {
+ for (S32 i = 0; i < num_faces; ++i)
+ {
+ pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
+ }
+ }
+}
+
void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
{
@@ -2591,9 +2652,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;
@@ -2999,6 +3061,10 @@ public:
{
renderRaycast(drawable);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE))
+ {
+ renderUpdateType(drawable);
+ }
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get());
@@ -3161,6 +3227,7 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_OCCLUSION |
LLPipeline::RENDER_DEBUG_LIGHTS |
LLPipeline::RENDER_DEBUG_BATCH_SIZE |
+ LLPipeline::RENDER_DEBUG_UPDATE_TYPE |
LLPipeline::RENDER_DEBUG_BBOXES |
LLPipeline::RENDER_DEBUG_POINTS |
LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
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..d52e0a6c86 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -38,6 +38,7 @@
#include "llspeakbutton.h"
#include "llbottomtray.h"
+#include "llfirstuse.h"
static LLDefaultChildRegistry::Register<LLSpeakButton> t1("talk_button");
@@ -134,8 +135,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)
@@ -173,6 +177,7 @@ void LLSpeakButton::onMouseDown_SpeakBtn()
{
bool down = true;
LLVoiceClient::getInstance()->inputUserControlState(down); // this method knows/care about whether this translates into a toggle-to-talk or down-to-talk
+ LLFirstUse::speak(false);
}
void LLSpeakButton::onMouseUp_SpeakBtn()
{
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..8fccb35886 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -139,6 +139,7 @@
#include "lltrans.h"
#include "llui.h"
#include "llurldispatcher.h"
+#include "llurlentry.h"
#include "llslurl.h"
#include "llurlhistory.h"
#include "llurlwhitelist.h"
@@ -198,6 +199,7 @@
// exported globals
//
bool gAgentMovementCompleted = false;
+S32 gMaxAgentGroups;
std::string SCREEN_HOME_FILENAME = "screen_home.bmp";
std::string SCREEN_LAST_FILENAME = "screen_last.bmp";
@@ -232,6 +234,8 @@ static LLHost gFirstSim;
static std::string gFirstSimSeedCap;
static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f);
static std::string gAgentStartLocation = "safe";
+static bool mLoginStatePastUI = false;
+
boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener());
@@ -705,7 +709,15 @@ bool idle_startup()
if (STATE_LOGIN_SHOW == LLStartUp::getStartupState())
{
LL_DEBUGS("AppInit") << "Initializing Window" << LL_ENDL;
-
+
+ // if we've gone backwards in the login state machine, to this state where we show the UI
+ // AND the debug setting to exit in this case is true, then go ahead and bail quickly
+ if ( mLoginStatePastUI && gSavedSettings.getBOOL("QuitOnLoginActivated") )
+ {
+ // no requirement for notification here - just exit
+ LLAppViewer::instance()->earlyExitNoNotify();
+ }
+
gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
timeout_count = 0;
@@ -737,8 +749,6 @@ bool idle_startup()
}
LLPanelLogin::giveFocus();
- gSavedSettings.setBOOL("FirstRunThisInstall", FALSE);
-
LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input
}
else
@@ -763,6 +773,7 @@ bool idle_startup()
gViewerWindow->setNormalControlsVisible( FALSE );
gLoginMenuBarView->setVisible( TRUE );
gLoginMenuBarView->setEnabled( TRUE );
+ show_debug_menus();
// Hide the splash screen
LLSplashScreen::hide();
@@ -783,6 +794,11 @@ bool idle_startup()
if (STATE_LOGIN_WAIT == LLStartUp::getStartupState())
{
+ // when we get to this state, we've already been past the login UI
+ // (possiblely automatically) - flag this so we can test in the
+ // STATE_LOGIN_SHOW state if we've gone backwards
+ mLoginStatePastUI = true;
+
// Don't do anything. Wait for the login view to call the login_callback,
// which will push us to the next state.
@@ -809,6 +825,11 @@ bool idle_startup()
gKeyboard->resetKeys();
}
+ // when we get to this state, we've already been past the login UI
+ // (possiblely automatically) - flag this so we can test in the
+ // STATE_LOGIN_SHOW state if we've gone backwards
+ mLoginStatePastUI = true;
+
// save the credentials
std::string userid = "unknown";
if(gUserCredential.notNull())
@@ -959,7 +980,6 @@ bool idle_startup()
login->setSkipOptionalUpdate(true);
}
- login->setUserInteraction(show_connect_box);
login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
login->setLastExecEvent(gLastExecEvent);
login->setUpdaterLauncher(boost::bind(&LLAppViewer::launchUpdater, LLAppViewer::instance()));
@@ -1682,9 +1702,6 @@ bool idle_startup()
// Set the show start location to true, now that the user has logged
// on with this install.
gSavedSettings.setBOOL("ShowStartLocation", TRUE);
-
- LLSideTray::getInstance()->showPanel("panel_home", LLSD());
-
}
// We're successfully logged in.
@@ -2861,9 +2878,17 @@ bool process_login_success_response()
if(!text.empty()) gAgentID.set(text);
gDebugInfo["AgentID"] = text;
+ // Agent id needed for parcel info request in LLUrlEntryParcel
+ // to resolve parcel name.
+ LLUrlEntryParcel::setAgentID(gAgentID);
+
text = response["session_id"].asString();
if(!text.empty()) gAgentSessionID.set(text);
gDebugInfo["SessionID"] = text;
+
+ // Session id needed for parcel info request in LLUrlEntryParcel
+ // to resolve parcel name.
+ LLUrlEntryParcel::setSessionID(gAgentSessionID);
text = response["secure_session_id"].asString();
if(!text.empty()) gAgent.mSecureSessionID.set(text);
@@ -3074,7 +3099,16 @@ bool process_login_success_response()
std::string map_server_url = response["map-server-url"];
if(!map_server_url.empty())
{
- gSavedSettings.setString("MapServerURL", map_server_url);
+ // We got an answer from the grid -> use that for map for the current session
+ gSavedSettings.setString("CurrentMapServerURL", map_server_url);
+ LL_INFOS("LLStartup") << "map-server-url : we got an answer from the grid : " << map_server_url << LL_ENDL;
+ }
+ else
+ {
+ // No answer from the grid -> use the default setting for current session
+ map_server_url = gSavedSettings.getString("MapServerURL");
+ gSavedSettings.setString("CurrentMapServerURL", map_server_url);
+ LL_INFOS("LLStartup") << "map-server-url : no map-server-url answer, we use the default setting for the map : " << map_server_url << LL_ENDL;
}
// Default male and female avatars allowing the user to choose their avatar on first login.
@@ -3151,6 +3185,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/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index e9fc25404a..1b8be7a5b2 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -115,6 +115,7 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
mSGBandwidth(NULL),
mSGPacketLoss(NULL),
mBtnVolume(NULL),
+ mBoxBalance(NULL),
mBalance(0),
mHealth(100),
mSquareMetersCredit(0),
@@ -168,6 +169,9 @@ BOOL LLStatusBar::postBuild()
getChild<LLUICtrl>("buyL")->setCommitCallback(
boost::bind(&LLStatusBar::onClickBuyCurrency, this));
+ mBoxBalance = getChild<LLTextBox>("balance");
+ mBoxBalance->setClickedCallback( &LLStatusBar::onClickBalance, this );
+
mBtnVolume = getChild<LLButton>( "volume_btn" );
mBtnVolume->setClickedCallback( onClickVolume, this );
mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this));
@@ -304,6 +308,7 @@ void LLStatusBar::setVisibleForMouselook(bool visible)
{
mTextTime->setVisible(visible);
getChild<LLUICtrl>("balance_bg")->setVisible(visible);
+ mBoxBalance->setVisible(visible);
mBtnVolume->setVisible(visible);
mMediaToggle->setVisible(visible);
mSGBandwidth->setVisible(visible);
@@ -330,16 +335,15 @@ void LLStatusBar::setBalance(S32 balance)
std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance );
- LLTextBox* balance_box = getChild<LLTextBox>("balance");
LLStringUtil::format_map_t string_args;
string_args["[AMT]"] = llformat("%s", money_str.c_str());
std::string label_str = getString("buycurrencylabel", string_args);
- balance_box->setValue(label_str);
+ mBoxBalance->setValue(label_str);
// Resize the L$ balance background to be wide enough for your balance plus the buy button
{
const S32 HPAD = 24;
- LLRect balance_rect = balance_box->getTextBoundingRect();
+ LLRect balance_rect = mBoxBalance->getTextBoundingRect();
LLRect buy_rect = getChildView("buyL")->getRect();
LLView* balance_bg_view = getChildView("balance_bg");
LLRect balance_bg_rect = balance_bg_view->getRect();
@@ -506,6 +510,14 @@ static void onClickVolume(void* data)
}
//static
+void LLStatusBar::onClickBalance(void* )
+{
+ // Force a balance request message:
+ LLStatusBar::sendMoneyBalanceRequest();
+ // The refresh of the display (call to setBalance()) will be done by process_money_balance_reply()
+}
+
+//static
void LLStatusBar::onClickMediaToggle(void* data)
{
LLStatusBar *status_bar = (LLStatusBar*)data;
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index 2388aeb0c8..4ea3183d18 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -94,6 +94,7 @@ private:
void onClickScreen(S32 x, S32 y);
static void onClickMediaToggle(void* data);
+ static void onClickBalance(void* data);
private:
LLTextBox *mTextTime;
@@ -102,6 +103,7 @@ private:
LLStatGraph *mSGPacketLoss;
LLButton *mBtnVolume;
+ LLTextBox *mBoxBalance;
LLButton *mMediaToggle;
LLView* mScriptOut;
LLFrameTimer mClockUpdateTimer;
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/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 6a213309a0..7fb52c1939 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -326,6 +326,7 @@ bool LLTextureCacheRemoteWorker::doRead()
// First state / stage : find out if the file is local
if (mState == INIT)
{
+#if 0
std::string filename = mCache->getLocalFileName(mID);
// Is it a JPEG2000 file?
{
@@ -360,6 +361,11 @@ bool LLTextureCacheRemoteWorker::doRead()
}
// Determine the next stage: if we found a file, then LOCAL else CACHE
mState = (local_size > 0 ? LOCAL : CACHE);
+
+ llassert_always(mState == CACHE) ;
+#else
+ mState = CACHE;
+#endif
}
// Second state / stage : if the file is local, load it and leave
@@ -1413,22 +1419,21 @@ void LLTextureCache::readHeaderCache()
}
}
}
- if (num_entries > sCacheMaxEntries)
+ if (num_entries - empty_entries > sCacheMaxEntries)
{
// Special case: cache size was reduced, need to remove entries
// Note: After we prune entries, we will call this again and create the LRU
- U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries;
+ U32 entries_to_purge = (num_entries - empty_entries) - sCacheMaxEntries;
llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl;
- if (entries_to_purge > 0)
+ // We can exit the following loop with the given condition, since if we'd reach the end of the lru set we'd have:
+ // purge_list.size() = lru.size() = num_entries - empty_entries = entries_to_purge + sCacheMaxEntries >= entries_to_purge
+ // So, it's certain that iter will never reach lru.end() first.
+ std::set<lru_data_t>::iterator iter = lru.begin();
+ while (purge_list.size() < entries_to_purge)
{
- for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter)
- {
- purge_list.insert(iter->second);
- if (purge_list.size() >= entries_to_purge)
- break;
- }
+ purge_list.insert(iter->second);
+ ++iter;
}
- llassert_always(purge_list.size() >= entries_to_purge);
}
else
{
@@ -1592,7 +1597,7 @@ void LLTextureCache::purgeTextures(bool validate)
if (validate)
{
validate_idx = gSavedSettings.getU32("CacheValidateCounter");
- U32 next_idx = (++validate_idx) % 256;
+ U32 next_idx = (validate_idx + 1) % 256;
gSavedSettings.setU32("CacheValidateCounter", next_idx);
LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Validating: " << validate_idx << LL_ENDL;
}
@@ -1858,8 +1863,22 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id)
//called after mHeaderMutex is locked.
void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
{
+ bool file_maybe_exists = true; // Always attempt to remove when idx is invalid.
+
if(idx >= 0) //valid entry
{
+ if (entry.mBodySize == 0) // Always attempt to remove when mBodySize > 0.
+ {
+ if (LLAPRFile::isExist(filename, getLocalAPRFilePool())) // Sanity check. Shouldn't exist when body size is 0.
+ {
+ LL_WARNS("TextureCache") << "Entry has body size of zero but file " << filename << " exists. Deleting this file, too." << LL_ENDL;
+ }
+ else
+ {
+ file_maybe_exists = false;
+ }
+ }
+
entry.mImageSize = -1;
entry.mBodySize = 0;
mHeaderIDMap.erase(entry.mID);
@@ -1869,7 +1888,10 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
mFreeList.insert(idx);
}
- LLAPRFile::remove(filename, getLocalAPRFilePool());
+ if (file_maybe_exists)
+ {
+ LLAPRFile::remove(filename, getLocalAPRFilePool());
+ }
}
bool LLTextureCache::removeFromCache(const LLUUID& id)
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..18c3a3b87d 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include <iostream>
+#include <map>
#include "llstl.h"
@@ -49,6 +50,7 @@
#include "llviewertexture.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
+#include "llviewerassetstats.h"
#include "llworld.h"
//////////////////////////////////////////////////////////////////////////////
@@ -143,7 +145,7 @@ public:
/*virtual*/ bool deleteOK(); // called from update() (WORK THREAD)
~LLTextureFetchWorker();
- void relese() { --mActiveCount; }
+ // void relese() { --mActiveCount; }
S32 callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
@@ -161,9 +163,11 @@ public:
mGetReason = reason;
}
- void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}
- bool getCanUseHTTP()const {return mCanUseHTTP ;}
+ void setCanUseHTTP(bool can_use_http) { mCanUseHTTP = can_use_http; }
+ bool getCanUseHTTP() const { return mCanUseHTTP; }
+ LLTextureFetch & getFetcher() { return *mFetcher; }
+
protected:
LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host,
F32 priority, S32 discard, S32 size);
@@ -277,6 +281,8 @@ private:
S32 mLastPacket;
U16 mTotalPackets;
U8 mImageCodec;
+
+ LLViewerAssetStats::duration_t mMetricsStartTime;
};
//////////////////////////////////////////////////////////////////////////////
@@ -299,6 +305,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,7 +339,29 @@ 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);
+
+ if (worker->mMetricsStartTime)
+ {
+ LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE,
+ true,
+ LLImageBase::TYPE_AVATAR_BAKE == worker->mType,
+ LLViewerAssetStatsFF::get_timestamp() - worker->mMetricsStartTime);
+ worker->mMetricsStartTime = 0;
+ }
+ LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE,
+ true,
+ LLImageBase::TYPE_AVATAR_BAKE == worker->mType);
}
else
{
@@ -357,6 +386,229 @@ private:
//////////////////////////////////////////////////////////////////////////////
+// Cross-thread messaging for asset metrics.
+
+/**
+ * @brief Base class for cross-thread requests made of the fetcher
+ *
+ * I believe the intent of the LLQueuedThread class was to
+ * have these operations derived from LLQueuedThread::QueuedRequest
+ * but the texture fetcher has elected to manage the queue
+ * in its own manner. So these are free-standing objects which are
+ * managed in simple FIFO order on the mCommands queue of the
+ * LLTextureFetch object.
+ *
+ * What each represents is a simple command sent from an
+ * outside thread into the TextureFetch thread to be processed
+ * in order and in a timely fashion (though not an absolute
+ * higher priority than other operations of the thread).
+ * Each operation derives a new class from the base customizing
+ * members, constructors and the doWork() method to effect
+ * the command.
+ *
+ * The flow is one-directional. There are two global instances
+ * of the LLViewerAssetStats collector, one for the main program's
+ * thread pointed to by gViewerAssetStatsMain and one for the
+ * TextureFetch thread pointed to by gViewerAssetStatsThread1.
+ * Common operations has each thread recording metrics events
+ * into the respective collector unconcerned with locking and
+ * the state of any other thread. But when the agent moves into
+ * a different region or the metrics timer expires and a report
+ * needs to be sent back to the grid, messaging across threads
+ * is required to distribute data and perform global actions.
+ * In pseudo-UML, it looks like:
+ *
+ * Main Thread1
+ * . .
+ * . .
+ * +-----+ .
+ * | AM | .
+ * +--+--+ .
+ * +-------+ | .
+ * | Main | +--+--+ .
+ * | | | SRE |---. .
+ * | Stats | +-----+ \ .
+ * | | | \ (uuid) +-----+
+ * | Coll. | +--+--+ `-------->| SR |
+ * +-------+ | MSC | +--+--+
+ * | ^ +-----+ |
+ * | | (uuid) / . +-----+ (uuid)
+ * | `--------' . | MSC |---------.
+ * | . +-----+ |
+ * | +-----+ . v
+ * | | TE | . +-------+
+ * | +--+--+ . | Thd1 |
+ * | | . | |
+ * | +-----+ . | Stats |
+ * `--------->| RSC | . | |
+ * +--+--+ . | Coll. |
+ * | . +-------+
+ * +--+--+ . |
+ * | SME |---. . |
+ * +-----+ \ . |
+ * . \ (clone) +-----+ |
+ * . `-------->| SM | |
+ * . +--+--+ |
+ * . | |
+ * . +-----+ |
+ * . | RSC |<--------'
+ * . +-----+
+ * . |
+ * . +-----+
+ * . | CP |--> HTTP POST
+ * . +-----+
+ * . .
+ * . .
+ *
+ *
+ * Key:
+ *
+ * SRE - Set Region Enqueued. Enqueue a 'Set Region' command in
+ * the other thread providing the new UUID of the region.
+ * TFReqSetRegion carries the data.
+ * SR - Set Region. New region UUID is sent to the thread-local
+ * collector.
+ * SME - Send Metrics Enqueued. Enqueue a 'Send Metrics' command
+ * including an ownership transfer of a cloned LLViewerAssetStats.
+ * TFReqSendMetrics carries the data.
+ * SM - Send Metrics. Global metrics reporting operation. Takes
+ * the cloned stats from the command, merges it with the
+ * thread's local stats, converts to LLSD and sends it on
+ * to the grid.
+ * AM - Agent Moved. Agent has completed some sort of move to a
+ * new region.
+ * TE - Timer Expired. Metrics timer has expired (on the order
+ * of 10 minutes).
+ * CP - CURL Post
+ * MSC - Modify Stats Collector. State change in the thread-local
+ * collector. Typically a region change which affects the
+ * global pointers used to find the 'current stats'.
+ * RSC - Read Stats Collector. Extract collector data cloning it
+ * (i.e. deep copy) when necessary.
+ *
+ */
+class LLTextureFetch::TFRequest // : public LLQueuedThread::QueuedRequest
+{
+public:
+ // Default ctors and assignment operator are correct.
+
+ virtual ~TFRequest()
+ {}
+
+ // Patterned after QueuedRequest's method but expected behavior
+ // is different. Always expected to complete on the first call
+ // and work dispatcher will assume the same and delete the
+ // request after invocation.
+ virtual bool doWork(LLTextureFetch * fetcher) = 0;
+};
+
+namespace
+{
+
+/**
+ * @brief Implements a 'Set Region' cross-thread command.
+ *
+ * When an agent moves to a new region, subsequent metrics need
+ * to be binned into a new or existing stats collection in 1:1
+ * relationship with the region. We communicate this region
+ * change across the threads involved in the communication with
+ * this message.
+ *
+ * Corresponds to LLTextureFetch::commandSetRegion()
+ */
+class TFReqSetRegion : public LLTextureFetch::TFRequest
+{
+public:
+ TFReqSetRegion(U64 region_handle)
+ : LLTextureFetch::TFRequest(),
+ mRegionHandle(region_handle)
+ {}
+ TFReqSetRegion & operator=(const TFReqSetRegion &); // Not defined
+
+ virtual ~TFReqSetRegion()
+ {}
+
+ virtual bool doWork(LLTextureFetch * fetcher);
+
+public:
+ const U64 mRegionHandle;
+};
+
+
+/**
+ * @brief Implements a 'Send Metrics' cross-thread command.
+ *
+ * This is the big operation. The main thread gathers metrics
+ * for a period of minutes into LLViewerAssetStats and other
+ * objects then makes a snapshot of the data by cloning the
+ * collector. This command transfers the clone, along with a few
+ * additional arguments (UUIDs), handing ownership to the
+ * TextureFetch thread. It then merges its own data into the
+ * cloned copy, converts to LLSD and kicks off an HTTP POST of
+ * the resulting data to the currently active metrics collector.
+ *
+ * Corresponds to LLTextureFetch::commandSendMetrics()
+ */
+class TFReqSendMetrics : public LLTextureFetch::TFRequest
+{
+public:
+ /**
+ * Construct the 'Send Metrics' command to have the TextureFetch
+ * thread add and log metrics data.
+ *
+ * @param caps_url URL of a "ViewerMetrics" Caps target
+ * to receive the data. Does not have to
+ * be associated with a particular region.
+ *
+ * @param session_id UUID of the agent's session.
+ *
+ * @param agent_id UUID of the agent. (Being pure here...)
+ *
+ * @param main_stats Pointer to a clone of the main thread's
+ * LLViewerAssetStats data. Thread1 takes
+ * ownership of the copy and disposes of it
+ * when done.
+ */
+ TFReqSendMetrics(const std::string & caps_url,
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLViewerAssetStats * main_stats)
+ : LLTextureFetch::TFRequest(),
+ mCapsURL(caps_url),
+ mSessionID(session_id),
+ mAgentID(agent_id),
+ mMainStats(main_stats)
+ {}
+ TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined
+
+ virtual ~TFReqSendMetrics();
+
+ virtual bool doWork(LLTextureFetch * fetcher);
+
+public:
+ const std::string mCapsURL;
+ const LLUUID mSessionID;
+ const LLUUID mAgentID;
+ LLViewerAssetStats * mMainStats;
+};
+
+/*
+ * Examines the merged viewer metrics report and if found to be too long,
+ * will attempt to truncate it in some reasonable fashion.
+ *
+ * @param max_regions Limit of regions allowed in report.
+ *
+ * @param metrics Full, merged viewer metrics report.
+ *
+ * @returns If data was truncated, returns true.
+ */
+bool truncate_viewer_metrics(int max_regions, LLSD & metrics);
+
+} // end of anonymous namespace
+
+
+//////////////////////////////////////////////////////////////////////////////
+
//static
const char* LLTextureFetchWorker::sStateDescs[] = {
"INVALID",
@@ -374,6 +626,9 @@ const char* LLTextureFetchWorker::sStateDescs[] = {
"DONE",
};
+// static
+volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data break
+
// called from MAIN THREAD
LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
@@ -423,7 +678,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mFirstPacket(0),
mLastPacket(-1),
mTotalPackets(0),
- mImageCodec(IMG_CODEC_INVALID)
+ mImageCodec(IMG_CODEC_INVALID),
+ mMetricsStartTime(0)
{
mCanUseNET = mUrl.empty() ;
@@ -591,6 +847,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
return true; // abort
}
}
+
if(mImagePriority < F_ALMOST_ZERO)
{
if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR)
@@ -800,7 +1057,15 @@ bool LLTextureFetchWorker::doWork(S32 param)
mRequestedDiscard = mDesiredDiscard;
mSentRequest = QUEUED;
mFetcher->addToNetworkQueue(this);
+ if (! mMetricsStartTime)
+ {
+ mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ }
+ LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE,
+ false,
+ LLImageBase::TYPE_AVATAR_BAKE == mType);
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
+
return false;
}
else
@@ -809,6 +1074,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
//llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end());
// Make certain this is in the network queue
//mFetcher->addToNetworkQueue(this);
+ //if (! mMetricsStartTime)
+ //{
+ // mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ //}
+ //LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, false,
+ // LLImageBase::TYPE_AVATAR_BAKE == mType);
//setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return false;
}
@@ -832,11 +1103,30 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = DECODE_IMAGE;
- mWriteToCacheState = SHOULD_WRITE ;
+ mWriteToCacheState = SHOULD_WRITE;
+
+ if (mMetricsStartTime)
+ {
+ LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE,
+ false,
+ LLImageBase::TYPE_AVATAR_BAKE == mType,
+ LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime);
+ mMetricsStartTime = 0;
+ }
+ LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE,
+ false,
+ LLImageBase::TYPE_AVATAR_BAKE == mType);
}
else
{
mFetcher->addToNetworkQueue(this); // failsafe
+ if (! mMetricsStartTime)
+ {
+ mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ }
+ LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE,
+ false,
+ LLImageBase::TYPE_AVATAR_BAKE == mType);
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
}
return false;
@@ -851,7 +1141,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
//1, not openning too many file descriptors at the same time;
//2, control the traffic of http so udp gets bandwidth.
//
- static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 32 ;
+ static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 8 ;
if(mFetcher->getNumHTTPRequests() > MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE)
{
return false ; //wait.
@@ -898,6 +1188,14 @@ bool LLTextureFetchWorker::doWork(S32 param)
mState = WAIT_HTTP_REQ;
mFetcher->addToHTTPQueue(mID);
+ if (! mMetricsStartTime)
+ {
+ mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ }
+ LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE,
+ true,
+ LLImageBase::TYPE_AVATAR_BAKE == mType);
+
// Will call callbackHttpGet when curl request completes
std::vector<std::string> headers;
headers.push_back("Accept: image/x-j2c");
@@ -1512,7 +1810,7 @@ bool LLTextureFetchWorker::writeToCacheComplete()
//////////////////////////////////////////////////////////////////////////////
// public
-LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded)
+LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode)
: LLWorkerThread("TextureFetch", threaded),
mDebugCount(0),
mDebugPause(FALSE),
@@ -1524,8 +1822,11 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0),
mHTTPTextureBits(0),
- mCurlGetRequest(NULL)
+ mTotalHTTPRequests(0),
+ mCurlGetRequest(NULL),
+ mQAMode(qa_mode)
{
+ mCurlPOSTRequestCount = 0;
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
}
@@ -1534,6 +1835,13 @@ LLTextureFetch::~LLTextureFetch()
{
clearDeleteList() ;
+ while (! mCommands.empty())
+ {
+ TFRequest * req(mCommands.front());
+ mCommands.erase(mCommands.begin());
+ delete req;
+ }
+
// ~LLQueuedThread() called here
}
@@ -1563,7 +1871,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;
}
@@ -1667,6 +1974,7 @@ void LLTextureFetch::addToHTTPQueue(const LLUUID& id)
{
LLMutexLock lock(&mNetworkQueueMutex);
mHTTPTextureQueue.insert(id);
+ mTotalHTTPRequests++;
}
void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size)
@@ -1729,6 +2037,15 @@ S32 LLTextureFetch::getNumHTTPRequests()
return size ;
}
+U32 LLTextureFetch::getTotalNumHTTPRequests()
+{
+ mNetworkQueueMutex.lock() ;
+ U32 size = mTotalHTTPRequests ;
+ mNetworkQueueMutex.unlock() ;
+
+ return size ;
+}
+
// call lockQueue() first!
LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)
{
@@ -1815,8 +2132,76 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
return res;
}
+// Replicates and expands upon the base class's
+// getPending() implementation. getPending() and
+// runCondition() replicate one another's logic to
+// an extent and are sometimes used for the same
+// function (deciding whether or not to sleep/pause
+// a thread). So the implementations need to stay
+// in step, at least until this can be refactored and
+// the redundancy eliminated.
+//
+// May be called from any thread
+
+//virtual
+S32 LLTextureFetch::getPending()
+{
+ S32 res;
+ lockData();
+ {
+ LLMutexLock lock(&mQueueMutex);
+
+ res = mRequestQueue.size();
+ res += mCurlPOSTRequestCount;
+ res += mCommands.size();
+ }
+ unlockData();
+ return res;
+}
+
+// virtual
+bool LLTextureFetch::runCondition()
+{
+ // Caller is holding the lock on LLThread's condition variable.
+
+ // LLQueuedThread, unlike its base class LLThread, makes this a
+ // private method which is unfortunate. I want to use it directly
+ // but I'm going to have to re-implement the logic here (or change
+ // declarations, which I don't want to do right now).
+ //
+ // Changes here may need to be reflected in getPending().
+
+ bool have_no_commands(false);
+ {
+ LLMutexLock lock(&mQueueMutex);
+
+ have_no_commands = mCommands.empty();
+ }
+
+ bool have_no_curl_requests(0 == mCurlPOSTRequestCount);
+
+ return ! (have_no_commands
+ && have_no_curl_requests
+ && (mRequestQueue.empty() && mIdleThread)); // From base class
+}
+
//////////////////////////////////////////////////////////////////////////////
+// MAIN THREAD (unthreaded envs), WORKER THREAD (threaded envs)
+void LLTextureFetch::commonUpdate()
+{
+ // Run a cross-thread command, if any.
+ cmdDoWork();
+
+ // Update Curl on same thread as mCurlGetRequest was constructed
+ S32 processed = mCurlGetRequest->process();
+ if (processed > 0)
+ {
+ lldebugs << "processed: " << processed << " messages." << llendl;
+ }
+}
+
+
// MAIN THREAD
//virtual
S32 LLTextureFetch::update(U32 max_time_ms)
@@ -1842,12 +2227,7 @@ S32 LLTextureFetch::update(U32 max_time_ms)
if (!mThreaded)
{
- // Update Curl on same thread as mCurlGetRequest was constructed
- S32 processed = mCurlGetRequest->process();
- if (processed > 0)
- {
- lldebugs << "processed: " << processed << " messages." << llendl;
- }
+ commonUpdate();
}
return res;
@@ -1902,12 +2282,7 @@ void LLTextureFetch::threadedUpdate()
}
process_timer.reset();
- // Update Curl on same thread as mCurlGetRequest was constructed
- S32 processed = mCurlGetRequest->process();
- if (processed > 0)
- {
- lldebugs << "processed: " << processed << " messages." << llendl;
- }
+ commonUpdate();
#if 0
const F32 INFO_TIME = 1.0f;
@@ -2357,3 +2732,280 @@ void LLTextureFetch::dump()
}
}
+//////////////////////////////////////////////////////////////////////////////
+
+// cross-thread command methods
+
+void LLTextureFetch::commandSetRegion(U64 region_handle)
+{
+ TFReqSetRegion * req = new TFReqSetRegion(region_handle);
+
+ cmdEnqueue(req);
+}
+
+void LLTextureFetch::commandSendMetrics(const std::string & caps_url,
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLViewerAssetStats * main_stats)
+{
+ TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, main_stats);
+
+ cmdEnqueue(req);
+}
+
+void LLTextureFetch::commandDataBreak()
+{
+ // The pedantically correct way to implement this is to create a command
+ // request object in the above fashion and enqueue it. However, this is
+ // simple data of an advisorial not operational nature and this case
+ // of shared-write access is tolerable.
+
+ LLTextureFetch::svMetricsDataBreak = true;
+}
+
+void LLTextureFetch::cmdEnqueue(TFRequest * req)
+{
+ lockQueue();
+ mCommands.push_back(req);
+ unlockQueue();
+
+ unpause();
+}
+
+LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()
+{
+ TFRequest * ret = 0;
+
+ lockQueue();
+ if (! mCommands.empty())
+ {
+ ret = mCommands.front();
+ mCommands.erase(mCommands.begin());
+ }
+ unlockQueue();
+
+ return ret;
+}
+
+void LLTextureFetch::cmdDoWork()
+{
+ if (mDebugPause)
+ {
+ return; // debug: don't do any work
+ }
+
+ TFRequest * req = cmdDequeue();
+ if (req)
+ {
+ // One request per pass should really be enough for this.
+ req->doWork(this);
+ delete req;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Private (anonymous) class methods implementing the command scheme.
+
+namespace
+{
+
+/**
+ * Implements the 'Set Region' command.
+ *
+ * Thread: Thread1 (TextureFetch)
+ */
+bool
+TFReqSetRegion::doWork(LLTextureFetch *)
+{
+ LLViewerAssetStatsFF::set_region_thread1(mRegionHandle);
+
+ return true;
+}
+
+
+TFReqSendMetrics::~TFReqSendMetrics()
+{
+ delete mMainStats;
+ mMainStats = 0;
+}
+
+
+/**
+ * Implements the 'Send Metrics' command. Takes over
+ * ownership of the passed LLViewerAssetStats pointer.
+ *
+ * Thread: Thread1 (TextureFetch)
+ */
+bool
+TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
+{
+ /*
+ * HTTP POST responder. Doesn't do much but tries to
+ * detect simple breaks in recording the metrics stream.
+ *
+ * The 'volatile' modifiers don't indicate signals,
+ * mmap'd memory or threads, really. They indicate that
+ * the referenced data is part of a pseudo-closure for
+ * this responder rather than being required for correct
+ * operation.
+ *
+ * We don't try very hard with the POST request. We give
+ * it one shot and that's more-or-less it. With a proper
+ * refactoring of the LLQueuedThread usage, these POSTs
+ * could be put in a request object and made more reliable.
+ */
+ class lcl_responder : public LLCurl::Responder
+ {
+ public:
+ lcl_responder(LLTextureFetch * fetcher,
+ S32 expected_sequence,
+ volatile const S32 & live_sequence,
+ volatile bool & reporting_break,
+ volatile bool & reporting_started)
+ : LLCurl::Responder(),
+ mFetcher(fetcher),
+ mExpectedSequence(expected_sequence),
+ mLiveSequence(live_sequence),
+ mReportingBreak(reporting_break),
+ mReportingStarted(reporting_started)
+ {
+ mFetcher->incrCurlPOSTCount();
+ }
+
+ ~lcl_responder()
+ {
+ mFetcher->decrCurlPOSTCount();
+ }
+
+ // virtual
+ void error(U32 status_num, const std::string & reason)
+ {
+ if (mLiveSequence == mExpectedSequence)
+ {
+ mReportingBreak = true;
+ }
+ LL_WARNS("Texture") << "Break in metrics stream due to POST failure to metrics collection service. Reason: "
+ << reason << LL_ENDL;
+ }
+
+ // virtual
+ void result(const LLSD & content)
+ {
+ if (mLiveSequence == mExpectedSequence)
+ {
+ mReportingBreak = false;
+ mReportingStarted = true;
+ }
+ }
+
+ private:
+ LLTextureFetch * mFetcher;
+ S32 mExpectedSequence;
+ volatile const S32 & mLiveSequence;
+ volatile bool & mReportingBreak;
+ volatile bool & mReportingStarted;
+
+ }; // class lcl_responder
+
+ if (! gViewerAssetStatsThread1)
+ return true;
+
+ static volatile bool reporting_started(false);
+ static volatile S32 report_sequence(0);
+
+ // We've taken over ownership of the stats copy at this
+ // point. Get a working reference to it for merging here
+ // but leave it in 'this'. Destructor will rid us of it.
+ LLViewerAssetStats & main_stats = *mMainStats;
+
+ // Merge existing stats into those from main, convert to LLSD
+ main_stats.merge(*gViewerAssetStatsThread1);
+ LLSD merged_llsd = main_stats.asLLSD(true);
+
+ // Add some additional meta fields to the content
+ merged_llsd["session_id"] = mSessionID;
+ merged_llsd["agent_id"] = mAgentID;
+ merged_llsd["message"] = "ViewerAssetMetrics"; // Identifies the type of metrics
+ merged_llsd["sequence"] = report_sequence; // Sequence number
+ merged_llsd["initial"] = ! reporting_started; // Initial data from viewer
+ merged_llsd["break"] = LLTextureFetch::svMetricsDataBreak; // Break in data prior to this report
+
+ // Update sequence number
+ if (S32_MAX == ++report_sequence)
+ report_sequence = 0;
+
+ // Limit the size of the stats report if necessary.
+ merged_llsd["truncated"] = truncate_viewer_metrics(10, merged_llsd);
+
+ if (! mCapsURL.empty())
+ {
+ LLCurlRequest::headers_t headers;
+ fetcher->getCurlRequest().post(mCapsURL,
+ headers,
+ merged_llsd,
+ new lcl_responder(fetcher,
+ report_sequence,
+ report_sequence,
+ LLTextureFetch::svMetricsDataBreak,
+ reporting_started));
+ }
+ else
+ {
+ LLTextureFetch::svMetricsDataBreak = true;
+ }
+
+ // In QA mode, Metrics submode, log the result for ease of testing
+ if (fetcher->isQAMode())
+ {
+ LL_INFOS("Textures") << merged_llsd << LL_ENDL;
+ }
+
+ gViewerAssetStatsThread1->reset();
+
+ return true;
+}
+
+
+bool
+truncate_viewer_metrics(int max_regions, LLSD & metrics)
+{
+ static const LLSD::String reg_tag("regions");
+ static const LLSD::String duration_tag("duration");
+
+ LLSD & reg_map(metrics[reg_tag]);
+ if (reg_map.size() <= max_regions)
+ {
+ return false;
+ }
+
+ // Build map of region hashes ordered by duration
+ typedef std::multimap<LLSD::Real, int> reg_ordered_list_t;
+ reg_ordered_list_t regions_by_duration;
+
+ int ind(0);
+ LLSD::array_const_iterator it_end(reg_map.endArray());
+ for (LLSD::array_const_iterator it(reg_map.beginArray()); it_end != it; ++it, ++ind)
+ {
+ LLSD::Real duration = (*it)[duration_tag].asReal();
+ regions_by_duration.insert(reg_ordered_list_t::value_type(duration, ind));
+ }
+
+ // Build a replacement regions array with the longest-persistence regions
+ LLSD new_region(LLSD::emptyArray());
+ reg_ordered_list_t::const_reverse_iterator it2_end(regions_by_duration.rend());
+ reg_ordered_list_t::const_reverse_iterator it2(regions_by_duration.rbegin());
+ for (int i(0); i < max_regions && it2_end != it2; ++i, ++it2)
+ {
+ new_region.append(reg_map[it2->second]);
+ }
+ reg_map = new_region;
+
+ return true;
+}
+
+} // end of anonymous namespace
+
+
+
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 796109df06..d101da1f4b 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -33,6 +33,7 @@
#include "llworkerthread.h"
#include "llcurl.h"
#include "lltextureinfo.h"
+#include "llapr.h"
class LLViewerTexture;
class LLTextureFetchWorker;
@@ -40,6 +41,7 @@ class HTTPGetResponder;
class LLTextureCache;
class LLImageDecodeThread;
class LLHost;
+class LLViewerAssetStats;
// Interface class
class LLTextureFetch : public LLWorkerThread
@@ -48,9 +50,11 @@ class LLTextureFetch : public LLWorkerThread
friend class HTTPGetResponder;
public:
- LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded);
+ LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* imagedecodethread, bool threaded, bool qa_mode);
~LLTextureFetch();
+ class TFRequest;
+
/*virtual*/ S32 update(U32 max_time_ms);
void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down.
void shutDownImageDecodeThread() ; //called in the main thread after the ImageDecodeThread shuts down.
@@ -75,30 +79,80 @@ public:
void dump();
S32 getNumRequests() ;
S32 getNumHTTPRequests() ;
+ U32 getTotalNumHTTPRequests() ;
// Public for access by callbacks
+ S32 getPending();
void lockQueue() { mQueueMutex.lock(); }
void unlockQueue() { mQueueMutex.unlock(); }
LLTextureFetchWorker* getWorker(const LLUUID& id);
LLTextureFetchWorker* getWorkerAfterLock(const LLUUID& id);
LLTextureInfo* getTextureInfo() { return &mTextureInfo; }
-
+
+ // Commands available to other threads to control metrics gathering operations.
+ void commandSetRegion(U64 region_handle);
+ void commandSendMetrics(const std::string & caps_url,
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLViewerAssetStats * main_stats);
+ void commandDataBreak();
+
+ LLCurlRequest & getCurlRequest() { return *mCurlGetRequest; }
+
+ bool isQAMode() const { return mQAMode; }
+
+ // Curl POST counter maintenance
+ inline void incrCurlPOSTCount() { mCurlPOSTRequestCount++; }
+ inline void decrCurlPOSTCount() { mCurlPOSTRequestCount--; }
+
protected:
void addToNetworkQueue(LLTextureFetchWorker* worker);
void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
void addToHTTPQueue(const LLUUID& id);
void removeFromHTTPQueue(const LLUUID& id, S32 received_size = 0);
void removeRequest(LLTextureFetchWorker* worker, bool cancel);
- // Called from worker thread (during doWork)
- void processCurlRequests();
+
+ // Overrides from the LLThread tree
+ bool runCondition();
private:
void sendRequestListToSimulators();
/*virtual*/ void startThread(void);
/*virtual*/ void endThread(void);
/*virtual*/ void threadedUpdate(void);
-
+ void commonUpdate();
+
+ // Metrics command helpers
+ /**
+ * Enqueues a command request at the end of the command queue
+ * and wakes up the thread as needed.
+ *
+ * Takes ownership of the TFRequest object.
+ *
+ * Method locks the command queue.
+ */
+ void cmdEnqueue(TFRequest *);
+
+ /**
+ * Returns the first TFRequest object in the command queue or
+ * NULL if none is present.
+ *
+ * Caller acquires ownership of the object and must dispose of it.
+ *
+ * Method locks the command queue.
+ */
+ TFRequest * cmdDequeue();
+
+ /**
+ * Processes the first command in the queue disposing of the
+ * request on completion. Successive calls are needed to perform
+ * additional commands.
+ *
+ * Method locks the command queue.
+ */
+ void cmdDoWork();
+
public:
LLUUID mDebugID;
S32 mDebugCount;
@@ -107,7 +161,7 @@ public:
S32 mBadPacketCount;
private:
- LLMutex mQueueMutex; //to protect mRequestMap only
+ LLMutex mQueueMutex; //to protect mRequestMap and mCommands only
LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.
LLTextureCache* mTextureCache;
@@ -129,6 +183,32 @@ private:
LLTextureInfo mTextureInfo;
U32 mHTTPTextureBits;
+
+ //debug use
+ U32 mTotalHTTPRequests ;
+
+ // Out-of-band cross-thread command queue. This command queue
+ // is logically tied to LLQueuedThread's list of
+ // QueuedRequest instances and so must be covered by the
+ // same locks.
+ typedef std::vector<TFRequest *> command_queue_t;
+ command_queue_t mCommands;
+
+ // If true, modifies some behaviors that help with QA tasks.
+ const bool mQAMode;
+
+ // Count of POST requests outstanding. We maintain the count
+ // indirectly in the CURL request responder's ctor and dtor and
+ // use it when determining whether or not to sleep the thread. Can't
+ // use the LLCurl module's request counter as it isn't thread compatible.
+ // *NOTE: Don't mix Atomic and static, apr_initialize must be called first.
+ LLAtomic32<S32> mCurlPOSTRequestCount;
+
+public:
+ // A probabilistically-correct indicator that the current
+ // attempt to log metrics follows a break in the metrics stream
+ // reporting due to either startup or a problem POSTing data.
+ static volatile bool svMetricsDataBreak;
};
#endif // LL_LLTEXTUREFETCH_H
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index c87aff022f..0115115a23 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -514,7 +514,9 @@ 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);
+ U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ;
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
@@ -525,13 +527,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 Tot Htp: %d",
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, total_http_requests);
//, 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..e0b07ed408 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),
@@ -60,7 +99,6 @@ LLToast::Params::Params()
LLToast::LLToast(const LLToast::Params& p)
: LLModalDialog(LLSD(), p.is_modal),
- mPanel(p.panel),
mToastLifetime(p.lifetime_secs),
mToastFadingTime(p.fading_time_secs),
mNotificationID(p.notif_id),
@@ -69,11 +107,13 @@ LLToast::LLToast(const LLToast::Params& p)
mCanBeStored(p.can_be_stored),
mHideBtnEnabled(p.enable_hide_btn),
mHideBtn(NULL),
+ mPanel(NULL),
mNotification(p.notification),
mIsHidden(false),
mHideBtnPressed(false),
mIsTip(p.is_tip),
- mWrapperPanel(NULL)
+ mWrapperPanel(NULL),
+ mIsFading(false)
{
mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs));
@@ -85,9 +125,12 @@ LLToast::LLToast(const LLToast::Params& p)
mWrapperPanel->setMouseEnterCallback(boost::bind(&LLToast::onToastMouseEnter, this));
mWrapperPanel->setMouseLeaveCallback(boost::bind(&LLToast::onToastMouseLeave, this));
- if(mPanel)
+ setBackgroundOpaque(TRUE); // *TODO: obsolete
+ updateTransparency();
+
+ if(p.panel())
{
- insertPanel(mPanel);
+ insertPanel(p.panel);
}
if(mHideBtnEnabled)
@@ -101,10 +144,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 +182,7 @@ LLToast::~LLToast()
void LLToast::hide()
{
setVisible(FALSE);
+ setFading(false);
mTimer->stop();
mIsHidden = true;
mOnFadeSignal(this);
@@ -153,7 +193,7 @@ void LLToast::onFocusLost()
if(mWrapperPanel && !isBackgroundVisible())
{
// Lets make wrapper panel behave like a floater
- setBackgroundOpaque(FALSE);
+ updateTransparency();
}
}
@@ -162,10 +202,20 @@ void LLToast::onFocusReceived()
if(mWrapperPanel && !isBackgroundVisible())
{
// Lets make wrapper panel behave like a floater
- setBackgroundOpaque(TRUE);
+ updateTransparency();
}
}
+void LLToast::setLifetime(S32 seconds)
+{
+ mToastLifetime = seconds;
+}
+
+void LLToast::setFadingTime(S32 seconds)
+{
+ mToastFadingTime = seconds;
+}
+
S32 LLToast::getTopPad()
{
if(mWrapperPanel)
@@ -195,13 +245,48 @@ void LLToast::setCanFade(bool can_fade)
//--------------------------------------------------------------------------
void LLToast::expire()
{
- // if toast has fade property - hide it
- if(mCanFade)
+ if (mCanFade)
{
- hide();
+ if (mIsFading)
+ {
+ // Fade timer expired. Time to hide.
+ hide();
+ }
+ else
+ {
+ // "Life" time has ended. Time to fade.
+ setFading(true);
+ mTimer->restart();
+ }
}
}
+void LLToast::setFading(bool transparent)
+{
+ mIsFading = transparent;
+ updateTransparency();
+
+ if (transparent)
+ {
+ mTimer->setPeriod(mToastFadingTime);
+ }
+ else
+ {
+ mTimer->setPeriod(mToastLifetime);
+ }
+}
+
+F32 LLToast::getTimeLeftToLive()
+{
+ F32 time_to_live = mTimer->getRemainingTimeF32();
+
+ if (!mIsFading)
+ {
+ time_to_live += mToastFadingTime;
+ }
+
+ return time_to_live;
+}
//--------------------------------------------------------------------------
void LLToast::reshapeToPanel()
@@ -224,6 +309,7 @@ void LLToast::reshapeToPanel()
void LLToast::insertPanel(LLPanel* panel)
{
+ mPanel = panel;
mWrapperPanel->addChild(panel);
reshapeToPanel();
}
@@ -245,13 +331,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,9 +346,13 @@ void LLToast::setVisible(BOOL show)
return;
}
+ if (show && getVisible())
+ {
+ return;
+ }
+
if(show)
{
- setBackgroundOpaque(TRUE);
if(!mTimer->getStarted() && mCanFade)
{
mTimer->start();
@@ -311,7 +394,7 @@ void LLToast::onToastMouseEnter()
{
mOnToastHoverSignal(this, MOUSE_ENTER);
- setBackgroundOpaque(TRUE);
+ updateTransparency();
//toasts fading is management by Screen Channel
@@ -320,7 +403,6 @@ void LLToast::onToastMouseEnter()
{
mHideBtn->setVisible(TRUE);
}
- mOnMouseEnterSignal(this);
mToastMouseEnterSignal(this, getValue());
}
}
@@ -341,6 +423,8 @@ void LLToast::onToastMouseLeave()
{
mOnToastHoverSignal(this, MOUSE_LEAVE);
+ updateTransparency();
+
//toasts fading is management by Screen Channel
if(mHideBtn && mHideBtn->getEnabled())
@@ -368,19 +452,46 @@ void LLToast::setBackgroundOpaque(BOOL b)
}
}
-void LLNotificationsUI::LLToast::stopFading()
+void LLToast::updateTransparency()
+{
+ ETypeTransparency transparency_type;
+
+ if (mCanFade)
+ {
+ // Notification toasts (including IM/chat toasts) change their transparency on hover.
+ if (isHovered())
+ {
+ transparency_type = TT_ACTIVE;
+ }
+ else
+ {
+ transparency_type = mIsFading ? TT_FADING : TT_INACTIVE;
+ }
+ }
+ else
+ {
+ // Transparency of alert toasts depends on focus.
+ transparency_type = hasFocus() ? TT_ACTIVE : TT_INACTIVE;
+ }
+
+ LLFloater::updateTransparency(transparency_type);
+}
+
+void LLNotificationsUI::LLToast::stopTimer()
{
if(mCanFade)
{
- stopTimer();
+ setFading(false);
+ mTimer->stop();
}
}
-void LLNotificationsUI::LLToast::startFading()
+void LLNotificationsUI::LLToast::startTimer()
{
if(mCanFade)
{
- resetTimer();
+ setFading(false);
+ mTimer->start();
}
}
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 0a96c092a0..242f786bf2 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,
@@ -107,11 +114,11 @@ public:
//Fading
- /** Stop fading timer */
- virtual void stopFading();
+ /** Stop lifetime/fading timer */
+ virtual void stopTimer();
- /** Start fading timer */
- virtual void startFading();
+ /** Start lifetime/fading timer */
+ virtual void startTimer();
bool isHovered();
@@ -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();}
//
@@ -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,18 @@ public:
LLHandle<LLToast> getHandle() { mHandle.bind(this); return mHandle; }
+protected:
+ void updateTransparency();
+
private:
void onToastMouseEnter();
void onToastMouseLeave();
- void expire();
+ void expire();
+
+ void setFading(bool fading);
LLUUID mNotificationID;
LLUUID mSessionID;
@@ -222,6 +235,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 mIsFading;
commit_signal_t mToastMouseEnterSignal;
commit_signal_t mToastMouseLeaveSignal;
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 371aad64bb..75178a6ef8 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
@@ -77,6 +77,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
from << from_name << "/" << groupData.mName;
LLTextBox* pTitleText = getChild<LLTextBox>("title");
pTitleText->setValue(from.str());
+ pTitleText->setToolTip(from.str());
//message subject
const std::string& subject = payload["subject"].asString();
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 9017f5ec55..fa91f129b8 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;
@@ -556,7 +563,17 @@ void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_paren
height = rc.getHeight();
width = rc.getWidth();
+ bool is_width_changed = width != getRect().getWidth();
+
LLToastPanel::reshape(width, height, called_from_parent);
+
+ // Notification height required to display the text message depends on
+ // the width of the text box thus if panel width is changed the text box
+ // width is also changed then reshape() is called to adjust proper height.
+ if (is_width_changed)
+ {
+ reshape(width, height, called_from_parent);
+ }
}
// EOF
diff --git a/indra/newview/lltoastscripttextbox.cpp b/indra/newview/lltoastscripttextbox.cpp
new file mode 100644
index 0000000000..2529ec865a
--- /dev/null
+++ b/indra/newview/lltoastscripttextbox.cpp
@@ -0,0 +1,121 @@
+/**
+ * @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(const LLNotificationPtr& notification)
+: LLToastPanel(notification)
+{
+ buildFromFile( "panel_notify_textbox.xml");
+
+ LLTextEditor* text_editorp = getChild<LLTextEditor>("text_editor_box");
+ text_editorp->setValue(notification->getMessage());
+
+ getChild<LLButton>("ignore_btn")->setClickedCallback(boost::bind(&LLToastScriptTextbox::onClickIgnore, this));
+
+ 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;
+ }
+}
+
+void LLToastScriptTextbox::onClickIgnore()
+{
+ LLSD response = mNotification->getResponseTemplate();
+ mNotification->respond(response);
+ close();
+}
diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h
new file mode 100644
index 0000000000..8e69d8834d
--- /dev/null
+++ b/indra/newview/lltoastscripttextbox.h
@@ -0,0 +1,59 @@
+/**
+ * @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"
+
+/**
+ * Toast panel for scripted llTextbox notifications.
+ */
+class LLToastScriptTextbox
+: public LLToastPanel
+{
+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(const LLNotificationPtr& notification);
+
+ /*virtual*/ ~LLToastScriptTextbox();
+
+private:
+
+ void onClickSubmit();
+ void onClickIgnore();
+
+ static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
+};
+
+#endif
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index 282d4e19c6..2d8ce95347 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -33,6 +33,7 @@
#include "llview.h"
#include "llviewerwindow.h"
+#include "llviewercontrol.h"
#include "lltoolcomp.h"
#include "lltoolfocus.h"
#include "llfocusmgr.h"
@@ -190,9 +191,12 @@ LLTool* LLTool::getOverrideTool(MASK mask)
{
return NULL;
}
- if (mask & MASK_ALT)
+ if (gSavedSettings.getBOOL("EnableAltZoom"))
{
- return LLToolCamera::getInstance();
+ if (mask & MASK_ALT)
+ {
+ return LLToolCamera::getInstance();
+ }
}
return NULL;
}
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index ca80a1db79..964b17d3a6 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -244,13 +244,13 @@ BOOL LLVisualParamHint::render()
//-----------------------------------------------------------------------------
// draw()
//-----------------------------------------------------------------------------
-void LLVisualParamHint::draw()
+void LLVisualParamHint::draw(F32 alpha)
{
if (!mIsVisible) return;
gGL.getTexUnit(0)->bind(this);
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
+ gGL.color4f(1.f, 1.f, 1.f, alpha);
LLGLSUIDefault gls_ui;
gGL.begin(LLRender::QUADS);
diff --git a/indra/newview/lltoolmorph.h b/indra/newview/lltoolmorph.h
index 59201233ae..a6889be151 100644
--- a/indra/newview/lltoolmorph.h
+++ b/indra/newview/lltoolmorph.h
@@ -68,7 +68,7 @@ public:
BOOL render();
void requestUpdate( S32 delay_frames ) {mNeedsUpdate = TRUE; mDelayFrames = delay_frames; }
void setUpdateDelayFrames( S32 delay_frames ) { mDelayFrames = delay_frames; }
- void draw();
+ void draw(F32 alpha);
LLViewerVisualParam* getVisualParam() { return mVisualParam; }
F32 getVisualParamWeight() { return mVisualParamWeight; }
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index d992d808c7..9549f180df 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -79,11 +79,16 @@ static ECursorType cursor_from_parcel_media(U8 click_action);
LLToolPie::LLToolPie()
: LLTool(std::string("Pie")),
- mGrabMouseButtonDown( FALSE ),
- mMouseOutsideSlop( FALSE ),
- mClickAction(0)
-{ }
-
+ mMouseButtonDown( false ),
+ mMouseOutsideSlop( false ),
+ mMouseSteerX(-1),
+ mMouseSteerY(-1),
+ mBlockClickToWalk(false),
+ mClickAction(0),
+ mClickActionBuyEnabled( gSavedSettings.getBOOL("ClickActionBuyEnabled") ),
+ mClickActionPayEnabled( gSavedSettings.getBOOL("ClickActionPayEnabled") )
+{
+}
BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
{
@@ -97,12 +102,17 @@ BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktyp
BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
{
+ mMouseOutsideSlop = FALSE;
+ mMouseDownX = x;
+ mMouseDownY = y;
+
//left mouse down always picks transparent
mPick = gViewerWindow->pickImmediate(x, y, TRUE);
mPick.mKeyMask = mask;
- mGrabMouseButtonDown = TRUE;
+
+ mMouseButtonDown = true;
- pickLeftMouseDownCallback();
+ handleLeftClickPick();
return TRUE;
}
@@ -117,7 +127,7 @@ BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
// claim not handled so UI focus stays same
- pickRightMouseDownCallback();
+ handleRightClickPick();
return FALSE;
}
@@ -134,7 +144,7 @@ BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks)
}
// True if you selected an object.
-BOOL LLToolPie::pickLeftMouseDownCallback()
+BOOL LLToolPie::handleLeftClickPick()
{
S32 x = mPick.mMousePt.mX;
S32 y = mPick.mMousePt.mY;
@@ -211,12 +221,28 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
} // else nothing (fall through to touch)
}
case CLICK_ACTION_PAY:
- if ((object && object->flagTakesMoney())
- || (parent && parent->flagTakesMoney()))
+ if ( mClickActionPayEnabled )
+ {
+ if ((object && object->flagTakesMoney())
+ || (parent && parent->flagTakesMoney()))
+ {
+ // pay event goes to object actually clicked on
+ mClickActionObject = object;
+ mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
+ if (LLSelectMgr::getInstance()->selectGetAllValid())
+ {
+ // call this right away, since we have all the info we need to continue the action
+ selectionPropertiesReceived();
+ }
+ return TRUE;
+ }
+ }
+ break;
+ case CLICK_ACTION_BUY:
+ if ( mClickActionBuyEnabled )
{
- // pay event goes to object actually clicked on
- mClickActionObject = object;
- mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
+ mClickActionObject = parent;
+ mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
if (LLSelectMgr::getInstance()->selectGetAllValid())
{
// call this right away, since we have all the info we need to continue the action
@@ -225,15 +251,6 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
return TRUE;
}
break;
- case CLICK_ACTION_BUY:
- mClickActionObject = parent;
- mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
- if (LLSelectMgr::getInstance()->selectGetAllValid())
- {
- // call this right away, since we have all the info we need to continue the action
- selectionPropertiesReceived();
- }
- return TRUE;
case CLICK_ACTION_OPEN:
if (parent && parent->allowOpen())
{
@@ -283,7 +300,12 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
}
// put focus back "in world"
- gFocusMgr.setKeyboardFocus(NULL);
+ if (gFocusMgr.getKeyboardFocus())
+ {
+ // don't click to walk on attempt to give focus to world
+ mBlockClickToWalk = true;
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
BOOL touchable = (object && object->flagHandleTouch())
|| (parent && parent->flagHandleTouch());
@@ -295,6 +317,7 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
)
{
gGrabTransientTool = this;
+ mMouseButtonDown = false;
LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() );
return LLToolGrab::getInstance()->handleObjectHit( mPick );
}
@@ -310,9 +333,9 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
if (!gSavedSettings.getBOOL("LeftClickShowMenu"))
{
// mouse already released
- if (!mGrabMouseButtonDown)
+ if (!mMouseButtonDown)
{
- return TRUE;
+ return true;
}
while( object && object->isAttachment() && !object->flagHandleTouch())
@@ -324,9 +347,10 @@ BOOL LLToolPie::pickLeftMouseDownCallback()
}
object = (LLViewerObject*)object->getParent();
}
- if (object && object == gAgentAvatarp)
+ if (object && object == gAgentAvatarp && !gSavedSettings.getBOOL("ClickToWalk"))
{
// we left clicked on avatar, switch to focus mode
+ mMouseButtonDown = false;
LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
gViewerWindow->hideCursor();
LLToolCamera::getInstance()->setMouseCapture(TRUE);
@@ -393,7 +417,7 @@ U8 final_click_action(LLViewerObject* obj)
return click_action;
}
-ECursorType cursor_from_object(LLViewerObject* object)
+ECursorType LLToolPie::cursorFromObject(LLViewerObject* object)
{
LLViewerObject* parent = NULL;
if (object)
@@ -413,7 +437,10 @@ ECursorType cursor_from_object(LLViewerObject* object)
}
break;
case CLICK_ACTION_BUY:
- cursor = UI_CURSOR_TOOLBUY;
+ if ( mClickActionBuyEnabled )
+ {
+ cursor = UI_CURSOR_TOOLBUY;
+ }
break;
case CLICK_ACTION_OPEN:
// Open always opens the parent.
@@ -423,10 +450,13 @@ ECursorType cursor_from_object(LLViewerObject* object)
}
break;
case CLICK_ACTION_PAY:
- if ((object && object->flagTakesMoney())
- || (parent && parent->flagTakesMoney()))
+ if ( mClickActionPayEnabled )
{
- cursor = UI_CURSOR_TOOLBUY;
+ if ((object && object->flagTakesMoney())
+ || (parent && parent->flagTakesMoney()))
+ {
+ cursor = UI_CURSOR_TOOLBUY;
+ }
}
break;
case CLICK_ACTION_ZOOM:
@@ -474,10 +504,16 @@ void LLToolPie::selectionPropertiesReceived()
switch (click_action)
{
case CLICK_ACTION_BUY:
- handle_buy();
+ if ( LLToolPie::getInstance()->mClickActionBuyEnabled )
+ {
+ handle_buy();
+ }
break;
case CLICK_ACTION_PAY:
- handle_give_money_dialog();
+ if ( LLToolPie::getInstance()->mClickActionPayEnabled )
+ {
+ handle_give_money_dialog();
+ }
break;
case CLICK_ACTION_OPEN:
LLFloaterReg::showInstance("openobject");
@@ -492,7 +528,28 @@ void LLToolPie::selectionPropertiesReceived()
BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
{
+ if (!mMouseOutsideSlop
+ && mMouseButtonDown
+ && gSavedSettings.getBOOL("ClickToWalk"))
+ {
+ S32 delta_x = x - mMouseDownX;
+ S32 delta_y = y - mMouseDownY;
+ S32 threshold = gSavedSettings.getS32("DragAndDropDistanceThreshold");
+ if (delta_x * delta_x + delta_y * delta_y > threshold * threshold)
+ {
+ startCameraSteering();
+ }
+ }
+
mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
+
+ if (inCameraSteerMode())
+ {
+ steerCameraWithMouse(x, y);
+ gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
+ return TRUE;
+ }
+
// perform a separate pick that detects transparent objects since they respond to 1-click actions
LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE);
@@ -518,7 +575,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
else if (click_action_object && useClickAction(mask, click_action_object, click_action_object->getRootEdit()))
{
show_highlight = true;
- ECursorType cursor = cursor_from_object(click_action_object);
+ ECursorType cursor = cursorFromObject(click_action_object);
gViewerWindow->setCursor(cursor);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
@@ -563,37 +620,62 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
{
LLViewerObject* obj = mPick.getObject();
-
- handleMediaMouseUp();
-
U8 click_action = final_click_action(obj);
- if (click_action != CLICK_ACTION_NONE)
+
+ // let media have first pass at click
+ if (handleMediaMouseUp() || LLViewerMediaFocus::getInstance()->getFocus())
{
- switch(click_action)
+ mBlockClickToWalk = true;
+ }
+ stopCameraSteering();
+ mMouseButtonDown = false;
+
+ if (click_action == CLICK_ACTION_NONE // not doing 1-click action
+ && gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled
+ && !gAgent.getFlying() // don't auto-navigate while flying until that works
+ && !mBlockClickToWalk // another behavior hasn't cancelled click to walk
+ && !mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
+ && (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
+ || mPick.mObjectID.notNull())) // or on an object
+ {
+ // handle special cases of steering picks
+ LLViewerObject* avatar_object = mPick.getObject();
+
+ // get pointer to avatar
+ while (avatar_object && !avatar_object->isAvatar())
{
- case CLICK_ACTION_BUY:
- case CLICK_ACTION_PAY:
- case CLICK_ACTION_OPEN:
- case CLICK_ACTION_ZOOM:
- case CLICK_ACTION_PLAY:
- case CLICK_ACTION_OPEN_MEDIA:
- // Because these actions open UI dialogs, we won't change
- // the cursor again until the next hover and GL pick over
- // the world. Keep the cursor an arrow, assuming that
- // after the user moves off the UI, they won't be on the
- // same object anymore.
- gViewerWindow->setCursor(UI_CURSOR_ARROW);
- // Make sure the hover-picked object is ignored.
- //gToolTipView->resetLastHoverObject();
- break;
- default:
- break;
+ avatar_object = (LLViewerObject*)avatar_object->getParent();
}
+
+ if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
+ {
+ const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
+ // pretend we picked some point a bit in front of avatar
+ mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
+ }
+ gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
+ if(mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
+ mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
+ mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
+ mAutoPilotDestination->setPixelSize(5);
+ mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
+ mAutoPilotDestination->setDuration(3.f);
+
+ handle_go_to();
+ mBlockClickToWalk = false;
+
+ return TRUE;
+ }
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
+ if (hasMouseCapture())
+ {
+ setMouseCapture(FALSE);
}
- mGrabMouseButtonDown = FALSE;
LLToolMgr::getInstance()->clearTransientTool();
gAgentCamera.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
+
+ mBlockClickToWalk = false;
return LLTool::handleMouseUp(x, y, mask);
}
@@ -913,7 +995,7 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
p.visible_time_near(6.f);
p.visible_time_far(3.f);
- p.delay_time(0.35f);
+ p.delay_time(gSavedSettings.getF32("AvatarInspectorTooltipDelay"));
p.wrap(false);
LLToolTipMgr::instance().show(p);
@@ -1031,7 +1113,7 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
p.click_homepage_callback(boost::bind(VisitHomePage, mHoverPick));
p.visible_time_near(6.f);
p.visible_time_far(3.f);
- p.delay_time(0.35f);
+ p.delay_time(gSavedSettings.getF32("ObjectInspectorTooltipDelay"));
p.wrap(false);
LLToolTipMgr::instance().show(p);
@@ -1214,6 +1296,11 @@ void LLToolPie::VisitHomePage(const LLPickInfo& info)
}
}
+void LLToolPie::handleSelect()
+{
+ // tool is reselected when app gets focus, etc.
+ mBlockClickToWalk = true;
+}
void LLToolPie::handleDeselect()
{
@@ -1228,15 +1315,17 @@ void LLToolPie::handleDeselect()
LLTool* LLToolPie::getOverrideTool(MASK mask)
{
- if (mask == MASK_CONTROL)
- {
- return LLToolGrab::getInstance();
- }
- else if (mask == (MASK_CONTROL | MASK_SHIFT))
+ if (gSavedSettings.getBOOL("EnableGrab"))
{
- return LLToolGrab::getInstance();
+ if (mask == MASK_CONTROL)
+ {
+ return LLToolGrab::getInstance();
+ }
+ else if (mask == (MASK_CONTROL | MASK_SHIFT))
+ {
+ return LLToolGrab::getInstance();
+ }
}
-
return LLTool::getOverrideTool(mask);
}
@@ -1250,10 +1339,20 @@ void LLToolPie::stopEditing()
void LLToolPie::onMouseCaptureLost()
{
- mMouseOutsideSlop = FALSE;
+ stopCameraSteering();
+ mMouseButtonDown = false;
handleMediaMouseUp();
}
+void LLToolPie::stopCameraSteering()
+{
+ mMouseOutsideSlop = false;
+}
+
+bool LLToolPie::inCameraSteerMode()
+{
+ return mMouseButtonDown && mMouseOutsideSlop && gSavedSettings.getBOOL("ClickToWalk");
+}
// true if x,y outside small box around start_x,start_y
BOOL LLToolPie::outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y)
@@ -1419,8 +1518,6 @@ bool LLToolPie::handleMediaMouseUp()
mMediaMouseCaptureID.setNull();
- setMouseCapture(FALSE);
-
result = true;
}
@@ -1483,7 +1580,7 @@ static ECursorType cursor_from_parcel_media(U8 click_action)
// True if we handled the event.
-BOOL LLToolPie::pickRightMouseDownCallback()
+BOOL LLToolPie::handleRightClickPick()
{
S32 x = mPick.mMousePt.mX;
S32 y = mPick.mMousePt.mY;
@@ -1605,10 +1702,148 @@ BOOL LLToolPie::pickRightMouseDownCallback()
void LLToolPie::showVisualContextMenuEffect()
{
- // VEFFECT: ShowPie
- LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
- effectp->setPositionGlobal(mPick.mPosGlobal);
- effectp->setColor(LLColor4U(gAgent.getEffectColor()));
- effectp->setDuration(0.25f);
+ // VEFFECT: ShowPie
+ LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
+ effectp->setPositionGlobal(mPick.mPosGlobal);
+ effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+ effectp->setDuration(0.25f);
+}
+
+bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius, LLVector3& intersection_pt)
+{
+ // do ray/sphere intersection by solving quadratic equation
+ LLVector3 sphere_to_ray_start_vec = ray_pt - sphere_center;
+ F32 B = 2.f * ray_dir * sphere_to_ray_start_vec;
+ F32 C = sphere_to_ray_start_vec.lengthSquared() - (sphere_radius * sphere_radius);
+
+ F32 discriminant = B*B - 4.f*C;
+ if (discriminant > 0.f)
+ { // intersection detected, now find closest one
+ F32 t0 = (-B - sqrtf(discriminant)) / 2.f;
+ if (t0 > 0.f)
+ {
+ intersection_pt = ray_pt + ray_dir * t0;
+ }
+ else
+ {
+ F32 t1 = (-B + sqrtf(discriminant)) / 2.f;
+ intersection_pt = ray_pt + ray_dir * t1;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void LLToolPie::startCameraSteering()
+{
+ mMouseOutsideSlop = true;
+ mBlockClickToWalk = true;
+
+ if (gAgentCamera.getFocusOnAvatar())
+ {
+ mSteerPick = mPick;
+
+ // handle special cases of steering picks
+ LLViewerObject* avatar_object = mSteerPick.getObject();
+
+ // get pointer to avatar
+ while (avatar_object && !avatar_object->isAvatar())
+ {
+ avatar_object = (LLViewerObject*)avatar_object->getParent();
+ }
+
+ // if clicking on own avatar...
+ if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
+ {
+ // ...project pick point a few meters in front of avatar
+ mSteerPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * 3.0;
+ }
+
+ if (!mSteerPick.isValid())
+ {
+ mSteerPick.mPosGlobal = gAgent.getPosGlobalFromAgent(
+ LLViewerCamera::instance().getOrigin() + gViewerWindow->mouseDirectionGlobal(mSteerPick.mMousePt.mX, mSteerPick.mMousePt.mY) * 100.f);
+ }
+
+ setMouseCapture(TRUE);
+
+ mMouseSteerX = mMouseDownX;
+ mMouseSteerY = mMouseDownY;
+ const LLVector3 camera_to_rotation_center = gAgent.getFrameAgent().getOrigin() - LLViewerCamera::instance().getOrigin();
+ const LLVector3 rotation_center_to_pick = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal) - gAgent.getFrameAgent().getOrigin();
+
+ mClockwise = camera_to_rotation_center * rotation_center_to_pick < 0.f;
+ if (mMouseSteerGrabPoint) { mMouseSteerGrabPoint->markDead(); }
+ mMouseSteerGrabPoint = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
+ mMouseSteerGrabPoint->setPositionGlobal(mSteerPick.mPosGlobal);
+ mMouseSteerGrabPoint->setColor(LLColor4U(170, 210, 190));
+ mMouseSteerGrabPoint->setPixelSize(5);
+ mMouseSteerGrabPoint->setDuration(2.f);
+ }
+}
+
+void LLToolPie::steerCameraWithMouse(S32 x, S32 y)
+{
+ const F32 MIN_ROTATION_RADIUS_FRACTION = 0.2f;
+
+ const LLVector3 pick_pos = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal);
+ const LLVector3 rotation_center = gAgent.getFrameAgent().getOrigin();
+ // FIXME: get this to work with camera tilt (i.e. sitting on a rotating object)
+ const LLVector3 rotation_up_axis(LLVector3::z_axis);
+
+ LLVector3 object_rotation_center = rotation_center + parallel_component(pick_pos - rotation_center, rotation_up_axis);
+ F32 min_rotation_radius = MIN_ROTATION_RADIUS_FRACTION * dist_vec(rotation_center, LLViewerCamera::instance().getOrigin());;
+ F32 pick_distance_from_rotation_center = llclamp(dist_vec(pick_pos, object_rotation_center), min_rotation_radius, F32_MAX);
+
+ LLVector3 mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(x, y), rotation_up_axis);
+ mouse_ray.normalize();
+
+ LLVector3 old_mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(mMouseSteerX, mMouseSteerY), rotation_up_axis);
+ old_mouse_ray.normalize();
+
+ LLVector3 camera_pos = gAgentCamera.getCameraPositionAgent();
+ LLVector3 camera_to_rotation_center = object_rotation_center - camera_pos;
+ LLVector3 adjusted_camera_pos = camera_pos + projected_vec(camera_to_rotation_center, rotation_up_axis);
+ LLVector3 rotation_fwd_axis = LLViewerCamera::instance().getAtAxis() - projected_vec(LLViewerCamera::instance().getAtAxis(), rotation_up_axis);
+ rotation_fwd_axis.normalize();
+ F32 pick_dist = dist_vec(pick_pos, adjusted_camera_pos);
+
+ LLVector3 mouse_on_sphere;
+ bool mouse_hit_sphere = intersect_ray_with_sphere(adjusted_camera_pos + (mouse_ray * pick_dist * 1.1f),
+ -1.f * mouse_ray,
+ object_rotation_center,
+ pick_distance_from_rotation_center,
+ mouse_on_sphere);
+
+ LLVector3 old_mouse_on_sphere;
+ intersect_ray_with_sphere(adjusted_camera_pos + (old_mouse_ray * pick_dist * 1.1f),
+ -1.f * old_mouse_ray,
+ object_rotation_center,
+ pick_distance_from_rotation_center,
+ old_mouse_on_sphere);
+
+ if (mouse_hit_sphere)
+ {
+ // calculate rotation frame in screen space
+ LLVector3 screen_rotation_up_axis = orthogonal_component(rotation_up_axis, LLViewerCamera::instance().getAtAxis());
+ screen_rotation_up_axis.normalize();
+
+ LLVector3 screen_rotation_left_axis = screen_rotation_up_axis % LLViewerCamera::instance().getAtAxis();
+
+ LLVector3 rotation_furthest_pt = object_rotation_center + pick_distance_from_rotation_center * rotation_fwd_axis;
+ F32 mouse_lateral_distance = llclamp(((mouse_on_sphere - rotation_furthest_pt) * screen_rotation_left_axis) / pick_distance_from_rotation_center, -1.f, 1.f);
+ F32 old_mouse_lateral_distance = llclamp(((old_mouse_on_sphere - rotation_furthest_pt) * screen_rotation_left_axis) / pick_distance_from_rotation_center, -1.f, 1.f);
+
+ F32 yaw_angle = asinf(mouse_lateral_distance);
+ F32 old_yaw_angle = asinf(old_mouse_lateral_distance);
+
+ F32 delta_angle = yaw_angle - old_yaw_angle;
+ if (!mClockwise) delta_angle *= -1.f;
+
+ gAgent.yaw(delta_angle);
+ mMouseSteerX = x;
+ mMouseSteerY = y;
+ }
}
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 65cb3e36a7..22359a6db8 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -30,6 +30,7 @@
#include "lltool.h"
#include "lluuid.h"
#include "llviewerwindow.h" // for LLPickInfo
+#include "llhudeffectblob.h" // for LLPointer<LLHudEffectBlob>, apparently
class LLViewerObject;
class LLObjectSelection;
@@ -56,6 +57,7 @@ public:
virtual void stopEditing();
virtual void onMouseCaptureLost();
+ virtual void handleSelect();
virtual void handleDeselect();
virtual LLTool* getOverrideTool(MASK mask);
@@ -64,6 +66,7 @@ public:
LLViewerObject* getClickActionObject() { return mClickActionObject; }
LLObjectSelection* getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; }
void resetSelection();
+ void blockClickToWalk() { mBlockClickToWalk = true; }
static void selectionPropertiesReceived();
@@ -75,11 +78,12 @@ public:
private:
BOOL outsideSlop (S32 x, S32 y, S32 start_x, S32 start_y);
- BOOL pickLeftMouseDownCallback();
- BOOL pickRightMouseDownCallback();
+ BOOL handleLeftClickPick();
+ BOOL handleRightClickPick();
BOOL useClickAction (MASK mask, LLViewerObject* object,LLViewerObject* parent);
void showVisualContextMenuEffect();
+ ECursorType cursorFromObject(LLViewerObject* object);
bool handleMediaClick(const LLPickInfo& info);
bool handleMediaHover(const LLPickInfo& info);
@@ -87,17 +91,31 @@ private:
BOOL handleTooltipLand(std::string line, std::string tooltip_msg);
BOOL handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg);
+ void steerCameraWithMouse(S32 x, S32 y);
+ void startCameraSteering();
+ void stopCameraSteering();
+ bool inCameraSteerMode();
+
private:
- BOOL mGrabMouseButtonDown;
- BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region
+ bool mMouseButtonDown;
+ bool mMouseOutsideSlop; // for this drag, has mouse moved outside slop region
+ S32 mMouseDownX;
+ S32 mMouseDownY;
+ S32 mMouseSteerX;
+ S32 mMouseSteerY;
+ LLPointer<LLHUDEffectBlob> mAutoPilotDestination;
+ LLPointer<LLHUDEffectBlob> mMouseSteerGrabPoint;
+ bool mClockwise;
+ bool mBlockClickToWalk;
LLUUID mMediaMouseCaptureID;
LLPickInfo mPick;
LLPickInfo mHoverPick;
+ LLPickInfo mSteerPick;
LLPointer<LLViewerObject> mClickActionObject;
U8 mClickAction;
LLSafeHandle<LLObjectSelection> mLeftClickSelection;
-
+ BOOL mClickActionBuyEnabled;
+ BOOL mClickActionPayEnabled;
};
-
#endif
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index c3dd17def9..983108391f 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -109,6 +109,8 @@ void LLTracker::stopTracking(void* userdata)
// static virtual
void LLTracker::drawHUDArrow()
{
+ if (!gSavedSettings.getBOOL("RenderTrackerBeacon")) return;
+
static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
/* tracking autopilot destination has been disabled
@@ -155,7 +157,7 @@ void LLTracker::drawHUDArrow()
// static
void LLTracker::render3D()
{
- if (!gFloaterWorldMap)
+ if (!gFloaterWorldMap || !gSavedSettings.getBOOL("RenderTrackerBeacon"))
{
return;
}
diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h
index c0c154abe8..8e916af315 100644
--- a/indra/newview/lltracker.h
+++ b/indra/newview/lltracker.h
@@ -75,7 +75,7 @@ public:
// these are static so that they can be used a callbacks
static ETrackingStatus getTrackingStatus() { return instance()->mTrackingStatus; }
static ETrackingLocationType getTrackedLocationType() { return instance()->mTrackingLocationType; }
- static BOOL isTracking(void*) { return (BOOL) instance()->mTrackingStatus; }
+ static BOOL isTracking(void*) { return instance()->mTrackingStatus != TRACKING_NOTHING; }
static void stopTracking(void*);
static void clearFocus();
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 78dd602f39..c648a6a28a 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -36,8 +36,11 @@
LLTransientFloaterMgr::LLTransientFloaterMgr()
{
- gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
- &LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+ if(gViewerWindow)
+ {
+ gViewerWindow->getRootView()->getChild<LLUICtrl>("popup_holder")->setMouseDownCallback(boost::bind(
+ &LLTransientFloaterMgr::leftMouseClickCallback, this, _2, _3, _4));
+ }
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..2de7db38ed 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -2,33 +2,27 @@
* @file lltranslate.cpp
* @brief Functions for translating text via Google Translate.
*
-* $LicenseInfo:firstyear=2009&license=viewergpl$
-*
-* Copyright (c) 2009-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$
-*/
+ * $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"
@@ -36,10 +30,10 @@
#include "llbufferstream.h"
#include "llui.h"
-#include "llversionviewer.h"
+#include "llversioninfo.h"
#include "llviewercontrol.h"
-#include "jsoncpp/reader.h"
+#include "reader.h"
// These two are concatenated with the language specifiers to form a complete Google Translate URL
const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=";
@@ -64,11 +58,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/lltranslate.h b/indra/newview/lltranslate.h
index 0786dc0ca3..e85a42e878 100644
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -2,33 +2,27 @@
* @file lltranslate.h
* @brief Human language translation class and JSON response receiver.
*
-* $LicenseInfo:firstyear=2009&license=viewergpl$
-*
-* Copyright (c) 2009-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$
-*/
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
#ifndef LL_LLTRANSLATE_H
#define LL_LLTRANSLATE_H
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index bd4d3c2b78..ebbb045f0a 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -180,7 +180,7 @@ bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, bool right_mouse)
LLWorldMapMessage::getInstance()->sendNamedRegionRequest(slurl.getRegion(),
LLURLDispatcherImpl::regionNameCallback,
slurl.getSLURLString(),
- false); // don't teleport
+ LLUI::sSettingGroups["config"]->getBOOL("SLURLTeleportDirectly")); // don't teleport
return true;
}
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/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
new file mode 100644
index 0000000000..7024b2c785
--- /dev/null
+++ b/indra/newview/llviewerassetstats.cpp
@@ -0,0 +1,613 @@
+/**
+ * @file llviewerassetstats.cpp
+ * @brief
+ *
+ * $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 "llviewerassetstats.h"
+#include "llregionhandle.h"
+
+#include "stdtypes.h"
+
+/*
+ * Classes and utility functions for per-thread and per-region
+ * asset and experiential metrics to be aggregated grid-wide.
+ *
+ * The basic metrics grouping is LLViewerAssetStats::PerRegionStats.
+ * This provides various counters and simple statistics for asset
+ * fetches binned into a few categories. One of these is maintained
+ * for each region encountered and the 'current' region is available
+ * as a simple reference. Each thread (presently two) interested
+ * in participating in these stats gets an instance of the
+ * LLViewerAssetStats class so that threads are completely
+ * independent.
+ *
+ * The idea of a current region is used for simplicity and speed
+ * of categorization. Each metrics event could have taken a
+ * region uuid argument resulting in a suitable lookup. Arguments
+ * against this design include:
+ *
+ * - Region uuid not trivially available to caller.
+ * - Cost (cpu, disruption in real work flow) too high.
+ * - Additional precision not really meaningful.
+ *
+ * By itself, the LLViewerAssetStats class is thread- and
+ * viewer-agnostic and can be used anywhere without assumptions
+ * of global pointers and other context. For the viewer,
+ * a set of free functions are provided in the namespace
+ * LLViewerAssetStatsFF which *do* implement viewer-native
+ * policies about per-thread globals and will do correct
+ * defensive tests of same.
+ *
+ * References
+ *
+ * Project:
+ * <TBD>
+ *
+ * Test Plan:
+ * <TBD>
+ *
+ * Jiras:
+ * <TBD>
+ *
+ * Unit Tests:
+ * indra/newview/tests/llviewerassetstats_test.cpp
+ *
+ */
+
+
+// ------------------------------------------------------
+// Global data definitions
+// ------------------------------------------------------
+LLViewerAssetStats * gViewerAssetStatsMain(0);
+LLViewerAssetStats * gViewerAssetStatsThread1(0);
+
+
+// ------------------------------------------------------
+// Local declarations
+// ------------------------------------------------------
+namespace
+{
+
+static LLViewerAssetStats::EViewerAssetCategories
+asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+}
+
+// ------------------------------------------------------
+// LLViewerAssetStats::PerRegionStats struct definition
+// ------------------------------------------------------
+void
+LLViewerAssetStats::PerRegionStats::reset()
+{
+ for (int i(0); i < LL_ARRAY_SIZE(mRequests); ++i)
+ {
+ mRequests[i].mEnqueued.reset();
+ mRequests[i].mDequeued.reset();
+ mRequests[i].mResponse.reset();
+ }
+ mFPS.reset();
+
+ mTotalTime = 0;
+ mStartTimestamp = LLViewerAssetStatsFF::get_timestamp();
+}
+
+
+void
+LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionStats & src)
+{
+ // mRegionHandle, mTotalTime, mStartTimestamp are left alone.
+
+ // mFPS
+ if (src.mFPS.getCount() && mFPS.getCount())
+ {
+ mFPS.merge(src.mFPS);
+ }
+
+ // Requests
+ for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
+ {
+ mRequests[i].mEnqueued.merge(src.mRequests[i].mEnqueued);
+ mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued);
+ mRequests[i].mResponse.merge(src.mRequests[i].mResponse);
+ }
+}
+
+
+void
+LLViewerAssetStats::PerRegionStats::accumulateTime(duration_t now)
+{
+ mTotalTime += (now - mStartTimestamp);
+ mStartTimestamp = now;
+}
+
+
+// ------------------------------------------------------
+// LLViewerAssetStats class definition
+// ------------------------------------------------------
+LLViewerAssetStats::LLViewerAssetStats()
+ : mRegionHandle(U64(0))
+{
+ reset();
+}
+
+
+LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src)
+ : mRegionHandle(src.mRegionHandle),
+ mResetTimestamp(src.mResetTimestamp)
+{
+ const PerRegionContainer::const_iterator it_end(src.mRegionStats.end());
+ for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it)
+ {
+ mRegionStats[it->first] = new PerRegionStats(*it->second);
+ }
+ mCurRegionStats = mRegionStats[mRegionHandle];
+}
+
+
+void
+LLViewerAssetStats::reset()
+{
+ // Empty the map of all region stats
+ mRegionStats.clear();
+
+ // If we have a current stats, reset it, otherwise, as at construction,
+ // create a new one as we must always have a current stats block.
+ if (mCurRegionStats)
+ {
+ mCurRegionStats->reset();
+ }
+ else
+ {
+ mCurRegionStats = new PerRegionStats(mRegionHandle);
+ }
+
+ // And add reference to map
+ mRegionStats[mRegionHandle] = mCurRegionStats;
+
+ // Start timestamp consistent with per-region collector
+ mResetTimestamp = mCurRegionStats->mStartTimestamp;
+}
+
+
+void
+LLViewerAssetStats::setRegion(region_handle_t region_handle)
+{
+ if (region_handle == mRegionHandle)
+ {
+ // Already active, ignore.
+ return;
+ }
+
+ // Get duration for current set
+ const duration_t now = LLViewerAssetStatsFF::get_timestamp();
+ mCurRegionStats->accumulateTime(now);
+
+ // Prepare new set
+ PerRegionContainer::iterator new_stats = mRegionStats.find(region_handle);
+ if (mRegionStats.end() == new_stats)
+ {
+ // Haven't seen this region_id before, create a new block and make it current.
+ mCurRegionStats = new PerRegionStats(region_handle);
+ mRegionStats[region_handle] = mCurRegionStats;
+ }
+ else
+ {
+ mCurRegionStats = new_stats->second;
+ }
+ mCurRegionStats->mStartTimestamp = now;
+ mRegionHandle = region_handle;
+}
+
+
+void
+LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
+
+ ++(mCurRegionStats->mRequests[int(eac)].mEnqueued);
+}
+
+void
+LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
+
+ ++(mCurRegionStats->mRequests[int(eac)].mDequeued);
+}
+
+void
+LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration)
+{
+ const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
+
+ mCurRegionStats->mRequests[int(eac)].mResponse.record(duration);
+}
+
+void
+LLViewerAssetStats::recordFPS(F32 fps)
+{
+ mCurRegionStats->mFPS.record(fps);
+}
+
+LLSD
+LLViewerAssetStats::asLLSD(bool compact_output)
+{
+ // Top-level tags
+ static const LLSD::String tags[EVACCount] =
+ {
+ LLSD::String("get_texture_temp_http"),
+ LLSD::String("get_texture_temp_udp"),
+ LLSD::String("get_texture_non_temp_http"),
+ LLSD::String("get_texture_non_temp_udp"),
+ LLSD::String("get_wearable_udp"),
+ LLSD::String("get_sound_udp"),
+ LLSD::String("get_gesture_udp"),
+ LLSD::String("get_other")
+ };
+
+ // Stats Group Sub-tags.
+ static const LLSD::String enq_tag("enqueued");
+ static const LLSD::String deq_tag("dequeued");
+ static const LLSD::String rcnt_tag("resp_count");
+ static const LLSD::String rmin_tag("resp_min");
+ static const LLSD::String rmax_tag("resp_max");
+ static const LLSD::String rmean_tag("resp_mean");
+
+ // MMM Group Sub-tags.
+ static const LLSD::String cnt_tag("count");
+ static const LLSD::String min_tag("min");
+ static const LLSD::String max_tag("max");
+ static const LLSD::String mean_tag("mean");
+
+ const duration_t now = LLViewerAssetStatsFF::get_timestamp();
+ mCurRegionStats->accumulateTime(now);
+
+ LLSD regions = LLSD::emptyArray();
+ for (PerRegionContainer::iterator it = mRegionStats.begin();
+ mRegionStats.end() != it;
+ ++it)
+ {
+ if (0 == it->first)
+ {
+ // Never emit NULL UUID/handle in results.
+ continue;
+ }
+
+ PerRegionStats & stats = *it->second;
+
+ LLSD reg_stat = LLSD::emptyMap();
+
+ for (int i = 0; i < LL_ARRAY_SIZE(tags); ++i)
+ {
+ PerRegionStats::prs_group & group(stats.mRequests[i]);
+
+ if ((! compact_output) ||
+ group.mEnqueued.getCount() ||
+ group.mDequeued.getCount() ||
+ group.mResponse.getCount())
+ {
+ LLSD & slot = reg_stat[tags[i]];
+ slot = LLSD::emptyMap();
+ slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount()));
+ slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount()));
+ slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount()));
+ slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin() * 1.0e-6));
+ slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax() * 1.0e-6));
+ slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6));
+ }
+ }
+
+ if ((! compact_output) || stats.mFPS.getCount())
+ {
+ LLSD & slot = reg_stat["fps"];
+ slot = LLSD::emptyMap();
+ slot[cnt_tag] = LLSD(S32(stats.mFPS.getCount()));
+ slot[min_tag] = LLSD(F64(stats.mFPS.getMin()));
+ slot[max_tag] = LLSD(F64(stats.mFPS.getMax()));
+ slot[mean_tag] = LLSD(F64(stats.mFPS.getMean()));
+ }
+
+ U32 grid_x(0), grid_y(0);
+ grid_from_region_handle(it->first, &grid_x, &grid_y);
+ reg_stat["grid_x"] = LLSD::Integer(grid_x);
+ reg_stat["grid_y"] = LLSD::Integer(grid_y);
+ reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6);
+ regions.append(reg_stat);
+ }
+
+ LLSD ret = LLSD::emptyMap();
+ ret["regions"] = regions;
+ ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6);
+
+ return ret;
+}
+
+void
+LLViewerAssetStats::merge(const LLViewerAssetStats & src)
+{
+ // mRegionHandle, mCurRegionStats and mResetTimestamp are left untouched.
+ // Just merge the stats bodies
+
+ const PerRegionContainer::const_iterator it_end(src.mRegionStats.end());
+ for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it)
+ {
+ PerRegionContainer::iterator dst(mRegionStats.find(it->first));
+ if (mRegionStats.end() == dst)
+ {
+ // Destination is missing data, just make a private copy
+ mRegionStats[it->first] = new PerRegionStats(*it->second);
+ }
+ else
+ {
+ dst->second->merge(*it->second);
+ }
+ }
+}
+
+
+// ------------------------------------------------------
+// Global free-function definitions (LLViewerAssetStatsFF namespace)
+// ------------------------------------------------------
+
+namespace LLViewerAssetStatsFF
+{
+
+//
+// Target thread is elaborated in the function name. This could
+// have been something 'templatey' like specializations iterated
+// over a set of constants but with so few, this is clearer I think.
+//
+// As for the threads themselves... rather than do fine-grained
+// locking as we gather statistics, this code creates a collector
+// for each thread, allocated and run independently. Logging
+// happens at relatively infrequent intervals and at that time
+// the data is sent to a single thread to be aggregated into
+// a single entity with locks, thread safety and other niceties.
+//
+// A particularly fussy implementation would distribute the
+// per-thread pointers across separate cache lines. But that should
+// be beyond current requirements.
+//
+
+// 'main' thread - initial program thread
+
+void
+set_region_main(LLViewerAssetStats::region_handle_t region_handle)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->setRegion(region_handle);
+}
+
+void
+record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->recordGetEnqueued(at, with_http, is_temp);
+}
+
+void
+record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->recordGetDequeued(at, with_http, is_temp);
+}
+
+void
+record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->recordGetServiced(at, with_http, is_temp, duration);
+}
+
+void
+record_fps_main(F32 fps)
+{
+ if (! gViewerAssetStatsMain)
+ return;
+
+ gViewerAssetStatsMain->recordFPS(fps);
+}
+
+
+// 'thread1' - should be for TextureFetch thread
+
+void
+set_region_thread1(LLViewerAssetStats::region_handle_t region_handle)
+{
+ if (! gViewerAssetStatsThread1)
+ return;
+
+ gViewerAssetStatsThread1->setRegion(region_handle);
+}
+
+void
+record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ if (! gViewerAssetStatsThread1)
+ return;
+
+ gViewerAssetStatsThread1->recordGetEnqueued(at, with_http, is_temp);
+}
+
+void
+record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ if (! gViewerAssetStatsThread1)
+ return;
+
+ gViewerAssetStatsThread1->recordGetDequeued(at, with_http, is_temp);
+}
+
+void
+record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
+{
+ if (! gViewerAssetStatsThread1)
+ return;
+
+ gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration);
+}
+
+
+void
+init()
+{
+ if (! gViewerAssetStatsMain)
+ {
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ }
+ if (! gViewerAssetStatsThread1)
+ {
+ gViewerAssetStatsThread1 = new LLViewerAssetStats();
+ }
+}
+
+void
+cleanup()
+{
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = 0;
+
+ delete gViewerAssetStatsThread1;
+ gViewerAssetStatsThread1 = 0;
+}
+
+
+} // namespace LLViewerAssetStatsFF
+
+
+// ------------------------------------------------------
+// Local function definitions
+// ------------------------------------------------------
+
+namespace
+{
+
+LLViewerAssetStats::EViewerAssetCategories
+asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp)
+{
+ // For statistical purposes, we divide GETs into several
+ // populations of asset fetches:
+ // - textures which are de-prioritized in the asset system
+ // - wearables (clothing, bodyparts) which directly affect
+ // user experiences when they log in
+ // - sounds
+ // - gestures
+ // - everything else.
+ //
+ llassert_always(26 == LLViewerAssetType::AT_COUNT);
+
+ // Multiple asset definitions are floating around so this requires some
+ // maintenance and attention.
+ static const LLViewerAssetStats::EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] =
+ {
+ LLViewerAssetStats::EVACTextureTempHTTPGet, // (0) AT_TEXTURE
+ LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND
+ LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD
+ LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK
+ LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT
+ LLViewerAssetStats::EVACWearableUDPGet, // AT_CLOTHING
+ LLViewerAssetStats::EVACOtherGet, // AT_OBJECT
+ LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD
+ LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY
+ LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY
+ LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT
+ LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE
+ LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA
+ LLViewerAssetStats::EVACWearableUDPGet, // AT_BODYPART
+ LLViewerAssetStats::EVACOtherGet, // AT_TRASH
+ LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY
+ LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND
+ LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND_WAV
+ LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA
+ LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG
+ LLViewerAssetStats::EVACGestureUDPGet, // (20) AT_ANIMATION
+ LLViewerAssetStats::EVACGestureUDPGet, // AT_GESTURE
+ LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE
+ LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE
+ LLViewerAssetStats::EVACOtherGet, // AT_LINK
+ LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER
+#if 0
+ // When LLViewerAssetType::AT_COUNT == 49
+ LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_START
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, // (30)
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, // (40)
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, //
+ LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_END
+ LLViewerAssetStats::EVACOtherGet, // AT_CURRENT_OUTFIT
+ LLViewerAssetStats::EVACOtherGet, // AT_OUTFIT
+ LLViewerAssetStats::EVACOtherGet // AT_MY_OUTFITS
+#endif
+ };
+
+ if (at < 0 || at >= LLViewerAssetType::AT_COUNT)
+ {
+ return LLViewerAssetStats::EVACOtherGet;
+ }
+ LLViewerAssetStats::EViewerAssetCategories ret(asset_to_bin_map[at]);
+ if (LLViewerAssetStats::EVACTextureTempHTTPGet == ret)
+ {
+ // Indexed with [is_temp][with_http]
+ static const LLViewerAssetStats::EViewerAssetCategories texture_bin_map[2][2] =
+ {
+ {
+ LLViewerAssetStats::EVACTextureNonTempUDPGet,
+ LLViewerAssetStats::EVACTextureNonTempHTTPGet,
+ },
+ {
+ LLViewerAssetStats::EVACTextureTempUDPGet,
+ LLViewerAssetStats::EVACTextureTempHTTPGet,
+ }
+ };
+
+ ret = texture_bin_map[is_temp][with_http];
+ }
+ return ret;
+}
+
+} // anonymous namespace
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
new file mode 100644
index 0000000000..73ec5974b2
--- /dev/null
+++ b/indra/newview/llviewerassetstats.h
@@ -0,0 +1,328 @@
+/**
+ * @file llviewerassetstats.h
+ * @brief Client-side collection of asset request statistics
+ *
+ * $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_LLVIEWERASSETSTATUS_H
+#define LL_LLVIEWERASSETSTATUS_H
+
+
+#include "linden_common.h"
+
+#include "llpointer.h"
+#include "llrefcount.h"
+#include "llviewerassettype.h"
+#include "llviewerassetstorage.h"
+#include "llsimplestat.h"
+#include "llsd.h"
+
+/**
+ * @class LLViewerAssetStats
+ * @brief Records performance aspects of asset access operations.
+ *
+ * This facility is derived from a very similar simulator-based
+ * one, LLSimAssetStats. It's function is to count asset access
+ * operations and characterize response times. Collected data
+ * are binned in several dimensions:
+ *
+ * - Asset types collapsed into a few aggregated categories
+ * - By simulator UUID
+ * - By transport mechanism (HTTP vs MessageSystem)
+ * - By persistence (temp vs non-temp)
+ *
+ * Statistics collected are fairly basic at this point:
+ *
+ * - Counts of enqueue and dequeue operations
+ * - Min/Max/Mean of asset transfer operations
+ *
+ * This collector differs from the simulator-based on in a
+ * number of ways:
+ *
+ * - The front-end/back-end distinction doesn't exist in viewer
+ * code
+ * - Multiple threads must be safely accomodated in the viewer
+ *
+ * Access to results is by conversion to an LLSD with some standardized
+ * key names. The intent of this structure is that it be emitted as
+ * standard syslog-based metrics formatting where it can be picked
+ * up by interested parties.
+ *
+ * For convenience, a set of free functions in namespace
+ * LLViewerAssetStatsFF is provided for conditional test-and-call
+ * operations.
+ */
+class LLViewerAssetStats
+{
+public:
+ enum EViewerAssetCategories
+ {
+ EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP
+ EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP
+ EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP
+ EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP
+ EVACWearableUDPGet, //< Wearable GETs
+ EVACSoundUDPGet, //< Sound GETs
+ EVACGestureUDPGet, //< Gesture GETs
+ EVACOtherGet, //< Other GETs
+
+ EVACCount // Must be last
+ };
+
+ /**
+ * Type for duration and other time values in the metrics. Selected
+ * for compatibility with the pre-existing timestamp on the texture
+ * fetcher class, LLTextureFetch.
+ */
+ typedef U64 duration_t;
+
+ /**
+ * Type for the region identifier used in stats. Currently uses
+ * the region handle's type (a U64) rather than the regions's LLUUID
+ * as the latter isn't available immediately.
+ */
+ typedef U64 region_handle_t;
+
+ /**
+ * @brief Collected data for a single region visited by the avatar.
+ *
+ * Fairly simple, for each asset bin enumerated above a count
+ * of enqueue and dequeue operations and simple stats on response
+ * times for completed requests.
+ */
+ class PerRegionStats : public LLRefCount
+ {
+ public:
+ PerRegionStats(const region_handle_t region_handle)
+ : LLRefCount(),
+ mRegionHandle(region_handle)
+ {
+ reset();
+ }
+
+ PerRegionStats(const PerRegionStats & src)
+ : LLRefCount(),
+ mRegionHandle(src.mRegionHandle),
+ mTotalTime(src.mTotalTime),
+ mStartTimestamp(src.mStartTimestamp),
+ mFPS(src.mFPS)
+ {
+ for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i)
+ {
+ mRequests[i] = src.mRequests[i];
+ }
+ }
+
+ // Default assignment and destructor are correct.
+
+ void reset();
+
+ void merge(const PerRegionStats & src);
+
+ // Apply current running time to total and reset start point.
+ // Return current timestamp as a convenience.
+ void accumulateTime(duration_t now);
+
+ public:
+ region_handle_t mRegionHandle;
+ duration_t mTotalTime;
+ duration_t mStartTimestamp;
+ LLSimpleStatMMM<> mFPS;
+
+ struct prs_group
+ {
+ LLSimpleStatCounter mEnqueued;
+ LLSimpleStatCounter mDequeued;
+ LLSimpleStatMMM<duration_t> mResponse;
+ }
+ mRequests [EVACCount];
+ };
+
+public:
+ LLViewerAssetStats();
+ LLViewerAssetStats(const LLViewerAssetStats &);
+ // Default destructor is correct.
+ LLViewerAssetStats & operator=(const LLViewerAssetStats &); // Not defined
+
+ // Clear all metrics data. This leaves the currently-active region
+ // in place but with zero'd data for all metrics. All other regions
+ // are removed from the collection map.
+ void reset();
+
+ // Set hidden region argument and establish context for subsequent
+ // collection calls.
+ void setRegion(region_handle_t region_handle);
+
+ // Asset GET Requests
+ void recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+ void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+ void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration);
+
+ // Frames-Per-Second Samples
+ void recordFPS(F32 fps);
+
+ // Merge a source instance into a destination instance. This is
+ // conceptually an 'operator+=()' method:
+ // - counts are added
+ // - minimums are min'd
+ // - maximums are max'd
+ // - other scalars are ignored ('this' wins)
+ //
+ void merge(const LLViewerAssetStats & src);
+
+ // Retrieve current metrics for all visited regions (NULL region UUID/handle excluded)
+ // Returned LLSD is structured as follows:
+ //
+ // &stats_group = {
+ // enqueued : int,
+ // dequeued : int,
+ // resp_count : int,
+ // resp_min : float,
+ // resp_max : float,
+ // resp_mean : float
+ // }
+ //
+ // &mmm_group = {
+ // count : int,
+ // min : float,
+ // max : float,
+ // mean : float
+ // }
+ //
+ // {
+ // duration: int
+ // regions: {
+ // $: { // Keys are strings of the region's handle in hex
+ // duration: : int,
+ // fps: : &mmm_group,
+ // get_texture_temp_http : &stats_group,
+ // get_texture_temp_udp : &stats_group,
+ // get_texture_non_temp_http : &stats_group,
+ // get_texture_non_temp_udp : &stats_group,
+ // get_wearable_udp : &stats_group,
+ // get_sound_udp : &stats_group,
+ // get_gesture_udp : &stats_group,
+ // get_other : &stats_group
+ // }
+ // }
+ // }
+ //
+ // @param compact_output If true, omits from conversion any mmm_block
+ // or stats_block that would contain all zero data.
+ // Useful for transmission when the receiver knows
+ // what is expected and will assume zero for missing
+ // blocks.
+ LLSD asLLSD(bool compact_output);
+
+protected:
+ typedef std::map<region_handle_t, LLPointer<PerRegionStats> > PerRegionContainer;
+
+ // Region of the currently-active region. Always valid but may
+ // be zero after construction or when explicitly set. Unchanged
+ // by a reset() call.
+ region_handle_t mRegionHandle;
+
+ // Pointer to metrics collection for currently-active region. Always
+ // valid and unchanged after reset() though contents will be changed.
+ // Always points to a collection contained in mRegionStats.
+ LLPointer<PerRegionStats> mCurRegionStats;
+
+ // Metrics data for all regions during one collection cycle
+ PerRegionContainer mRegionStats;
+
+ // Time of last reset
+ duration_t mResetTimestamp;
+};
+
+
+/**
+ * Global stats collectors one for each independent thread where
+ * assets and other statistics are gathered. The globals are
+ * expected to be created at startup time and then picked up by
+ * their respective threads afterwards. A set of free functions
+ * are provided to access methods behind the globals while both
+ * minimally disrupting visual flow and supplying a description
+ * of intent.
+ *
+ * Expected thread assignments:
+ *
+ * - Main: main() program execution thread
+ * - Thread1: TextureFetch worker thread
+ */
+extern LLViewerAssetStats * gViewerAssetStatsMain;
+
+extern LLViewerAssetStats * gViewerAssetStatsThread1;
+
+namespace LLViewerAssetStatsFF
+{
+/**
+ * @brief Allocation and deallocation of globals.
+ *
+ * init() should be called before threads are started that will access it though
+ * you'll likely get away with calling it afterwards. cleanup() should only be
+ * called after threads are shutdown to prevent races on the global pointers.
+ */
+void init();
+
+void cleanup();
+
+/**
+ * We have many timers, clocks etc. in the runtime. This is the
+ * canonical timestamp for these metrics which is compatible with
+ * the pre-existing timestamping in the texture fetcher.
+ */
+inline LLViewerAssetStats::duration_t get_timestamp()
+{
+ return LLTimer::getTotalTime();
+}
+
+/**
+ * Region context, event and duration loggers for the Main thread.
+ */
+void set_region_main(LLViewerAssetStats::region_handle_t region_handle);
+
+void record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+void record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp,
+ LLViewerAssetStats::duration_t duration);
+
+void record_fps_main(F32 fps);
+
+
+/**
+ * Region context, event and duration loggers for Thread 1.
+ */
+void set_region_thread1(LLViewerAssetStats::region_handle_t region_handle);
+
+void record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+void record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp);
+
+void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp,
+ LLViewerAssetStats::duration_t duration);
+
+} // namespace LLViewerAssetStatsFF
+
+#endif // LL_LLVIEWERASSETSTATUS_H
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 2e7ef0fec3..36c8b42a52 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -33,6 +33,61 @@
#include "message.h"
#include "llagent.h"
+#include "lltransfersourceasset.h"
+#include "lltransfertargetvfile.h"
+#include "llviewerassetstats.h"
+
+///----------------------------------------------------------------------------
+/// LLViewerAssetRequest
+///----------------------------------------------------------------------------
+
+/**
+ * @brief Local class to encapsulate asset fetch requests with a timestamp.
+ *
+ * Derived from the common LLAssetRequest class, this is currently used
+ * only for fetch/get operations and its only function is to wrap remote
+ * asset fetch requests so that they can be timed.
+ */
+class LLViewerAssetRequest : public LLAssetRequest
+{
+public:
+ LLViewerAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
+ : LLAssetRequest(uuid, type),
+ mMetricsStartTime(0)
+ {
+ }
+
+ LLViewerAssetRequest & operator=(const LLViewerAssetRequest &); // Not defined
+ // Default assignment operator valid
+
+ // virtual
+ ~LLViewerAssetRequest()
+ {
+ recordMetrics();
+ }
+
+protected:
+ void recordMetrics()
+ {
+ if (mMetricsStartTime)
+ {
+ // Okay, it appears this request was used for useful things. Record
+ // the expected dequeue and duration of request processing.
+ LLViewerAssetStatsFF::record_dequeue_main(mType, false, false);
+ LLViewerAssetStatsFF::record_response_main(mType, false, false,
+ (LLViewerAssetStatsFF::get_timestamp()
+ - mMetricsStartTime));
+ mMetricsStartTime = 0;
+ }
+ }
+
+public:
+ LLViewerAssetStats::duration_t mMetricsStartTime;
+};
+
+///----------------------------------------------------------------------------
+/// LLViewerAssetStorage
+///----------------------------------------------------------------------------
LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs, LLVFS *static_vfs,
@@ -258,3 +313,77 @@ void LLViewerAssetStorage::storeAssetData(
}
}
}
+
+
+/**
+ * @brief Allocate and queue an asset fetch request for the viewer
+ *
+ * This is a nearly-verbatim copy of the base class's implementation
+ * with the following changes:
+ * - Use a locally-derived request class
+ * - Start timing for metrics when request is queued
+ *
+ * This is an unfortunate implementation choice but it's forced by
+ * current conditions. A refactoring that might clean up the layers
+ * of responsibility or introduce factories or more virtualization
+ * of methods would enable a more attractive solution.
+ *
+ * If LLAssetStorage::_queueDataRequest changes, this must change
+ * as well.
+ */
+
+// virtual
+void LLViewerAssetStorage::_queueDataRequest(
+ const LLUUID& uuid,
+ LLAssetType::EType atype,
+ LLGetAssetCallback callback,
+ void *user_data,
+ BOOL duplicate,
+ BOOL is_priority)
+{
+ if (mUpstreamHost.isOk())
+ {
+ // stash the callback info so we can find it after we get the response message
+ LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype);
+ req->mDownCallback = callback;
+ req->mUserData = user_data;
+ req->mIsPriority = is_priority;
+ if (!duplicate)
+ {
+ // Only collect metrics for non-duplicate requests. Others
+ // are piggy-backing and will artificially lower averages.
+ req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ }
+
+ mPendingDownloads.push_back(req);
+
+ if (!duplicate)
+ {
+ // send request message to our upstream data provider
+ // Create a new asset transfer.
+ LLTransferSourceParamsAsset spa;
+ spa.setAsset(uuid, atype);
+
+ // Set our destination file, and the completion callback.
+ LLTransferTargetParamsVFile tpvf;
+ tpvf.setAsset(uuid, atype);
+ tpvf.setCallback(downloadCompleteCallback, req);
+
+ llinfos << "Starting transfer for " << uuid << llendl;
+ LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
+ ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
+
+ LLViewerAssetStatsFF::record_enqueue_main(atype, false, false);
+ }
+ }
+ else
+ {
+ // uh-oh, we shouldn't have gotten here
+ llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
+ if (callback)
+ {
+ callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
+ }
+ }
+}
+
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index 6346b79f03..ca9b9943fa 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -63,6 +63,17 @@ public:
bool is_priority = false,
bool user_waiting=FALSE,
F64 timeout=LL_ASSET_STORAGE_TIMEOUT);
+
+protected:
+ using LLAssetStorage::_queueDataRequest;
+
+ // virtual
+ void _queueDataRequest(const LLUUID& uuid,
+ LLAssetType::EType type,
+ void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+ void *user_data,
+ BOOL duplicate,
+ BOOL is_priority);
};
#endif
diff --git a/indra/newview/llviewerchat.cpp b/indra/newview/llviewerchat.cpp
index 0af850a46b..286b16bab2 100644
--- a/indra/newview/llviewerchat.cpp
+++ b/indra/newview/llviewerchat.cpp
@@ -31,6 +31,8 @@
#include "llagent.h" // gAgent
#include "lluicolortable.h"
#include "llviewercontrol.h" // gSavedSettings
+#include "llviewerregion.h"
+#include "llworld.h"
#include "llinstantmessage.h" //SYSTEM_FROM
// LLViewerChat
@@ -214,3 +216,43 @@ void LLViewerChat::formatChatMsg(const LLChat& chat, std::string& formated_msg)
}
+//static
+std::string LLViewerChat::getSenderSLURL(const LLChat& chat, const LLSD& args)
+{
+ switch (chat.mSourceType)
+ {
+ case CHAT_SOURCE_AGENT:
+ return LLSLURL("agent", chat.mFromID, "about").getSLURLString();
+
+ case CHAT_SOURCE_OBJECT:
+ return getObjectImSLURL(chat, args);
+
+ default:
+ llwarns << "Getting SLURL for an unsupported sender type: " << chat.mSourceType << llendl;
+ }
+
+ return LLStringUtil::null;
+}
+
+//static
+std::string LLViewerChat::getObjectImSLURL(const LLChat& chat, const LLSD& args)
+{
+ std::string url = LLSLURL("objectim", chat.mFromID, "").getSLURLString();
+ url += "?name=" + chat.mFromName;
+ url += "&owner=" + chat.mOwnerID.asString();
+
+ std::string slurl = args["slurl"].asString();
+ if (slurl.empty())
+ {
+ LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
+ if(region)
+ {
+ LLSLURL region_slurl(region->getName(), chat.mPosAgent);
+ slurl = region_slurl.getLocationString();
+ }
+ }
+
+ url += "&slurl=" + LLURI::escape(slurl);
+
+ return url;
+}
diff --git a/indra/newview/llviewerchat.h b/indra/newview/llviewerchat.h
index a9f9a98960..0f15d29f04 100644
--- a/indra/newview/llviewerchat.h
+++ b/indra/newview/llviewerchat.h
@@ -40,6 +40,10 @@ public:
static LLFontGL* getChatFont();
static S32 getChatFontSize();
static void formatChatMsg(const LLChat& chat, std::string& formated_msg);
+ static std::string getSenderSLURL(const LLChat& chat, const LLSD& args);
+
+private:
+ static std::string getObjectImSLURL(const LLChat& chat, const LLSD& args);
};
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index fbec2a7b9e..ffe607f912 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())
@@ -151,6 +164,12 @@ static bool handleAvatarLODChanged(const LLSD& newvalue)
return true;
}
+static bool handleAvatarPhysicsLODChanged(const LLSD& newvalue)
+{
+ LLVOAvatar::sPhysicsLODFactor = (F32) newvalue.asReal();
+ return true;
+}
+
static bool handleAvatarMaxVisibleChanged(const LLSD& newvalue)
{
LLVOAvatar::sMaxVisible = (U32) newvalue.asInteger();
@@ -296,6 +315,15 @@ static bool handleRenderUseVBOChanged(const LLSD& newvalue)
return true;
}
+static bool handleRenderUseVBOMappingChanged(const LLSD& newvalue)
+{
+ if (gPipeline.isInit())
+ {
+ gPipeline.setDisableVBOMapping(newvalue.asBoolean());
+ }
+ return true;
+}
+
static bool handleWLSkyDetailChanged(const LLSD&)
{
if (gSky.mVOWLSkyp.notNull())
@@ -489,6 +517,19 @@ 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.asInteger())
+ {
+ LLUpdaterService update_service;
+ if(!update_service.isChecking()) update_service.startChecking();
+ }
+ else
+ {
+ LLUpdaterService().stopChecking();
+ }
+}
+
////////////////////////////////////////////////////////////////////////////
void settings_setup_listeners()
@@ -517,6 +558,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _2));
gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));
gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2));
+ gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2));
gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2));
gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _2));
gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _2));
@@ -563,6 +605,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleRenderUseVBOChanged, _2));
+ gSavedSettings.getControl("RenderVBOMappingDisable")->getSignal()->connect(boost::bind(&handleRenderUseVBOMappingChanged, _2));
gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2));
gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _2));
@@ -636,7 +679,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("UpdaterServiceSetting")->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..41b7c13826 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())
{
@@ -652,8 +647,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
- BOOL to_texture = !for_snapshot &&
- gPipeline.canUseVertexShaders() &&
+ BOOL to_texture = gPipeline.canUseVertexShaders() &&
LLPipeline::sRenderGlow;
LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
@@ -665,11 +659,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);
@@ -714,7 +708,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
- if (!for_snapshot)
+ //if (!for_snapshot)
{
LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
@@ -730,7 +724,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);
@@ -1049,8 +1042,7 @@ LLRect get_whole_screen_region()
S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
int tile_y = sub_region / num_horizontal_tiles;
int tile_x = sub_region - (tile_y * num_horizontal_tiles);
- glh::matrix4f mat;
-
+
whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
}
return whole_screen;
@@ -1130,10 +1122,14 @@ void render_ui(F32 zoom_factor, int subfield)
LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
LLGLState::checkStates();
- glPushMatrix();
- glLoadMatrixd(gGLLastModelView);
glh::matrix4f saved_view = glh_get_current_modelview();
- glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+
+ if (!gSnapshot)
+ {
+ glPushMatrix();
+ glLoadMatrixd(gGLLastModelView);
+ glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+ }
{
BOOL to_texture = gPipeline.canUseVertexShaders() &&
@@ -1184,8 +1180,11 @@ void render_ui(F32 zoom_factor, int subfield)
LLVertexBuffer::unbind();
}
- glh_set_current_modelview(saved_view);
- glPopMatrix();
+ if (!gSnapshot)
+ {
+ glh_set_current_modelview(saved_view);
+ glPopMatrix();
+ }
if (gDisplaySwapBuffers)
{
@@ -1327,7 +1326,7 @@ void render_ui_2d()
// render outline for HUD
if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
{
- glPushMatrix();
+ gGL.pushMatrix();
S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
@@ -1336,7 +1335,7 @@ void render_ui_2d()
glScalef(zoom,zoom,1.f);
gGL.color4fv(LLColor4::white.mV);
gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
- glPopMatrix();
+ gGL.popMatrix();
stop_glerror();
}
@@ -1384,8 +1383,7 @@ void render_ui_2d()
gGL.setColorMask(true, false);
LLUI::sDirtyRect = t_rect;
-
- }
+ }
LLGLDisable cull(GL_CULL_FACE);
LLGLDisable blend(GL_BLEND);
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..dca1e33e60 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -60,6 +60,7 @@
#include "llfloaterhardwaresettings.h"
#include "llfloaterhelpbrowser.h"
#include "llfloatermediabrowser.h"
+#include "llfloaterwebcontent.h"
#include "llfloatermediasettings.h"
#include "llfloaterhud.h"
#include "llfloaterimagepreview.h"
@@ -81,6 +82,7 @@
#include "llfloaterpostprocess.h"
#include "llfloaterpreference.h"
#include "llfloaterproperties.h"
+#include "llfloaterregiondebugconsole.h"
#include "llfloaterregioninfo.h"
#include "llfloaterreporter.h"
#include "llfloaterscriptdebug.h"
@@ -227,6 +229,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>);
@@ -250,6 +253,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("voice_controls", "floater_voice_controls.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLCallFloater>);
LLFloaterReg::add("voice_effect", "floater_voice_effect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterVoiceEffect>);
+ LLFloaterReg::add("web_content", "floater_web_content.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWebContent>);
LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
LLFloaterWindowSizeUtil::registerFloater();
LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWorldMap>);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 7dbaa4cf92..519514d99c 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -48,6 +48,7 @@
#include "llinventorybridge.h"
#include "llinventorypanel.h"
#include "llfloaterinventory.h"
+#include "lllandmarkactions.h"
#include "llviewerassettype.h"
#include "llviewerregion.h"
@@ -59,6 +60,9 @@
#include "llcommandhandler.h"
#include "llviewermessage.h"
#include "llsidepanelappearance.h"
+#include "llavatarnamecache.h"
+#include "llavataractions.h"
+#include "lllogininstance.h"
///----------------------------------------------------------------------------
/// Helper class to store special inventory item names and their localized values.
@@ -85,6 +89,7 @@ public:
mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt");
mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha");
mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo");
+ mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics");
mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
@@ -211,6 +216,7 @@ public:
};
LLInventoryHandler gInventoryHandler;
+
///----------------------------------------------------------------------------
/// Class LLViewerInventoryItem
///----------------------------------------------------------------------------
@@ -361,11 +367,11 @@ void LLViewerInventoryItem::fetchFromServer(void) const
{
if(gAgent.getID() != mPermissions.getOwner())
{
- url = region->getCapability("FetchLib");
+ url = region->getCapability("FetchLib2");
}
else
{
- url = region->getCapability("FetchInventory");
+ url = region->getCapability("FetchInventory2");
}
}
else
@@ -643,7 +649,7 @@ bool LLViewerInventoryCategory::fetch()
std::string url;
if (gAgent.getRegion())
{
- url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
+ url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
}
else
{
@@ -655,7 +661,7 @@ bool LLViewerInventoryCategory::fetch()
}
else
{ //Deprecated, but if we don't have a capability, use the old system.
- llinfos << "WebFetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl;
+ llinfos << "FetchInventoryDescendents2 capability not found. Using deprecated UDP message." << llendl;
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("FetchInventoryDescendents");
msg->nextBlock("AgentData");
@@ -1414,6 +1420,8 @@ public:
S32 getSortIndex(const LLUUID& inv_item_id);
void removeSortIndex(const LLUUID& inv_item_id);
+ void getSLURL(const LLUUID& asset_id);
+
/**
* Implementation of LLDestroyClass. Calls cleanup() instance method.
*
@@ -1440,9 +1448,17 @@ private:
void load();
void save();
+ void saveFavoritesSLURLs();
+
+ void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark);
+ void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl);
+
typedef std::map<LLUUID, S32> sort_index_map_t;
sort_index_map_t mSortIndexes;
+ typedef std::map<LLUUID, std::string> slurls_map_t;
+ slurls_map_t mSLURLs;
+
bool mIsDirty;
struct IsNotInFavorites
@@ -1497,10 +1513,27 @@ void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id)
mIsDirty = true;
}
+void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
+{
+ slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id);
+ if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached
+
+ LLLandmark* lm = gLandmarkList.getAsset(asset_id,
+ boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1));
+ if (lm)
+ {
+ onLandmarkLoaded(asset_id, lm);
+ }
+}
+
// static
void LLFavoritesOrderStorage::destroyClass()
{
LLFavoritesOrderStorage::instance().cleanup();
+ if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
+ {
+ LLFavoritesOrderStorage::instance().saveFavoritesSLURLs();
+ }
}
void LLFavoritesOrderStorage::load()
@@ -1523,6 +1556,76 @@ void LLFavoritesOrderStorage::load()
}
}
+void LLFavoritesOrderStorage::saveFavoritesSLURLs()
+{
+ // Do not change the file if we are not logged in yet.
+ if (!LLLoginInstance::getInstance()->authSuccess()) return;
+
+ std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
+ if (user_dir.empty()) return;
+
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
+ llifstream in_file;
+ in_file.open(filename);
+ LLSD fav_llsd;
+ if (in_file.is_open())
+ {
+ LLSDSerialize::fromXML(fav_llsd, in_file);
+ }
+
+ const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
+
+ LLSD user_llsd;
+ for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
+ {
+ LLSD value;
+ value["name"] = (*it)->getName();
+ value["asset_id"] = (*it)->getAssetUUID();
+
+ slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
+ if (slurl_iter != mSLURLs.end())
+ {
+ value["slurl"] = slurl_iter->second;
+ user_llsd[(*it)->getSortField()] = value;
+ }
+ }
+
+ LLAvatarName av_name;
+ LLAvatarNameCache::get( gAgentID, &av_name );
+ fav_llsd[av_name.getLegacyName()] = user_llsd;
+
+ llofstream file;
+ file.open(filename);
+ LLSDSerialize::toPrettyXML(fav_llsd, file);
+}
+
+void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark)
+{
+ if (!landmark) return;
+
+ LLVector3d pos_global;
+ if (!landmark->getGlobalPos(pos_global))
+ {
+ // If global position was unknown on first getGlobalPos() call
+ // it should be set for the subsequent calls.
+ landmark->getGlobalPos(pos_global);
+ }
+
+ if (!pos_global.isExactlyZero())
+ {
+ LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
+ boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1));
+ }
+}
+
+void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl)
+{
+ mSLURLs[asset_id] = slurl;
+}
+
void LLFavoritesOrderStorage::save()
{
// nothing to save if clean
@@ -1579,6 +1682,12 @@ S32 LLViewerInventoryItem::getSortField() const
void LLViewerInventoryItem::setSortField(S32 sortField)
{
LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField);
+ getSLURL();
+}
+
+void LLViewerInventoryItem::getSLURL()
+{
+ LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID);
}
const LLPermissions& LLViewerInventoryItem::getPermissions() const
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 1af06a1be8..41542a4e0f 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -62,6 +62,7 @@ public:
virtual const std::string& getName() const;
virtual S32 getSortField() const;
virtual void setSortField(S32 sortField);
+ virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here.
virtual const LLPermissions& getPermissions() const;
virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied
virtual const LLUUID& getCreatorUUID() const;
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/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index d7e15e7d6c..1aa9fd8a45 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -40,6 +40,7 @@
#include "llviewerwindow.h"
#include "llvoavatarself.h"
#include "llfloatercamera.h"
+#include "llinitparam.h"
//
// Constants
@@ -53,6 +54,11 @@ const S32 NUDGE_FRAMES = 2;
const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
const F32 YAW_NUDGE_RATE = 0.05f; // fraction of normal speed
+struct LLKeyboardActionRegistry
+: public LLRegistrySingleton<std::string, boost::function<void (EKeystate keystate)>, LLKeyboardActionRegistry>
+{
+};
+
LLViewerKeyboard gViewerKeyboard;
void agent_jump( EKeystate s )
@@ -550,52 +556,50 @@ void start_gesture( EKeystate s )
}
}
-void bind_keyboard_functions()
-{
- gViewerKeyboard.bindNamedFunction("jump", agent_jump);
- gViewerKeyboard.bindNamedFunction("push_down", agent_push_down);
- gViewerKeyboard.bindNamedFunction("push_forward", agent_push_forward);
- gViewerKeyboard.bindNamedFunction("push_backward", agent_push_backward);
- gViewerKeyboard.bindNamedFunction("look_up", agent_look_up);
- gViewerKeyboard.bindNamedFunction("look_down", agent_look_down);
- gViewerKeyboard.bindNamedFunction("toggle_fly", agent_toggle_fly);
- gViewerKeyboard.bindNamedFunction("turn_left", agent_turn_left);
- gViewerKeyboard.bindNamedFunction("turn_right", agent_turn_right);
- gViewerKeyboard.bindNamedFunction("slide_left", agent_slide_left);
- gViewerKeyboard.bindNamedFunction("slide_right", agent_slide_right);
- gViewerKeyboard.bindNamedFunction("spin_around_ccw", camera_spin_around_ccw);
- gViewerKeyboard.bindNamedFunction("spin_around_cw", camera_spin_around_cw);
- gViewerKeyboard.bindNamedFunction("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
- gViewerKeyboard.bindNamedFunction("spin_around_cw_sitting", camera_spin_around_cw_sitting);
- gViewerKeyboard.bindNamedFunction("spin_over", camera_spin_over);
- gViewerKeyboard.bindNamedFunction("spin_under", camera_spin_under);
- gViewerKeyboard.bindNamedFunction("spin_over_sitting", camera_spin_over_sitting);
- gViewerKeyboard.bindNamedFunction("spin_under_sitting", camera_spin_under_sitting);
- gViewerKeyboard.bindNamedFunction("move_forward", camera_move_forward);
- gViewerKeyboard.bindNamedFunction("move_backward", camera_move_backward);
- gViewerKeyboard.bindNamedFunction("move_forward_sitting", camera_move_forward_sitting);
- gViewerKeyboard.bindNamedFunction("move_backward_sitting", camera_move_backward_sitting);
- gViewerKeyboard.bindNamedFunction("pan_up", camera_pan_up);
- gViewerKeyboard.bindNamedFunction("pan_down", camera_pan_down);
- gViewerKeyboard.bindNamedFunction("pan_left", camera_pan_left);
- gViewerKeyboard.bindNamedFunction("pan_right", camera_pan_right);
- gViewerKeyboard.bindNamedFunction("pan_in", camera_pan_in);
- gViewerKeyboard.bindNamedFunction("pan_out", camera_pan_out);
- gViewerKeyboard.bindNamedFunction("move_forward_fast", camera_move_forward_fast);
- gViewerKeyboard.bindNamedFunction("move_backward_fast", camera_move_backward_fast);
- gViewerKeyboard.bindNamedFunction("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
- gViewerKeyboard.bindNamedFunction("edit_avatar_spin_cw", edit_avatar_spin_cw);
- gViewerKeyboard.bindNamedFunction("edit_avatar_spin_over", edit_avatar_spin_over);
- gViewerKeyboard.bindNamedFunction("edit_avatar_spin_under", edit_avatar_spin_under);
- gViewerKeyboard.bindNamedFunction("edit_avatar_move_forward", edit_avatar_move_forward);
- gViewerKeyboard.bindNamedFunction("edit_avatar_move_backward", edit_avatar_move_backward);
- gViewerKeyboard.bindNamedFunction("stop_moving", stop_moving);
- gViewerKeyboard.bindNamedFunction("start_chat", start_chat);
- gViewerKeyboard.bindNamedFunction("start_gesture", start_gesture);
-}
-
-LLViewerKeyboard::LLViewerKeyboard() :
- mNamedFunctionCount(0)
+#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
+REGISTER_KEYBOARD_ACTION("jump", agent_jump);
+REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
+REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
+REGISTER_KEYBOARD_ACTION("push_backward", agent_push_backward);
+REGISTER_KEYBOARD_ACTION("look_up", agent_look_up);
+REGISTER_KEYBOARD_ACTION("look_down", agent_look_down);
+REGISTER_KEYBOARD_ACTION("toggle_fly", agent_toggle_fly);
+REGISTER_KEYBOARD_ACTION("turn_left", agent_turn_left);
+REGISTER_KEYBOARD_ACTION("turn_right", agent_turn_right);
+REGISTER_KEYBOARD_ACTION("slide_left", agent_slide_left);
+REGISTER_KEYBOARD_ACTION("slide_right", agent_slide_right);
+REGISTER_KEYBOARD_ACTION("spin_around_ccw", camera_spin_around_ccw);
+REGISTER_KEYBOARD_ACTION("spin_around_cw", camera_spin_around_cw);
+REGISTER_KEYBOARD_ACTION("spin_around_ccw_sitting", camera_spin_around_ccw_sitting);
+REGISTER_KEYBOARD_ACTION("spin_around_cw_sitting", camera_spin_around_cw_sitting);
+REGISTER_KEYBOARD_ACTION("spin_over", camera_spin_over);
+REGISTER_KEYBOARD_ACTION("spin_under", camera_spin_under);
+REGISTER_KEYBOARD_ACTION("spin_over_sitting", camera_spin_over_sitting);
+REGISTER_KEYBOARD_ACTION("spin_under_sitting", camera_spin_under_sitting);
+REGISTER_KEYBOARD_ACTION("move_forward", camera_move_forward);
+REGISTER_KEYBOARD_ACTION("move_backward", camera_move_backward);
+REGISTER_KEYBOARD_ACTION("move_forward_sitting", camera_move_forward_sitting);
+REGISTER_KEYBOARD_ACTION("move_backward_sitting", camera_move_backward_sitting);
+REGISTER_KEYBOARD_ACTION("pan_up", camera_pan_up);
+REGISTER_KEYBOARD_ACTION("pan_down", camera_pan_down);
+REGISTER_KEYBOARD_ACTION("pan_left", camera_pan_left);
+REGISTER_KEYBOARD_ACTION("pan_right", camera_pan_right);
+REGISTER_KEYBOARD_ACTION("pan_in", camera_pan_in);
+REGISTER_KEYBOARD_ACTION("pan_out", camera_pan_out);
+REGISTER_KEYBOARD_ACTION("move_forward_fast", camera_move_forward_fast);
+REGISTER_KEYBOARD_ACTION("move_backward_fast", camera_move_backward_fast);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_ccw", edit_avatar_spin_ccw);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_cw", edit_avatar_spin_cw);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_over", edit_avatar_spin_over);
+REGISTER_KEYBOARD_ACTION("edit_avatar_spin_under", edit_avatar_spin_under);
+REGISTER_KEYBOARD_ACTION("edit_avatar_move_forward", edit_avatar_move_forward);
+REGISTER_KEYBOARD_ACTION("edit_avatar_move_backward", edit_avatar_move_backward);
+REGISTER_KEYBOARD_ACTION("stop_moving", stop_moving);
+REGISTER_KEYBOARD_ACTION("start_chat", start_chat);
+REGISTER_KEYBOARD_ACTION("start_gesture", start_gesture);
+#undef REGISTER_KEYBOARD_ACTION
+
+LLViewerKeyboard::LLViewerKeyboard()
{
for (S32 i = 0; i < MODE_COUNT; i++)
{
@@ -613,16 +617,6 @@ LLViewerKeyboard::LLViewerKeyboard() :
}
}
-
-void LLViewerKeyboard::bindNamedFunction(const std::string& name, LLKeyFunc func)
-{
- S32 i = mNamedFunctionCount;
- mNamedFunctions[i].mName = name;
- mNamedFunctions[i].mFunction = func;
- mNamedFunctionCount++;
-}
-
-
BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)
{
if (string == "FIRST_PERSON")
@@ -695,8 +689,9 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL
BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
{
- S32 i,index;
- void (*function)(EKeystate keystate) = NULL;
+ S32 index;
+ typedef boost::function<void(EKeystate)> function_t;
+ function_t function = NULL;
std::string name;
// Allow remapping of F2-F12
@@ -719,13 +714,11 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
}
// Not remapped, look for a function
- for (i = 0; i < mNamedFunctionCount; i++)
+
+ function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+ if (result)
{
- if (function_name == mNamedFunctions[i].mName)
- {
- function = mNamedFunctions[i].mFunction;
- name = mNamedFunctions[i].mName;
- }
+ function = *result;
}
if (!function)
@@ -755,7 +748,6 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
mBindings[mode][index].mKey = key;
mBindings[mode][index].mMask = mask;
-// mBindings[mode][index].mName = name;
mBindings[mode][index].mFunction = function;
if (index == mBindingCount[mode])
@@ -764,6 +756,61 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c
return TRUE;
}
+LLViewerKeyboard::KeyBinding::KeyBinding()
+: key("key"),
+ mask("mask"),
+ command("command")
+{}
+
+LLViewerKeyboard::KeyMode::KeyMode(EKeyboardMode _mode)
+: bindings("binding"),
+ mode(_mode)
+{}
+
+LLViewerKeyboard::Keys::Keys()
+: first_person("first_person", KeyMode(MODE_FIRST_PERSON)),
+ third_person("third_person", KeyMode(MODE_THIRD_PERSON)),
+ edit("edit", KeyMode(MODE_EDIT)),
+ sitting("sitting", KeyMode(MODE_SITTING)),
+ edit_avatar("edit_avatar", KeyMode(MODE_EDIT_AVATAR))
+{}
+
+S32 LLViewerKeyboard::loadBindingsXML(const std::string& filename)
+{
+ S32 binding_count = 0;
+ Keys keys;
+ LLSimpleXUIParser parser;
+
+ if (parser.readXUI(filename, keys)
+ && keys.validateBlock())
+ {
+ binding_count += loadBindingMode(keys.first_person);
+ binding_count += loadBindingMode(keys.third_person);
+ binding_count += loadBindingMode(keys.edit);
+ binding_count += loadBindingMode(keys.sitting);
+ binding_count += loadBindingMode(keys.edit_avatar);
+ }
+ return binding_count;
+}
+
+S32 LLViewerKeyboard::loadBindingMode(const LLViewerKeyboard::KeyMode& keymode)
+{
+ S32 binding_count = 0;
+ for (LLInitParam::ParamIterator<KeyBinding>::const_iterator it = keymode.bindings.begin(),
+ end_it = keymode.bindings.end();
+ it != end_it;
+ ++it)
+ {
+ KEY key;
+ MASK mask;
+ LLKeyboard::keyFromString(it->key, &key);
+ LLKeyboard::maskFromString(it->mask, &mask);
+ bindKey(keymode.mode, key, mask, it->command);
+ binding_count++;
+ }
+
+ return binding_count;
+}
S32 LLViewerKeyboard::loadBindings(const std::string& filename)
{
@@ -912,18 +959,18 @@ void LLViewerKeyboard::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_lev
if (key_down && !repeat)
{
// ...key went down this frame, call function
- (*binding[i].mFunction)( KEYSTATE_DOWN );
+ binding[i].mFunction( KEYSTATE_DOWN );
}
else if (key_up)
{
// ...key went down this frame, call function
- (*binding[i].mFunction)( KEYSTATE_UP );
+ binding[i].mFunction( KEYSTATE_UP );
}
else if (key_level)
{
// ...key held down from previous frame
// Not windows, just call the function.
- (*binding[i].mFunction)( KEYSTATE_LEVEL );
+ binding[i].mFunction( KEYSTATE_LEVEL );
}//if
}//if
}//for
diff --git a/indra/newview/llviewerkeyboard.h b/indra/newview/llviewerkeyboard.h
index 2fa5d5dfa6..925244e89b 100644
--- a/indra/newview/llviewerkeyboard.h
+++ b/indra/newview/llviewerkeyboard.h
@@ -55,26 +55,51 @@ typedef enum e_keyboard_mode
void bind_keyboard_functions();
-
class LLViewerKeyboard
{
public:
+ struct KeyBinding : public LLInitParam::Block<KeyBinding>
+ {
+ Mandatory<std::string> key,
+ mask,
+ command;
+
+ KeyBinding();
+ };
+
+ struct KeyMode : public LLInitParam::Block<KeyMode>
+ {
+ Multiple<KeyBinding> bindings;
+ EKeyboardMode mode;
+ KeyMode(EKeyboardMode mode);
+ };
+
+ struct Keys : public LLInitParam::Block<Keys>
+ {
+ Optional<KeyMode> first_person,
+ third_person,
+ edit,
+ sitting,
+ edit_avatar;
+
+ Keys();
+ };
+
LLViewerKeyboard();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
- void bindNamedFunction(const std::string& name, LLKeyFunc func);
-
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
+ S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode();
BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
-protected:
+
+private:
+ S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
- S32 mNamedFunctionCount;
- LLNamedFunction mNamedFunctions[MAX_NAMED_FUNCTIONS];
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
S32 mBindingCount[MODE_COUNT];
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 48ab122edf..499165135a 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -52,16 +52,20 @@
#include "llviewerregion.h"
#include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
#include "llfilepicker.h"
-
+#include "llnotifications.h"
+#include "lldir.h"
#include "llevent.h" // LLSimpleListener
#include "llnotificationsutil.h"
#include "lluuid.h"
#include "llkeyboard.h"
#include "llmutelist.h"
+#include "llpanelprofile.h"
+#include "llappviewer.h"
//#include "llfirstuse.h"
#include "llwindow.h"
#include "llfloatermediabrowser.h" // for handling window close requests and geometry change requests in media browser windows.
+#include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows.
#include <boost/bind.hpp> // for SkinFolder listener
#include <boost/signals2.hpp>
@@ -290,9 +294,47 @@ public:
};
+class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
+{
+LOG_CLASS(LLViewerMediaWebProfileResponder);
+public:
+ LLViewerMediaWebProfileResponder(std::string host)
+ {
+ mHost = host;
+ }
+
+ ~LLViewerMediaWebProfileResponder()
+ {
+ }
+
+ /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+ {
+ LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
+ LL_WARNS("MediaAuth") << content << LL_ENDL;
+
+ std::string cookie = content["set-cookie"].asString();
+
+ LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
+ }
+
+ void completedRaw(
+ U32 status,
+ const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
+ {
+ // This is just here to disable the default behavior (attempting to parse the response as llsd).
+ // We don't care about the content of the response, only the set-cookie header.
+ }
+
+ std::string mHost;
+};
+
+
LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
LLURL LLViewerMedia::sOpenIDURL;
std::string LLViewerMedia::sOpenIDCookie;
+LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL;
static LLViewerMedia::impl_list sViewerMediaImplList;
static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
static LLTimer sMediaCreateTimer;
@@ -492,7 +534,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:
@@ -742,6 +784,9 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
// Enable/disable the plugin read thread
LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread"));
+ // HACK: we always try to keep a spare running webkit plugin around to improve launch times.
+ createSpareBrowserMediaSource();
+
sAnyMediaShowing = false;
sUpdatedCookies = getCookieStore()->getChangedCookies();
if(!sUpdatedCookies.empty())
@@ -759,6 +804,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
pimpl->update();
pimpl->calculateInterest();
}
+
+ // Let the spare media source actually launch
+ if(sSpareBrowserMediaSource)
+ {
+ sSpareBrowserMediaSource->idle();
+ }
// Sort the static instance list using our interest criteria
sViewerMediaImplList.sort(priorityComparitor);
@@ -1034,6 +1085,26 @@ bool LLViewerMedia::isParcelAudioPlaying()
return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
}
+void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response)
+{
+ LLViewerMediaImpl *impl = LLViewerMedia::getMediaImplFromTextureID(notification["payload"]["media_id"]);
+ if(impl)
+ {
+ LLPluginClassMedia* media = impl->getMediaPlugin();
+ if(media)
+ {
+ if (response["ok"])
+ {
+ media->sendAuthResponse(true, response["username"], response["password"]);
+ }
+ else
+ {
+ media->sendAuthResponse(false, "", "");
+ }
+ }
+ }
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::clearAllCookies()
@@ -1083,7 +1154,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;
@@ -1319,6 +1390,19 @@ void LLViewerMedia::setOpenIDCookie()
// *HACK: Doing this here is nasty, find a better way.
LLWebSharing::instance().setOpenIDCookie(sOpenIDCookie);
+
+ // Do a web profile get so we can store the cookie
+ LLSD headers = LLSD::emptyMap();
+ headers["Accept"] = "*/*";
+ headers["Cookie"] = sOpenIDCookie;
+ headers["User-Agent"] = getCurrentUserAgent();
+
+ std::string profile_url = getProfileURL("");
+ LLURL raw_profile_url( profile_url.c_str() );
+
+ LLHTTPClient::get(profile_url,
+ new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
+ headers);
}
}
@@ -1400,6 +1484,32 @@ void LLViewerMedia::proxyWindowClosed(const std::string &uuid)
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::createSpareBrowserMediaSource()
+{
+ // If we don't have a spare browser media source, create one.
+ // However, if PluginAttachDebuggerToPlugins is set then don't spawn a spare
+ // SLPlugin process in order to not be confused by an unrelated gdb terminal
+ // popping up at the moment we start a media plugin.
+ if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
+ {
+ // The null owner will keep the browser plugin from fully initializing
+ // (specifically, it keeps LLPluginClassMedia from negotiating a size change,
+ // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
+ sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
+{
+ LLPluginClassMedia* result = sSpareBrowserMediaSource;
+ sSpareBrowserMediaSource = NULL;
+ return result;
+};
+
bool LLViewerMedia::hasInWorldMedia()
{
if (sInWorldMediaDisabled) return false;
@@ -1636,6 +1746,22 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
{
std::string plugin_basename = LLMIMETypes::implType(media_type);
+ LLPluginClassMedia* media_source = NULL;
+
+ // HACK: we always try to keep a spare running webkit plugin around to improve launch times.
+ // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
+ if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
+ {
+ media_source = LLViewerMedia::getSpareBrowserMediaSource();
+ if(media_source)
+ {
+ media_source->setOwner(owner);
+ media_source->setTarget(target);
+ media_source->setSize(default_width, default_height);
+
+ return media_source;
+ }
+ }
if(plugin_basename.empty())
{
@@ -1673,7 +1799,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
}
else
{
- LLPluginClassMedia* media_source = new LLPluginClassMedia(owner);
+ media_source = new LLPluginClassMedia(owner);
media_source->setSize(default_width, default_height);
media_source->setUserDataPath(user_data_path);
media_source->setLanguageCode(LLUI::getLanguage());
@@ -1692,7 +1818,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
media_source->setTarget(target);
- if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
+ const std::string plugin_dir = gDirUtilp->getLLPluginDir();
+ if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
{
return media_source;
}
@@ -1753,6 +1880,18 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
media_source->focus(mHasFocus);
media_source->setBackgroundColor(mBackgroundColor);
+ if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors"))
+ {
+ media_source->ignore_ssl_cert_errors(true);
+ }
+
+ // the correct way to deal with certs it to load ours from CA.pem and append them to the ones
+ // Qt/WebKit loads from your system location.
+ // Note: This needs the new CA.pem file with the Equifax Secure Certificate Authority
+ // cert at the bottom: (MIIDIDCCAomgAwIBAgIENd70zzANBg)
+ std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" );
+ media_source->addCertificateFilePath( ca_path );
+
media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
if(mClearCache)
@@ -1849,6 +1988,18 @@ void LLViewerMediaImpl::setSize(int width, int height)
}
//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::showNotification(LLNotificationPtr notify)
+{
+ mNotification = notify;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::hideNotification()
+{
+ mNotification.reset();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::play()
{
// If the media source isn't there, try to initialize it and load an URL.
@@ -2850,7 +3001,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL;
std::string url = plugin->getClickURL();
LLURLDispatcher::dispatch(url, NULL, mTrustedBrowser);
-
}
break;
case MEDIA_EVENT_CLICK_LINK_HREF:
@@ -2913,6 +3063,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL;
+ hideNotification();
if(getNavState() == MEDIANAVSTATE_SERVER_SENT)
{
@@ -3003,7 +3154,26 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
plugin->sendPickFileResponse(response);
}
break;
-
+
+
+ case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST:
+ {
+ LLNotification::Params auth_request_params;
+ auth_request_params.name = "AuthRequest";
+
+ // pass in host name and realm for site (may be zero length but will always exist)
+ LLSD args;
+ LLURL raw_url( plugin->getAuthURL().c_str() );
+ args["HOST_NAME"] = raw_url.getAuthority();
+ args["REALM"] = plugin->getAuthRealm();
+ auth_request_params.substitutions = args;
+
+ auth_request_params.payload = LLSD().with("media_id", mTextureId);
+ auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
+ LLNotifications::instance().add(auth_request_params);
+ };
+ break;
+
case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST:
{
std::string uuid = plugin->getClickUUID();
@@ -3019,6 +3189,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// This close request is directed at another instance
pass_through = false;
LLFloaterMediaBrowser::closeRequest(uuid);
+ LLFloaterWebContent::closeRequest(uuid);
}
}
break;
@@ -3038,6 +3209,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// This request is directed at another instance
pass_through = false;
LLFloaterMediaBrowser::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
+ LLFloaterWebContent::geometryChanged(uuid, plugin->getGeometryX(), plugin->getGeometryY(), plugin->getGeometryWidth(), plugin->getGeometryHeight());
}
}
break;
@@ -3521,6 +3693,11 @@ bool LLViewerMediaImpl::isInAgentParcel() const
return result;
}
+LLNotificationPtr LLViewerMediaImpl::getCurrentNotification() const
+{
+ return mNotification;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
//
// static
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 4025a4484f..e2e342cc45 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -37,6 +37,7 @@
#include "llpluginclassmedia.h"
#include "v4color.h"
+#include "llnotificationptr.h"
#include "llurl.h"
@@ -130,6 +131,8 @@ public:
static bool isParcelMediaPlaying();
static bool isParcelAudioPlaying();
+ static void onAuthSubmit(const LLSD& notification, const LLSD& response);
+
// Clear all cookies for all plugins
static void clearAllCookies();
@@ -155,6 +158,9 @@ public:
static void proxyWindowOpened(const std::string &target, const std::string &uuid);
static void proxyWindowClosed(const std::string &uuid);
+ static void createSpareBrowserMediaSource();
+ static LLPluginClassMedia* getSpareBrowserMediaSource();
+
private:
static void setOpenIDCookie();
static void onTeleportFinished();
@@ -162,6 +168,7 @@ private:
static LLPluginCookieStore *sCookieStore;
static LLURL sOpenIDURL;
static std::string sOpenIDCookie;
+ static LLPluginClassMedia* sSpareBrowserMediaSource;
};
// Implementation functions not exported into header file
@@ -195,6 +202,9 @@ public:
LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
void setSize(int width, int height);
+ void showNotification(LLNotificationPtr notify);
+ void hideNotification();
+
void play();
void stop();
void pause();
@@ -387,6 +397,9 @@ public:
// Is this media in the agent's parcel?
bool isInAgentParcel() const;
+ // get currently active notification associated with this media instance
+ LLNotificationPtr getCurrentNotification() const;
+
private:
bool isAutoPlayable() const;
bool shouldShowBasedOnClass() const;
@@ -444,7 +457,8 @@ private:
bool mNavigateSuspendedDeferred;
bool mTrustedBrowser;
std::string mTarget;
-
+ LLNotificationPtr mNotification;
+
private:
BOOL mIsUpdated ;
std::list< LLVOVolume* > mObjectList ;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ccf3df827d..bd46ee1b67 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -45,7 +45,7 @@
#include "llconsole.h"
#include "lldebugview.h"
#include "llfilepicker.h"
-//#include "llfirstuse.h"
+#include "llfirstuse.h"
#include "llfloaterbuy.h"
#include "llfloaterbuycontents.h"
#include "llbuycurrencyhtml.h"
@@ -191,6 +191,8 @@ BOOL is_selection_buy_not_take();
S32 selection_price();
BOOL enable_take();
void handle_take();
+void handle_object_show_inspector();
+void handle_avatar_show_inspector();
bool confirm_take(const LLSD& notification, const LLSD& response);
void handle_buy_object(LLSaleInfo sale_info);
@@ -221,8 +223,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*);
@@ -557,7 +557,7 @@ class LLAdvancedCheckConsole : public view_listener_t
new_value = get_visibility( (void*)gDebugView->mMemoryView );
}
#endif
-
+
return new_value;
}
};
@@ -843,6 +843,55 @@ class LLAdvancedCheckFeature : public view_listener_t
}
};
+void toggle_destination_and_avatar_picker(const LLSD& show)
+{
+ S32 panel_idx = show.isDefined() ? show.asInteger() : -1;
+ LLView* container = gViewerWindow->getRootView()->findChildView("avatar_picker_and_destination_guide_container");
+ if (!container) return;
+
+ LLMediaCtrl* destinations = container->findChild<LLMediaCtrl>("destination_guide_contents");
+ LLMediaCtrl* avatar_picker = container->findChild<LLMediaCtrl>("avatar_picker_contents");
+ if (!destinations || !avatar_picker) return;
+
+ LLButton* avatar_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("avatar_btn");
+ LLButton* destination_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("destination_btn");
+
+ switch(panel_idx)
+ {
+ case 0:
+ if (!destinations->getVisible())
+ {
+ container->setVisible(true);
+ destinations->setVisible(true);
+ avatar_picker->setVisible(false);
+ LLFirstUse::notUsingDestinationGuide(false);
+ avatar_btn->setToggleState(false);
+ destination_btn->setToggleState(true);
+ return;
+ }
+ break;
+ case 1:
+ if (!avatar_picker->getVisible())
+ {
+ container->setVisible(true);
+ destinations->setVisible(false);
+ avatar_picker->setVisible(true);
+ avatar_btn->setToggleState(true);
+ destination_btn->setToggleState(false);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ container->setVisible(false);
+ destinations->setVisible(false);
+ avatar_picker->setVisible(false);
+ avatar_btn->setToggleState(false);
+ destination_btn->setToggleState(false);
+};
+
//////////////////
// INFO DISPLAY //
@@ -877,6 +926,10 @@ U32 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
}
+ else if ("update type" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_UPDATE_TYPE;
+ }
else if ("texture anim" == info_display)
{
return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
@@ -1384,37 +1437,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 +2016,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 +2040,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;
}
};
@@ -2823,7 +2855,7 @@ class LLObjectMute : public view_listener_t
}
LLMute mute(id, name, type);
- if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
+ if (LLMuteList::getInstance()->isMuted(mute.mID))
{
LLMuteList::getInstance()->remove(mute);
}
@@ -3608,6 +3640,15 @@ class LLEnableEditShape : public view_listener_t
}
};
+class LLEnableEditPhysics : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ //return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
+ return TRUE;
+ }
+};
+
bool is_object_sittable()
{
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
@@ -4160,6 +4201,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
@@ -4184,9 +4230,9 @@ class LLObjectEnableReturn : public view_listener_t
{
virtual bool apply(LLViewerObject* obj)
{
- return (obj->isOverAgentOwnedLand() ||
- obj->isOverGroupOwnedLand() ||
- obj->permModify());
+ return
+ obj->permModify() ||
+ obj->isReturnable();
}
} func;
const bool firstonly = true;
@@ -4312,6 +4358,33 @@ void handle_take()
}
}
+void handle_object_show_inspector()
+{
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ LLViewerObject* objectp = selection->getFirstRootObject(TRUE);
+ if (!objectp)
+ {
+ return;
+ }
+
+ LLSD params;
+ params["object_id"] = objectp->getID();
+ LLFloaterReg::showInstance("inspect_object", params);
+}
+
+void handle_avatar_show_inspector()
+{
+ LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+ if(avatar)
+ {
+ LLSD params;
+ params["avatar_id"] = avatar->getID();
+ LLFloaterReg::showInstance("inspect_avatar", params);
+ }
+}
+
+
+
bool confirm_take(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -4737,110 +4810,6 @@ class LLToolsSelectNextPart : public view_listener_t
}
};
-// in order to link, all objects must have the same owner, and the
-// agent must have the ability to modify all of the objects. However,
-// we're not answering that question with this method. The question
-// we're answering is: does the user have a reasonable expectation
-// that a link operation should work? If so, return true, false
-// otherwise. this allows the handle_link method to more finely check
-// the selection and give an error message when the uer has a
-// reasonable expectation for the link to work, but it will fail.
-class LLToolsEnableLink : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = false;
- // check if there are at least 2 objects selected, and that the
- // user can modify at least one of the selected objects.
-
- // in component mode, can't link
- if (!gSavedSettings.getBOOL("EditLinkedParts"))
- {
- if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2)
- {
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- return object->permModify();
- }
- } func;
- const bool firstonly = true;
- new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- }
- }
- return new_value;
- }
-};
-
-class LLToolsLink : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
- {
- LLNotificationsUtil::add("UnableToLinkWhileDownloading");
- return true;
- }
-
- S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (object_count > MAX_CHILDREN_PER_TASK + 1)
- {
- LLSD args;
- args["COUNT"] = llformat("%d", object_count);
- int max = MAX_CHILDREN_PER_TASK+1;
- args["MAX"] = llformat("%d", max);
- LLNotificationsUtil::add("UnableToLinkObjects", args);
- return true;
- }
-
- if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2)
- {
- LLNotificationsUtil::add("CannotLinkIncompleteSet");
- return true;
- }
- if(!LLSelectMgr::getInstance()->selectGetRootsModify())
- {
- LLNotificationsUtil::add("CannotLinkModify");
- return true;
- }
- LLUUID owner_id;
- std::string owner_name;
- if(!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name))
- {
- // we don't actually care if you're the owner, but novices are
- // the most likely to be stumped by this one, so offer the
- // easiest and most likely solution.
- LLNotificationsUtil::add("CannotLinkDifferentOwners");
- return true;
- }
- LLSelectMgr::getInstance()->sendLink();
- return true;
- }
-};
-
-class LLToolsEnableUnlink : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject();
- bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() &&
- first_editable_object &&
- !first_editable_object->isAttachment();
- return new_value;
- }
-};
-
-class LLToolsUnlink : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- LLSelectMgr::getInstance()->sendDelink();
- return true;
- }
-};
-
-
class LLToolsStopAllAnimations : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -5566,6 +5535,11 @@ void handle_edit_shape()
LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_shape"));
}
+void handle_edit_physics()
+{
+ LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_physics"));
+}
+
void handle_report_abuse()
{
// Prevent menu from appearing in screen shot.
@@ -5602,20 +5576,42 @@ class LLShowHelp : public view_listener_t
}
};
-class LLShowSidetrayPanel : public view_listener_t
+class LLToggleHelp : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- std::string panel_name = userdata.asString();
- // Toggle the panel
- if (!LLSideTray::getInstance()->isPanelActive(panel_name))
+ LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
+ if (help_browser && help_browser->isInVisibleChain())
{
- // LLFloaterInventory::showAgentInventory();
- LLSideTray::getInstance()->showPanel(panel_name, LLSD());
+ help_browser->closeFloater();
}
else
{
- LLSideTray::getInstance()->collapseSideBar();
+ std::string help_topic = userdata.asString();
+ LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+ vhelp->showTopic(help_topic);
+ }
+ return true;
+ }
+};
+
+class LLShowSidetrayPanel : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string panel_name = userdata.asString();
+
+ LLPanel* panel = LLSideTray::getInstance()->getPanel(panel_name);
+ if (panel)
+ {
+ if (panel->isInVisibleChain())
+ {
+ LLSideTray::getInstance()->hidePanel(panel_name);
+ }
+ else
+ {
+ LLSideTray::getInstance()->showPanel(panel_name);
+ }
}
return true;
}
@@ -5744,6 +5740,44 @@ class LLShowAgentProfile : public view_listener_t
}
};
+class LLToggleAgentProfile : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLUUID agent_id;
+ if (userdata.asString() == "agent")
+ {
+ agent_id = gAgent.getID();
+ }
+ else if (userdata.asString() == "hit object")
+ {
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+ if (objectp)
+ {
+ agent_id = objectp->getID();
+ }
+ }
+ else
+ {
+ agent_id = userdata.asUUID();
+ }
+
+ LLVOAvatar* avatar = find_avatar_from_object(agent_id);
+ if (avatar)
+ {
+ if (!LLAvatarActions::profileVisible(avatar->getID()))
+ {
+ LLAvatarActions::showProfile(avatar->getID());
+ }
+ else
+ {
+ LLAvatarActions::hideProfile(avatar->getID());
+ }
+ }
+ return true;
+ }
+};
+
class LLLandEdit : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -6518,16 +6552,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;
}
};
@@ -7152,7 +7176,13 @@ LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p
BOOL LLViewerMenuHolderGL::hideMenus()
{
- BOOL handled = LLMenuHolderGL::hideMenus();
+ BOOL handled = FALSE;
+
+ if (LLMenuHolderGL::hideMenus())
+ {
+ LLToolPie::instance().blockClickToWalk();
+ handled = TRUE;
+ }
// drop pie menu selection
mParcelSelection = NULL;
@@ -7183,44 +7213,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();
@@ -7231,6 +7223,12 @@ void handle_web_browser_test(const LLSD& param)
LLWeb::loadURLInternal(url);
}
+void handle_web_content_test(const LLSD& param)
+{
+ std::string url = param.asString();
+ LLWeb::loadWebURLInternal(url);
+}
+
void handle_buy_currency_test(void*)
{
std::string url =
@@ -7354,6 +7352,11 @@ class LLViewToggleBeacon : public view_listener_t
LLPipeline::toggleRenderPhysicalBeacons(NULL);
gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) );
}
+ else if (beacon == "moapbeacon")
+ {
+ LLPipeline::toggleRenderMOAPBeacons(NULL);
+ gSavedSettings.setBOOL( "moapbeacon", LLPipeline::getRenderMOAPBeacons(NULL) );
+ }
else if (beacon == "soundsbeacon")
{
LLPipeline::toggleRenderSoundBeacons(NULL);
@@ -7413,6 +7416,11 @@ class LLViewCheckBeaconEnabled : public view_listener_t
new_value = gSavedSettings.getBOOL( "scriptsbeacon");
LLPipeline::setRenderScriptedBeacons(new_value);
}
+ else if (beacon == "moapbeacon")
+ {
+ new_value = gSavedSettings.getBOOL( "moapbeacon");
+ LLPipeline::setRenderMOAPBeacons(new_value);
+ }
else if (beacon == "physicalbeacon")
{
new_value = gSavedSettings.getBOOL( "physicalbeacon");
@@ -7833,9 +7841,11 @@ void initialize_menus()
view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
+ view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics");
commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
commit.add("EditShape", boost::bind(&handle_edit_shape));
+ commit.add("EditPhysics", boost::bind(&handle_edit_physics));
// View menu
view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
@@ -7861,6 +7871,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");
@@ -7897,8 +7910,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
view_listener_t::addMenu(new LLToolsSelectNextPart(), "Tools.SelectNextPart");
- view_listener_t::addMenu(new LLToolsLink(), "Tools.Link");
- view_listener_t::addMenu(new LLToolsUnlink(), "Tools.Unlink");
+ commit.add("Tools.Link", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance()));
+ commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");
@@ -7911,8 +7924,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart");
- view_listener_t::addMenu(new LLToolsEnableLink(), "Tools.EnableLink");
- view_listener_t::addMenu(new LLToolsEnableUnlink(), "Tools.EnableUnlink");
+ enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance()));
+ enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
@@ -7934,9 +7947,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");
@@ -7981,7 +7991,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
// Advanced > UI
- commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2));
+ commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser
+ commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater
view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
@@ -8006,8 +8017,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 +8077,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");
@@ -8113,6 +8123,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
+ commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector));
view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));
@@ -8140,6 +8151,7 @@ void initialize_menus()
commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
commit.add("Object.Open", boost::bind(&handle_object_open));
commit.add("Object.Take", boost::bind(&handle_take));
+ commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
@@ -8178,8 +8190,10 @@ void initialize_menus()
commit.add("ReportAbuse", boost::bind(&handle_report_abuse));
commit.add("BuyCurrency", boost::bind(&handle_buy_currency));
view_listener_t::addMenu(new LLShowHelp(), "ShowHelp");
+ view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp");
view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");
view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
+ view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");
view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
@@ -8199,4 +8213,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints");
+
+ commit.add("Destination.show", boost::bind(&toggle_destination_and_avatar_picker, 0));
+ commit.add("Avatar.show", boost::bind(&toggle_destination_and_avatar_picker, 1));
}
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 87cb4efbc4..b4e239b0cd 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -126,6 +126,8 @@ bool enable_pay_object();
bool enable_buy_object();
bool handle_go_to();
+void toggle_destination_and_avatar_picker(const LLSD& show);
+
// Export to XML or Collada
void handle_export_selected( void * );
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 237aa39e6e..fda291f3c1 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -507,7 +507,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
"No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
short_name.c_str());
args["FILE"] = short_name;
- upload_error(error_message, "NofileExtension", filename, args);
+ upload_error(error_message, "NoFileExtension", filename, args);
return;
}
else if( exten == "bmp")
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9b1f2e67c6..8b52d478e6 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)
@@ -1198,8 +1199,6 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
// Highlight item
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)
@@ -1463,15 +1462,18 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// This is an offer from an agent. In this case, the back
// end has already copied the items into your inventory,
// so we can fetch it out of our inventory.
- LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(mObjectID, from_string);
- open_agent_offer->startFetch();
- if(catp || (itemp && itemp->isFinished()))
+ if (gSavedSettings.getBOOL("ShowOfferedInventory"))
{
- open_agent_offer->done();
- }
- else
- {
- opener = open_agent_offer;
+ LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(mObjectID, from_string);
+ open_agent_offer->startFetch();
+ if(catp || (itemp && itemp->isFinished()))
+ {
+ open_agent_offer->done();
+ }
+ else
+ {
+ opener = open_agent_offer;
+ }
}
}
break;
@@ -1511,7 +1513,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,11 +1717,18 @@ 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 +".";
- LLSD args;
- args["MESSAGE"] = log_message;
- LLNotificationsUtil::add("SystemMessage", args);
+
+ if (gSavedSettings.getBOOL("LogInventoryDecline"))
+ {
+ 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);
+ }
if (busy && (!mFromGroup && !mFromObject))
{
@@ -2501,15 +2515,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;
@@ -2721,6 +2726,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LLSD args;
args["slurl"] = location;
args["type"] = LLNotificationsUI::NT_NEARBYCHAT;
+
+ // Look for IRC-style emotes here so object name formatting is correct
+ std::string prefix = message.substr(0, 4);
+ if (prefix == "/me " || prefix == "/me'")
+ {
+ chat.mChatStyle = CHAT_STYLE_IRC;
+ }
+
LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args);
}
@@ -3032,6 +3045,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
}
else
{
+ args["NAME"] = source_name;
LLNotificationsUtil::add("OfferCallingCard", args, payload);
}
}
@@ -3346,6 +3360,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
// then this info is news to us.
void process_teleport_start(LLMessageSystem *msg, void**)
{
+ // on teleport, don't tell them about destination guide anymore
+ LLFirstUse::notUsingDestinationGuide(false);
U32 teleport_flags = 0x0;
msg->getU32("Info", "TeleportFlags", teleport_flags);
@@ -3750,8 +3766,19 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
}
else
{
- // This is likely just the initial logging in phase.
+ // This is initial log-in or a region crossing
gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+
+ if(LLStartUp::getStartupState() < STATE_STARTED)
+ { // This is initial log-in, not a region crossing:
+ // Set the camera looking ahead of the AV so send_agent_update() below
+ // will report the correct location to the server.
+ LLVector3 look_at_point = look_at;
+ look_at_point = agent_pos + look_at_point.rotVec(gAgent.getQuat());
+
+ static LLVector3 up_direction(0.0f, 0.0f, 1.0f);
+ LLViewerCamera::getInstance()->lookAt(agent_pos, look_at_point, up_direction);
+ }
}
if ( LLTracker::isTracking(NULL) )
@@ -3820,37 +3847,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
return;
}
- if (!gLastVersionChannel.empty())
- {
- // work out the URL for this server's Release Notes
- std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/";
- std::string server_version = version_channel;
- std::vector<std::string> s_vect;
- boost::algorithm::split(s_vect, server_version, isspace);
- for(U32 i = 0; i < s_vect.size(); i++)
- {
- if (i != (s_vect.size() - 1))
- {
- if(i != (s_vect.size() - 2))
- {
- url += s_vect[i] + "_";
- }
- else
- {
- url += s_vect[i] + "/";
- }
- }
- else
- {
- url += s_vect[i].substr(0,4);
- }
- }
-
- LLSD args;
- args["URL"] = url;
- LLNotificationsUtil::add("ServerVersionChanged", args);
- }
-
gLastVersionChannel = version_channel;
}
@@ -3867,6 +3863,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);
@@ -6302,6 +6299,9 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)
payload["from_id"] = target_id;
payload["SUPPRESS_TOAST"] = true;
LLNotificationsUtil::add("TeleportOfferSent", args, payload);
+
+ // Add the recepient to the recent people list.
+ LLRecentPeople::instance().add(target_id);
}
}
gAgent.sendReliableMessage();
@@ -6435,8 +6435,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 +6463,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()));
}
@@ -6670,6 +6684,8 @@ void process_initiate_download(LLMessageSystem* msg, void**)
void process_script_teleport_request(LLMessageSystem* msg, void**)
{
+ if (!gSavedSettings.getBOOL("ScriptsCanShowUI")) return;
+
std::string object_name;
std::string sim_name;
LLVector3 pos;
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index 6ff893f543..b4a9b8e677 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -117,7 +117,6 @@ void process_alert_core(const std::string& message, BOOL modal);
typedef std::list<LLMeanCollisionData*> mean_collision_list_t;
extern mean_collision_list_t gMeanCollisionList;
-void handle_show_mean_events(void *);
void process_mean_collision_alert_message(LLMessageSystem* msg, void**);
void process_frozen_message(LLMessageSystem* msg, void**);
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index b91e407c6d..a59afdc28a 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -31,6 +31,7 @@
#include "llviewercontrol.h"
#include "llsdserialize.h"
#include "llsecapi.h"
+#include "lltrans.h"
#include "llweb.h"
@@ -504,7 +505,8 @@ void LLGridManager::setGridChoice(const std::string& grid)
addGrid(grid_data);
}
mGrid = grid;
- gSavedSettings.setString("CurrentGrid", grid);
+ gSavedSettings.setString("CurrentGrid", grid);
+
updateIsInProductionGrid();
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index a58b0d68de..32cd8dbb39 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:
@@ -226,7 +233,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mState(0),
mMedia(NULL),
mClickAction(0),
- mAttachmentItemID(LLUUID::null)
+ mAttachmentItemID(LLUUID::null),
+ mLastUpdateType(OUT_UNKNOWN),
+ mLastUpdateCached(FALSE)
{
if (!is_global)
{
@@ -468,7 +477,6 @@ void LLViewerObject::initVOClasses()
llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
LLVOGrass::initClass();
LLVOWater::initClass();
- LLVOSky::initClass();
LLVOVolume::initClass();
}
@@ -508,20 +516,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)
// This method returns true if the object is over land owned by the
// agent.
-BOOL LLViewerObject::isOverAgentOwnedLand() const
+bool LLViewerObject::isReturnable()
{
- return mRegionp
- && mRegionp->getParcelOverlay()
- && mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion());
-}
+ if (isAttachment())
+ {
+ return false;
+ }
+ std::vector<LLBBox> boxes;
+ boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
+ }
-// This method returns true if the object is over land owned by the
-// agent.
-BOOL LLViewerObject::isOverGroupOwnedLand() const
-{
- return mRegionp
- && mRegionp->getParcelOverlay()
- && mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
+ return mRegionp
+ && mRegionp->objectIsReturnable(getPositionRegion(), boxes);
}
BOOL LLViewerObject::setParent(LLViewerObject* parent)
@@ -1839,7 +1850,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.normQuat();
- if (gPingInterpolate)
+ if (sPingInterpolate)
{
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
if (cdp)
@@ -1860,6 +1871,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)
@@ -2000,7 +2013,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 +2040,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 +2055,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 +2145,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 +2162,159 @@ 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 &&
+ sPhaseOutUpdateInterpolationTime > 0.0)
+ { // 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)
+ {
+ // Find out how many seconds since last packet arrived on the circuit
+ F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime();
+
+ if (!cdp->isAlive() || // Circuit is dead or blocked
+ cdp->isBlocked() || // or doesn't seem to be getting any packets
+ (time_since_last_packet > sPhaseOutUpdateInterpolationTime))
+ {
+ // 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);
+ }
+ }
+ }
+ }
+
+ 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);
@@ -2865,6 +3008,8 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
{
if (!mOnMap)
{
+ llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle()));
+
gObjectList.addToMap(this);
mOnMap = TRUE;
}
@@ -3392,8 +3537,8 @@ void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, BOOL damped)
// Set position relative to parent, if no parent, relative to region
if (!isRoot())
{
- LLViewerObject::setPosition(pos_parent);
- updateDrawable(damped);
+ LLViewerObject::setPosition(pos_parent, damped);
+ //updateDrawable(damped);
}
else
{
@@ -3434,6 +3579,7 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
LLVector3 position_offset = getPosition() * getParent()->getRotation();
((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset);
+ updateDrawable(damped);
}
else if (isJointChild())
{
@@ -3442,15 +3588,14 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
LLQuaternion inv_parent_rot = parent->getRotation();
inv_parent_rot.transQuat();
LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot;
- LLViewerObject::setPosition(pos_parent);
+ LLViewerObject::setPosition(pos_parent, damped);
}
else
{
- LLViewerObject::setPosition(pos_edit);
+ LLViewerObject::setPosition(pos_edit, damped);
mPositionRegion = pos_edit;
mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
- }
- updateDrawable(damped);
+ }
}
@@ -4972,6 +5117,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)
@@ -5245,6 +5404,26 @@ void LLViewerObject::setAttachmentItemID(const LLUUID &id)
mAttachmentItemID = id;
}
+EObjectUpdateType LLViewerObject::getLastUpdateType() const
+{
+ return mLastUpdateType;
+}
+
+void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type)
+{
+ mLastUpdateType = last_update_type;
+}
+
+BOOL LLViewerObject::getLastUpdateCached() const
+{
+ return mLastUpdateCached;
+}
+
+void LLViewerObject::setLastUpdateCached(BOOL last_update_cached)
+{
+ mLastUpdateCached = last_update_cached;
+}
+
const LLUUID &LLViewerObject::extractAttachmentItemID()
{
LLUUID item_id = LLUUID::null;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 7d697a4a5f..7afb7f464b 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -77,6 +77,7 @@ typedef enum e_object_update_type
OUT_TERSE_IMPROVED,
OUT_FULL_COMPRESSED,
OUT_FULL_CACHED,
+ OUT_UNKNOWN,
} EObjectUpdateType;
@@ -131,7 +132,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
@@ -226,12 +227,9 @@ public:
virtual BOOL hasLightTexture() const { return FALSE; }
// This method returns true if the object is over land owned by
- // the agent.
- BOOL isOverAgentOwnedLand() const;
-
- // True if over land owned by group of which the agent is
- // either officer or member.
- BOOL isOverGroupOwnedLand() const;
+ // the agent, one of its groups, or it encroaches and
+ // anti-encroachment is enabled
+ bool isReturnable();
/*
// This method will scan through this object, and then query the
@@ -464,7 +462,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 +508,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 +519,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 +613,7 @@ 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
+
// extra data sent from the sim...currently only used for tree species info
U8* mData;
@@ -669,9 +671,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
//--------------------------------------------------------------------
@@ -679,8 +693,15 @@ public:
const LLUUID &getAttachmentItemID() const;
void setAttachmentItemID(const LLUUID &id);
const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object
+ EObjectUpdateType getLastUpdateType() const;
+ void setLastUpdateType(EObjectUpdateType last_update_type);
+ BOOL getLastUpdateCached() const;
+ void setLastUpdateCached(BOOL last_update_cached);
+
private:
LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
+ EObjectUpdateType mLastUpdateType;
+ BOOL mLastUpdateCached;
};
///////////////////
@@ -717,8 +738,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 +756,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..979d91cfcb 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -56,6 +56,7 @@
#include "llresmgr.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
+#include "llviewerstatsrecorder.h"
#include "llvoavatarself.h"
#include "lltoolmgr.h"
#include "lltoolpie.h"
@@ -159,14 +160,13 @@ U64 LLViewerObjectList::getIndex(const U32 local_id,
return (((U64)index) << 32) | (U64)local_id;
}
-BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
+BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp)
{
- if(object.getRegion())
+ if(objectp && objectp->getRegion())
{
- U32 local_id = object.mLocalID;
- LLHost region_host = object.getRegion()->getHost();
- U32 ip = region_host.getAddress();
- U32 port = region_host.getPort();
+ U32 local_id = objectp->mLocalID;
+ U32 ip = objectp->getRegion()->getHost().getAddress();
+ U32 port = objectp->getRegion()->getHost().getPort();
U64 ipport = (((U64)ip) << 32) | (U64)port;
U32 index = sIPAndPortToIndex[ipport];
@@ -181,7 +181,7 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
}
// Found existing entry
- if (iter->second == object.getID())
+ if (iter->second == objectp->getID())
{ // Full UUIDs match, so remove the entry
sIndexAndLocalIDToUUID.erase(iter);
return TRUE;
@@ -297,8 +297,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
// have to transform to absolute coordinates.
num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
+ // I don't think this case is ever hit. TODO* Test this.
if (!cached && !compressed && update_type != OUT_FULL)
{
+ //llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;
gTerseObjectUpdates += num_objects;
S32 size;
if (mesgsys->getReceiveCompressedSize())
@@ -309,7 +311,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
size = mesgsys->getReceiveSize();
}
- // llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
+ //llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
}
else
{
@@ -340,9 +342,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U8 compressed_dpbuffer[2048];
LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
LLDataPacker *cached_dpp = NULL;
-
+
+#if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(regionp);
+#endif
+
for (i = 0; i < num_objects; i++)
{
+ // timer is unused?
LLTimer update_timer;
BOOL justCreated = FALSE;
@@ -354,9 +361,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
// Lookup data packer and add this id to cache miss lists if necessary.
- cached_dpp = regionp->getDP(id, crc);
+ U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
+ cached_dpp = regionp->getDP(id, crc, cache_miss_type);
if (cached_dpp)
{
+ // Cache Hit.
cached_dpp->reset();
cached_dpp->unpackUUID(fullid, "ID");
cached_dpp->unpackU32(local_id, "LocalID");
@@ -364,6 +373,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
else
{
+ // Cache Miss.
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type);
+ #endif
+
continue; // no data packer, skip this object
}
}
@@ -375,13 +389,15 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
compressed_dp.reset();
U32 flags = 0;
- if (update_type != OUT_TERSE_IMPROVED)
+ if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
}
+ // I don't think we ever use this flag from the server. DK 2010/12/09
if (flags & FLAGS_ZLIB_COMPRESSED)
{
+ //llinfos << "TEST: flags & FLAGS_ZLIB_COMPRESSED" << llendl;
compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);
uncompressed_length = 2048;
@@ -397,7 +413,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
- if (update_type != OUT_TERSE_IMPROVED)
+ if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
compressed_dp.unpackUUID(fullid, "ID");
compressed_dp.unpackU32(local_id, "LocalID");
@@ -417,7 +433,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
}
}
- else if (update_type != OUT_FULL)
+ else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only?
{
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
getUUIDFromLocal(fullid,
@@ -430,7 +446,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
mNumUnknownUpdates++;
}
}
- else
+ else // OUT_FULL only?
{
mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
@@ -455,19 +471,19 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
// << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion()
// << llendl;
//}
- removeFromLocalIDTable(*objectp);
+ removeFromLocalIDTable(objectp);
setUUIDAndLocal(fullid,
local_id,
gMessageSystem->getSenderIP(),
gMessageSystem->getSenderPort());
if (objectp->mLocalID != local_id)
- { // Update local ID in object with the one sent from the region
+ { // Update local ID in object with the one sent from the region
objectp->mLocalID = local_id;
}
if (objectp->getRegion() != regionp)
- { // Object changed region, so update it
+ { // Object changed region, so update it
objectp->updateRegion(regionp); // for LLVOAvatar
}
}
@@ -478,18 +494,24 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{
if (update_type == OUT_TERSE_IMPROVED)
{
- // llinfos << "terse update for an unknown object:" << fullid << llendl;
+ // llinfos << "terse update for an unknown object (compressed):" << fullid << llendl;
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
+ #endif
continue;
}
}
- else if (cached)
+ else if (cached) // Cache hit only?
{
}
else
{
if (update_type != OUT_FULL)
{
- // llinfos << "terse update for an unknown object:" << fullid << llendl;
+ //llinfos << "terse update for an unknown object:" << fullid << llendl;
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
+ #endif
continue;
}
@@ -499,7 +521,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
if (mDeadObjects.find(fullid) != mDeadObjects.end())
{
mNumDeadObjectUpdates++;
- // llinfos << "update for a dead object:" << fullid << llendl;
+ //llinfos << "update for a dead object:" << fullid << llendl;
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
+ #endif
continue;
}
#endif
@@ -507,6 +532,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
if (!objectp)
{
+ llinfos << "createObject failure for object: " << fullid << llendl;
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type);
+ #endif
continue;
}
justCreated = TRUE;
@@ -519,19 +548,26 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
}
+ bool bCached = false;
if (compressed)
{
- if (update_type != OUT_TERSE_IMPROVED)
+ if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
objectp->mLocalID = local_id;
}
processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
- if (update_type != OUT_TERSE_IMPROVED)
+ if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
+ bCached = true;
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
+ LLViewerStatsRecorder::instance()->recordCacheFullUpdate(local_id, update_type, result, objectp);
+ #else
objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
+ #endif
}
}
- else if (cached)
+ else if (cached) // Cache hit only?
{
objectp->mLocalID = local_id;
processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
@@ -544,8 +580,17 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
}
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->recordObjectUpdateEvent(local_id, update_type, objectp);
+ #endif
+ objectp->setLastUpdateType(update_type);
+ objectp->setLastUpdateCached(bCached);
}
+#if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
+#endif
+
LLVOAvatar::cullAvatarsByPixelArea();
}
@@ -654,19 +699,34 @@ 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
F32 last_time = gFrameTimeSeconds;
- U64 time = totalTime(); // this will become the new gFrameTime when the update is done
+ U64 time = totalTime(); // this will become the new gFrameTime when the update is done
// Time _can_ go backwards, for example if the user changes the system clock.
// It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here.
// llassert(time > gFrameTime);
F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC;
- gFrameTime = time;
+ gFrameTime = time;
F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;
gFrameTimeSeconds = (F32)time_since_start;
@@ -768,7 +828,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
{
std::string id_str;
objectp->mID.toString(id_str);
- std::string tmpstr = std::string("Par: ") + id_str;
+ std::string tmpstr = std::string("Par: ") + id_str;
addDebugBeacon(objectp->getPositionAgent(),
tmpstr,
LLColor4(1.f,0.f,0.f,1.f),
@@ -788,12 +848,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
std::string tmpstr;
if (objectp->getParent())
{
- tmpstr = std::string("ChP: ") + id_str;
+ tmpstr = std::string("ChP: ") + id_str;
text_color = LLColor4(0.f, 1.f, 0.f, 1.f);
}
else
{
- tmpstr = std::string("ChNoP: ") + id_str;
+ tmpstr = std::string("ChNoP: ") + id_str;
text_color = LLColor4(1.f, 0.f, 0.f, 1.f);
}
id = sIndexAndLocalIDToUUID[oi.mParentInfo];
@@ -824,13 +884,14 @@ void LLViewerObjectList::clearDebugText()
void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
{
LLMemType mt(LLMemType::MTYPE_OBJECT);
- if (mDeadObjects.count(objectp->mID))
+ if (mDeadObjects.find(objectp->mID) != mDeadObjects.end())
{
- llinfos << "Object " << objectp->mID << " already on dead list, ignoring cleanup!" << llendl;
- return;
+ llinfos << "Object " << objectp->mID << " already on dead list!" << llendl;
+ }
+ else
+ {
+ mDeadObjects.insert(objectp->mID);
}
-
- mDeadObjects.insert(std::pair<LLUUID, LLPointer<LLViewerObject> >(objectp->mID, objectp));
// Cleanup any references we have to this object
// Remove from object map so noone can look it up.
@@ -844,7 +905,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
// << objectp->getRegion()->getHost().getPort() << llendl;
//}
- removeFromLocalIDTable(*objectp);
+ removeFromLocalIDTable(objectp);
if (objectp->onActiveList())
{
@@ -1064,6 +1125,62 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
LLWorld::getInstance()->shiftRegions(offset);
}
+//debug code
+bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp)
+{
+ for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
+ {
+ LLViewerObject* objectp = *iter;
+
+ if(objectp->isDead() || objectp->getRegion() == regionp)
+ {
+ return true ;
+ }
+ }
+
+ return false ;
+}
+
+//make sure the region is cleaned up.
+void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp)
+{
+ std::set<LLViewerObject*> dead_object_list ;
+ std::set<LLViewerObject*> region_object_list ;
+ for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
+ {
+ LLViewerObject* objectp = *iter;
+
+ if(objectp->isDead())
+ {
+ dead_object_list.insert(objectp) ;
+ }
+ else if(objectp->getRegion() == regionp)
+ {
+ region_object_list.insert(objectp) ;
+ }
+ }
+
+ if(dead_object_list.size() > 0)
+ {
+ llwarns << "There are " << dead_object_list.size() << " dead objects on the map!" << llendl ;
+
+ for(std::set<LLViewerObject*>::iterator iter = dead_object_list.begin(); iter != dead_object_list.end(); ++iter)
+ {
+ cleanupReferences(*iter) ;
+ }
+ }
+ if(region_object_list.size() > 0)
+ {
+ llwarns << "There are " << region_object_list.size() << " objects not removed from the deleted region!" << llendl ;
+
+ for(std::set<LLViewerObject*>::iterator iter = region_object_list.begin(); iter != region_object_list.end(); ++iter)
+ {
+ (*iter)->markDead() ;
+ }
+ }
+}
+
+
void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
{
LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" );
@@ -1082,6 +1199,12 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
{
LLViewerObject* objectp = *iter;
+
+ if(objectp->isDead())//some dead objects somehow not cleaned.
+ {
+ continue ;
+ }
+
if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment())
{
continue;
@@ -1269,34 +1392,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;
@@ -1397,7 +1492,7 @@ LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCod
LLViewerObject *old_instance = findObject(id);
if (old_instance)
{
- cleanupReferences(old_instance);
+ //cleanupReferences(old_instance);
old_instance->markDead();
return createObject(pcode, regionp, id, old_instance->getLocalID(), LLHost());
@@ -1527,8 +1622,8 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
llinfos << "Agent: " << objectp->getPositionAgent() << llendl;
addDebugBeacon(objectp->getPositionAgent(),"");
#endif
- gPipeline.markMoved(objectp->mDrawable);
- objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);
+ gPipeline.markMoved(objectp->mDrawable);
+ objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);
// Flag the object as no longer orphaned
childp->mOrphaned = FALSE;
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index eba5584b57..22a7f97c38 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -87,6 +87,8 @@ public:
void shiftObjects(const LLVector3 &offset);
+ bool hasMapObjectInRegion(LLViewerRegion* regionp) ;
+ void clearAllMapObjectsInRegion(LLViewerRegion* regionp) ;
void renderObjectsForMap(LLNetMap &netmap);
void renderObjectBounds(const LLVector3 &center);
@@ -104,7 +106,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);
@@ -161,7 +162,7 @@ public:
const U32 ip,
const U32 port); // Requires knowledge of message system info!
- static BOOL removeFromLocalIDTable(const LLViewerObject &object);
+ static BOOL removeFromLocalIDTable(const LLViewerObject* objectp);
// Used ONLY by the orphaned object code.
static U64 getIndex(const U32 local_id, const U32 ip, const U32 port);
@@ -181,8 +182,7 @@ protected:
vobj_list_t mMapObjects;
- typedef std::map<LLUUID, LLPointer<LLViewerObject> > vo_map;
- vo_map mDeadObjects; // Need to keep multiple entries per UUID
+ std::set<LLUUID> mDeadObjects;
std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap;
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index 99e869dafc..40f0b43313 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -586,6 +586,18 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
}
break;
+
+ case MEDIA_EVENT_AUTH_REQUEST:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL;
+ }
+ break;
+
+ case MEDIA_EVENT_LINK_HOVERED:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
+ };
+ break;
};
}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 11de377410..fccd1156d3 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -850,7 +850,7 @@ LLParcel* LLViewerParcelMgr::getCollisionParcel() const
void LLViewerParcelMgr::render()
{
- if (mSelected && mRenderSelection)
+ if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection"))
{
// Rendering is done in agent-coordinates, so need to supply
// an appropriate offset to the render code.
@@ -1784,8 +1784,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
void optionally_start_music(const std::string& music_url)
{
- if (gSavedSettings.getBOOL("AudioStreamingMusic") &&
- gSavedSettings.getBOOL("AudioStreamingMedia"))
+ if (gSavedSettings.getBOOL("AudioStreamingMusic"))
{
// only play music when you enter a new parcel if the UI control for this
// was not *explicitly* stopped by the user. (part of SL-4878)
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index eee653b0c1..d07e06f6a7 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const
return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);
}
+bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const
+{
+ // boxes are expected to already be axis aligned
+ for (U32 i = 0; i < boxes.size(); ++i)
+ {
+ LLVector3 min = boxes[i].getMinAgent();
+ LLVector3 max = boxes[i].getMaxAgent();
+
+ S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+
+ for (S32 row = top; row <= bottom; row++)
+ {
+ for (S32 column = left; column <= right; column++)
+ {
+ U8 type = ownership(row, column);
+ if ((PARCEL_SELF == type)
+ || (PARCEL_GROUP == type))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const
{
S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 61be220312..c80baedda6 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -30,6 +30,7 @@
// The ownership data for land parcels.
// One of these structures per region.
+#include "llbbox.h"
#include "lldarray.h"
#include "llframetimer.h"
#include "lluuid.h"
@@ -54,6 +55,12 @@ public:
BOOL isOwnedSelf(const LLVector3& pos) const;
BOOL isOwnedGroup(const LLVector3& pos) const;
BOOL isOwnedOther(const LLVector3& pos) const;
+
+ // "encroaches" means the prim hangs over the parcel, but its center
+ // might be in another parcel. for now, we simply test axis aligned
+ // bounding boxes which isn't perfect, but is close
+ bool encroachesOwned(const std::vector<LLBBox>& boxes) const;
+
BOOL isSoundLocal(const LLVector3& pos) const;
BOOL isBuildCameraAllowed(const LLVector3& pos) const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7fb259e012..e1d3e8a0b3 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -59,6 +59,7 @@
#include "llurldispatcher.h"
#include "llviewerobjectlist.h"
#include "llviewerparceloverlay.h"
+#include "llviewerstatsrecorder.h"
#include "llvlmanager.h"
#include "llvlcomposition.h"
#include "llvocache.h"
@@ -66,6 +67,7 @@
#include "llworld.h"
#include "llspatialpartition.h"
#include "stringize.h"
+#include "llviewercontrol.h"
#ifdef LL_WINDOWS
#pragma warning(disable:4355)
@@ -266,6 +268,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
@@ -320,6 +323,12 @@ LLViewerRegion::~LLViewerRegion()
std::for_each(mObjectPartition.begin(), mObjectPartition.end(), DeletePointer());
}
+/*virtual*/
+const LLHost& LLViewerRegion::getHost() const
+{
+ return mHost;
+}
+
void LLViewerRegion::loadObjectCache()
{
if (mCacheLoaded)
@@ -1031,7 +1040,7 @@ void LLViewerRegion::getInfo(LLSD& info)
info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
}
-void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
+LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
{
U32 local_id = objectp->getLocalID();
U32 crc = objectp->getCRC();
@@ -1045,35 +1054,36 @@ void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinary
{
// Record a hit
entry->recordDupe();
+ return CACHE_UPDATE_DUPE;
}
- else
- {
- // Update the cache entry
- mCacheMap.erase(local_id);
- delete entry;
- entry = new LLVOCacheEntry(local_id, crc, dp);
- mCacheMap[local_id] = entry;
- }
- }
- else
- {
- // we haven't seen this object before
- // Create new entry and add to map
- if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
- {
- mCacheMap.erase(mCacheMap.begin());
- }
+ // Update the cache entry
+ mCacheMap.erase(local_id);
+ delete entry;
entry = new LLVOCacheEntry(local_id, crc, dp);
-
mCacheMap[local_id] = entry;
+ return CACHE_UPDATE_CHANGED;
+ }
+
+ // we haven't seen this object before
+
+ // Create new entry and add to map
+ eCacheUpdateResult result = CACHE_UPDATE_ADDED;
+ if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
+ {
+ mCacheMap.erase(mCacheMap.begin());
+ result = CACHE_UPDATE_REPLACED;
+
}
- return ;
+ entry = new LLVOCacheEntry(local_id, crc, dp);
+
+ mCacheMap[local_id] = entry;
+ return result;
}
// Get data packer for this object, if we have cached data
// AND the CRC matches. JC
-LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)
+LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)
{
llassert(mCacheLoaded);
@@ -1086,17 +1096,20 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)
{
// Record a hit
entry->recordHit();
+ cache_miss_type = CACHE_MISS_TYPE_NONE;
return entry->getDP(crc);
}
else
{
// llinfos << "CRC miss for " << local_id << llendl;
+ cache_miss_type = CACHE_MISS_TYPE_CRC;
mCacheMissCRC.put(local_id);
}
}
else
{
// llinfos << "Cache miss for " << local_id << llendl;
+ cache_miss_type = CACHE_MISS_TYPE_FULL;
mCacheMissFull.put(local_id);
}
return NULL;
@@ -1118,9 +1131,6 @@ void LLViewerRegion::requestCacheMisses()
S32 blocks = 0;
S32 i;
- const U8 CACHE_MISS_TYPE_FULL = 0;
- const U8 CACHE_MISS_TYPE_CRC = 1;
-
// Send full cache miss updates. For these, we KNOW we don't
// have a viewer object.
for (i = 0; i < full_count; i++)
@@ -1183,6 +1193,11 @@ void LLViewerRegion::requestCacheMisses()
mCacheDirty = TRUE ;
// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
+ #if LL_RECORD_VIEWER_STATS
+ LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this);
+ LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count);
+ LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
+ #endif
}
void LLViewerRegion::dumpCache()
@@ -1371,11 +1386,17 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
- capabilityNames.append("FetchInventory");
capabilityNames.append("ObjectMedia");
capabilityNames.append("ObjectMediaNavigate");
- capabilityNames.append("FetchLib");
- capabilityNames.append("FetchLibDescendents");
+
+ if (gSavedSettings.getBOOL("UseHTTPInventory"))
+ {
+ capabilityNames.append("FetchLib2");
+ capabilityNames.append("FetchLibDescendents2");
+ capabilityNames.append("FetchInventory2");
+ capabilityNames.append("FetchInventoryDescendents2");
+ }
+
capabilityNames.append("GetDisplayNames");
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
@@ -1399,6 +1420,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
capabilityNames.append("SetDisplayName");
+ capabilityNames.append("SimConsoleAsync");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TextureStats");
capabilityNames.append("UntrustedSimulatorMessage");
@@ -1411,9 +1433,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("UpdateNotecardTaskInventory");
capabilityNames.append("UpdateScriptTask");
capabilityNames.append("UploadBakedTexture");
+ capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
- capabilityNames.append("WebFetchInventoryDescendents");
// Please add new capabilities alphabetically to reduce
// merge conflicts.
@@ -1493,6 +1515,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
return NULL;
}
+// the viewer can not yet distinquish between normal- and estate-owned objects
+// so we collapse these two bits and enable the UI if either are set
+const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT
+ | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT;
+
+bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const
+{
+ return (mParcelOverlay != NULL)
+ && (mParcelOverlay->isOwnedSelf(pos)
+ || mParcelOverlay->isOwnedGroup(pos)
+ || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT)
+ && mParcelOverlay->encroachesOwned(boxes)) );
+}
+
void LLViewerRegion::showReleaseNotes()
{
std::string url = this->getCapability("ServerReleaseNotes");
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 1ba025312b..dd40b876cd 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -33,6 +33,7 @@
#include "lldarray.h"
#include "llwind.h"
+#include "llbbox.h"
#include "llcloud.h"
#include "llstat.h"
#include "v3dmath.h"
@@ -50,7 +51,7 @@
// Surface id's
#define LAND 1
#define WATER 2
-const U32 MAX_OBJECT_CACHE_ENTRIES = 10000;
+const U32 MAX_OBJECT_CACHE_ENTRIES = 50000;
class LLEventPoll;
@@ -73,6 +74,7 @@ public:
{
PARTITION_HUD=0,
PARTITION_TERRAIN,
+ PARTITION_VOIDWATER,
PARTITION_WATER,
PARTITION_TREE,
PARTITION_PARTICLE,
@@ -243,7 +245,7 @@ public:
LLEventPump& getCapAPI() { return mCapabilityListener.getCapAPI(); }
/// implements LLCapabilityProvider
- virtual LLHost getHost() const { return mHost; }
+ /*virtual*/ const LLHost& getHost() const;
const U64 &getHandle() const { return mHandle; }
LLSurface &getLand() const { return *mLandp; }
@@ -273,9 +275,24 @@ public:
void getInfo(LLSD& info);
+ typedef enum
+ {
+ CACHE_MISS_TYPE_FULL = 0,
+ CACHE_MISS_TYPE_CRC,
+ CACHE_MISS_TYPE_NONE
+ } eCacheMissType;
+
+ typedef enum
+ {
+ CACHE_UPDATE_DUPE = 0,
+ CACHE_UPDATE_CHANGED,
+ CACHE_UPDATE_ADDED,
+ CACHE_UPDATE_REPLACED
+ } eCacheUpdateResult;
+
// handle a full update message
- void cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
- LLDataPacker *getDP(U32 local_id, U32 crc);
+ eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
+ LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type);
void requestCacheMisses();
void addCacheMissFull(const U32 local_id);
@@ -292,6 +309,8 @@ public:
std::string getHttpUrl() const { return mHttpUrl ;}
LLSpatialPartition* getSpatialPartition(U32 type);
+
+ bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
public:
struct CompareDistance
{
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..874519a59f 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;
@@ -851,6 +852,8 @@ void send_stats()
body["DisplayNamesEnabled"] = gSavedSettings.getBOOL("UseDisplayNames");
body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames");
+ body["MinimalSkin"] = !gSavedSettings.getString("SessionSettingsFile").empty();
+
LLViewerStats::getInstance()->addToMessage(body);
LLHTTPClient::post(url, body, new ViewerStatsResponder());
}
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/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp
new file mode 100644
index 0000000000..e9d21b4848
--- /dev/null
+++ b/indra/newview/llviewerstatsrecorder.cpp
@@ -0,0 +1,258 @@
+/**
+ * @file llviewerstatsrecorder.cpp
+ * @brief record info about viewer events to a metrics log file
+ *
+ * $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 "llviewerstatsrecorder.h"
+
+#if LL_RECORD_VIEWER_STATS
+
+#include "llfile.h"
+#include "llviewerregion.h"
+#include "llviewerobject.h"
+
+
+// To do - something using region name or global position
+#if LL_WINDOWS
+ static const std::string STATS_FILE_NAME("C:\\ViewerObjectCacheStats.csv");
+#else
+ static const std::string STATS_FILE_NAME("/tmp/viewerstats.csv");
+#endif
+
+LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL;
+LLViewerStatsRecorder::LLViewerStatsRecorder() :
+ mObjectCacheFile(NULL),
+ mTimer(),
+ mRegionp(NULL),
+ mStartTime(0.f),
+ mProcessingTime(0.f)
+{
+ if (NULL != sInstance)
+ {
+ llerrs << "Attempted to create multiple instances of LLViewerStatsRecorder!" << llendl;
+ }
+ sInstance = this;
+ clearStats();
+}
+
+LLViewerStatsRecorder::~LLViewerStatsRecorder()
+{
+ if (mObjectCacheFile != NULL)
+ {
+ LLFile::close(mObjectCacheFile);
+ mObjectCacheFile = NULL;
+ }
+}
+
+// static
+void LLViewerStatsRecorder::initClass()
+{
+ sInstance = new LLViewerStatsRecorder();
+}
+
+// static
+void LLViewerStatsRecorder::cleanupClass()
+{
+ delete sInstance;
+ sInstance = NULL;
+}
+
+
+void LLViewerStatsRecorder::initStatsRecorder(LLViewerRegion *regionp)
+{
+ if (mObjectCacheFile == NULL)
+ {
+ mStartTime = LLTimer::getTotalTime();
+ mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb");
+ if (mObjectCacheFile)
+ { // Write column headers
+ std::ostringstream data_msg;
+ data_msg << "EventTime, "
+ << "ProcessingTime, "
+ << "CacheHits, "
+ << "CacheFullMisses, "
+ << "CacheCrcMisses, "
+ << "FullUpdates, "
+ << "TerseUpdates, "
+ << "CacheMissRequests, "
+ << "CacheMissResponses, "
+ << "CacheUpdateDupes, "
+ << "CacheUpdateChanges, "
+ << "CacheUpdateAdds, "
+ << "CacheUpdateReplacements, "
+ << "UpdateFailures"
+ << "\n";
+
+ fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile );
+ }
+ }
+}
+
+void LLViewerStatsRecorder::beginObjectUpdateEvents(LLViewerRegion *regionp)
+{
+ initStatsRecorder(regionp);
+ mRegionp = regionp;
+ mProcessingTime = LLTimer::getTotalTime();
+ clearStats();
+}
+
+void LLViewerStatsRecorder::clearStats()
+{
+ mObjectCacheHitCount = 0;
+ mObjectCacheMissFullCount = 0;
+ mObjectCacheMissCrcCount = 0;
+ mObjectFullUpdates = 0;
+ mObjectTerseUpdates = 0;
+ mObjectCacheMissRequests = 0;
+ mObjectCacheMissResponses = 0;
+ mObjectCacheUpdateDupes = 0;
+ mObjectCacheUpdateChanges = 0;
+ mObjectCacheUpdateAdds = 0;
+ mObjectCacheUpdateReplacements = 0;
+ mObjectUpdateFailures = 0;
+}
+
+
+void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type)
+{
+ mObjectUpdateFailures++;
+}
+
+void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type)
+{
+ if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type)
+ {
+ mObjectCacheMissFullCount++;
+ }
+ else
+ {
+ mObjectCacheMissCrcCount++;
+ }
+}
+
+void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp)
+{
+ switch (update_type)
+ {
+ case OUT_FULL:
+ mObjectFullUpdates++;
+ break;
+ case OUT_TERSE_IMPROVED:
+ mObjectTerseUpdates++;
+ break;
+ case OUT_FULL_COMPRESSED:
+ mObjectCacheMissResponses++;
+ break;
+ case OUT_FULL_CACHED:
+ mObjectCacheHitCount++;
+ break;
+ default:
+ llwarns << "Unknown update_type" << llendl;
+ break;
+ };
+}
+
+void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp)
+{
+ switch (update_result)
+ {
+ case LLViewerRegion::CACHE_UPDATE_DUPE:
+ mObjectCacheUpdateDupes++;
+ break;
+ case LLViewerRegion::CACHE_UPDATE_CHANGED:
+ mObjectCacheUpdateChanges++;
+ break;
+ case LLViewerRegion::CACHE_UPDATE_ADDED:
+ mObjectCacheUpdateAdds++;
+ break;
+ case LLViewerRegion::CACHE_UPDATE_REPLACED:
+ mObjectCacheUpdateReplacements++;
+ break;
+ default:
+ llwarns << "Unknown update_result type" << llendl;
+ break;
+ };
+}
+
+void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count)
+{
+ mObjectCacheMissRequests += count;
+}
+
+void LLViewerStatsRecorder::endObjectUpdateEvents()
+{
+ llinfos << "ILX: "
+ << mObjectCacheHitCount << " hits, "
+ << mObjectCacheMissFullCount << " full misses, "
+ << mObjectCacheMissCrcCount << " crc misses, "
+ << mObjectFullUpdates << " full updates, "
+ << mObjectTerseUpdates << " terse updates, "
+ << mObjectCacheMissRequests << " cache miss requests, "
+ << mObjectCacheMissResponses << " cache miss responses, "
+ << mObjectCacheUpdateDupes << " cache update dupes, "
+ << mObjectCacheUpdateChanges << " cache update changes, "
+ << mObjectCacheUpdateAdds << " cache update adds, "
+ << mObjectCacheUpdateReplacements << " cache update replacements, "
+ << mObjectUpdateFailures << " update failures"
+ << llendl;
+
+ S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures;
+ if (mObjectCacheFile != NULL &&
+ total_objects > 0)
+ {
+ std::ostringstream data_msg;
+ F32 processing32 = (F32) ((LLTimer::getTotalTime() - mProcessingTime) / 1000.0);
+
+ data_msg << getTimeSinceStart()
+ << ", " << processing32
+ << ", " << mObjectCacheHitCount
+ << ", " << mObjectCacheMissFullCount
+ << ", " << mObjectCacheMissCrcCount
+ << ", " << mObjectFullUpdates
+ << ", " << mObjectTerseUpdates
+ << ", " << mObjectCacheMissRequests
+ << ", " << mObjectCacheMissResponses
+ << ", " << mObjectCacheUpdateDupes
+ << ", " << mObjectCacheUpdateChanges
+ << ", " << mObjectCacheUpdateAdds
+ << ", " << mObjectCacheUpdateReplacements
+ << ", " << mObjectUpdateFailures
+ << "\n";
+
+ fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile );
+ }
+
+ clearStats();
+}
+
+F32 LLViewerStatsRecorder::getTimeSinceStart()
+{
+ return (F32) ((LLTimer::getTotalTime() - mStartTime) / 1000.0);
+}
+
+#endif
+
+
+
diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h
new file mode 100644
index 0000000000..612ac380f7
--- /dev/null
+++ b/indra/newview/llviewerstatsrecorder.h
@@ -0,0 +1,97 @@
+/**
+ * @file llviewerstatsrecorder.h
+ * @brief record info about viewer events to a metrics log file
+ *
+ * $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 LLVIEWERSTATSRECORDER_H
+#define LLVIEWERSTATSRECORDER_H
+
+
+// This is a diagnostic class used to record information from the viewer
+// for analysis.
+
+// This is normally 0. Set to 1 to enable viewer stats recording
+#define LL_RECORD_VIEWER_STATS 0
+
+
+#if LL_RECORD_VIEWER_STATS
+#include "llframetimer.h"
+#include "llviewerobject.h"
+#include "llviewerregion.h"
+
+class LLMutex;
+class LLViewerRegion;
+class LLViewerObject;
+
+class LLViewerStatsRecorder
+{
+ public:
+ LLViewerStatsRecorder();
+ ~LLViewerStatsRecorder();
+
+ static void initClass();
+ static void cleanupClass();
+ static LLViewerStatsRecorder* instance() {return sInstance; }
+
+ void initStatsRecorder(LLViewerRegion *regionp);
+
+ void beginObjectUpdateEvents(LLViewerRegion *regionp);
+ void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type);
+ void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type);
+ void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp);
+ void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp);
+ void recordRequestCacheMissesEvent(S32 count);
+ void endObjectUpdateEvents();
+
+ F32 getTimeSinceStart();
+
+private:
+ static LLViewerStatsRecorder* sInstance;
+
+ LLFILE * mObjectCacheFile; // File to write data into
+ LLFrameTimer mTimer;
+ LLViewerRegion* mRegionp;
+ F64 mStartTime;
+ F64 mProcessingTime;
+
+ S32 mObjectCacheHitCount;
+ S32 mObjectCacheMissFullCount;
+ S32 mObjectCacheMissCrcCount;
+ S32 mObjectFullUpdates;
+ S32 mObjectTerseUpdates;
+ S32 mObjectCacheMissRequests;
+ S32 mObjectCacheMissResponses;
+ S32 mObjectCacheUpdateDupes;
+ S32 mObjectCacheUpdateChanges;
+ S32 mObjectCacheUpdateAdds;
+ S32 mObjectCacheUpdateReplacements;
+ S32 mObjectUpdateFailures;
+
+
+ void clearStats();
+};
+#endif // LL_RECORD_VIEWER_STATS
+
+#endif // LLVIEWERSTATSRECORDER_H
+
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5c262838ae..cf7f3f80ad 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()
@@ -1203,12 +1214,15 @@ void LLViewerFetchedTexture::cleanup()
void LLViewerFetchedTexture::setForSculpt()
{
+ static const S32 MAX_INTERVAL = 8 ; //frames
+
mForSculpt = TRUE ;
if(isForSculptOnly() && !getBoundRecently())
{
destroyGLTexture() ; //sculpt image does not need gl texture.
}
checkCachedRawSculptImage() ;
+ setMaxVirtualSizeResetInterval(MAX_INTERVAL) ;
}
BOOL LLViewerFetchedTexture::isForSculptOnly() const
@@ -1503,7 +1517,7 @@ void LLViewerFetchedTexture::processTextureStats()
}
else if(!mFullWidth || !mFullHeight)
{
- mDesiredDiscardLevel = getMaxDiscardLevel() ;
+ mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel) ;
}
else
{
@@ -1846,10 +1860,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 +2089,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 +2119,8 @@ void LLViewerFetchedTexture::clearCallbackEntryList()
}
gTextureList.mCallbackList.erase(this);
- mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1;
mLoadedCallbackDesiredDiscardLevel = S8_MAX ;
- if(mForceToSaveRawImage)
+ if(needsToSaveRawImage())
{
destroySavedRawImage() ;
}
@@ -2151,14 +2166,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 +2210,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
mPauseLoadedCallBacks = FALSE ;
if(need_raw)
{
- mForceToSaveRawImage = TRUE ;
+ mSaveRawImage = TRUE ;
}
}
@@ -2227,16 +2241,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 +2323,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 +2401,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 +2437,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 +2457,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 +2536,11 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
return mRawImage;
}
+bool LLViewerFetchedTexture::needsToSaveRawImage()
+{
+ return mForceToSaveRawImage || mSaveRawImage ;
+}
+
void LLViewerFetchedTexture::destroyRawImage()
{
if (mAuxRawImage.notNull()) sAuxCount--;
@@ -2526,7 +2551,7 @@ void LLViewerFetchedTexture::destroyRawImage()
if(mIsRawImageValid)
{
- if(mForceToSaveRawImage)
+ if(needsToSaveRawImage())
{
saveRawImage() ;
}
@@ -2658,7 +2683,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 ;
}
@@ -2666,12 +2691,10 @@ void LLViewerFetchedTexture::saveRawImage()
mLastReferencedSavedRawImageTime = sCurrentTime ;
}
-void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, bool from_callback)
+void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard)
{
if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)
{
- llassert_always(from_callback || mBoostLevel == LLViewerTexture::BOOST_PREVIEW) ;
-
mForceToSaveRawImage = TRUE ;
mDesiredSavedRawDiscardLevel = desired_discard ;
@@ -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..d512f8ec3a 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;}
//---------------
@@ -464,7 +465,7 @@ public:
S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
BOOL isRawImageValid()const { return mIsRawImageValid ; }
- void forceToSaveRawImage(S32 desired_discard = 0, bool from_callback = false) ;
+ void forceToSaveRawImage(S32 desired_discard = 0) ;
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
void destroySavedRawImage() ;
LLImageRaw* getSavedRawImage() ;
@@ -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..10126219f8 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)
@@ -1513,42 +1531,45 @@ bool LLUIImageList::initFromFile()
return false;
}
- std::vector<std::string> paths;
- // path to current selected skin
- paths.push_back(gDirUtilp->getSkinDir()
- + gDirUtilp->getDirDelimiter()
- + "textures"
- + gDirUtilp->getDirDelimiter()
- + "textures.xml");
- // path to user overrides on current skin
- paths.push_back(gDirUtilp->getUserSkinDir()
- + gDirUtilp->getDirDelimiter()
- + "textures"
- + gDirUtilp->getDirDelimiter()
- + "textures.xml");
-
- // apply skinned xml files incrementally
- for(std::vector<std::string>::iterator path_it = paths.begin();
- path_it != paths.end();
- ++path_it)
- {
- // don't reapply base file to itself
- if (!path_it->empty() && (*path_it) != base_file_path)
- {
- LLXMLNodePtr update_root;
- if (LLXMLNode::parseFile(*path_it, update_root, NULL))
- {
- LLXMLNode::updateNode(root, update_root);
- }
- }
- }
-
UIImageDeclarations images;
LLXUIParser parser;
parser.readXUI(root, images, base_file_path);
+ // add components defined in current skin
+ std::string skin_update_path = gDirUtilp->getSkinDir()
+ + gDirUtilp->getDirDelimiter()
+ + "textures"
+ + gDirUtilp->getDirDelimiter()
+ + "textures.xml";
+ LLXMLNodePtr update_root;
+ if (skin_update_path != base_file_path
+ && LLXMLNode::parseFile(skin_update_path, update_root, NULL))
+ {
+ parser.readXUI(update_root, images, skin_update_path);
+ }
+
+ // add components defined in user override of current skin
+ skin_update_path = gDirUtilp->getUserSkinDir()
+ + gDirUtilp->getDirDelimiter()
+ + "textures"
+ + gDirUtilp->getDirDelimiter()
+ + "textures.xml";
+ if (skin_update_path != base_file_path
+ && LLXMLNode::parseFile(skin_update_path, update_root, NULL))
+ {
+ parser.readXUI(update_root, images, skin_update_path);
+ }
+
if (!images.validateBlock()) return false;
+ std::map<std::string, UIImageDeclaration> merged_declarations;
+ for (LLInitParam::ParamIterator<UIImageDeclaration>::const_iterator image_it = images.textures.begin();
+ image_it != images.textures.end();
+ ++image_it)
+ {
+ merged_declarations[image_it->name].overwriteFrom(*image_it);
+ }
+
enum e_decode_pass
{
PASS_DECODE_NOW,
@@ -1558,19 +1579,20 @@ bool LLUIImageList::initFromFile()
for (S32 cur_pass = PASS_DECODE_NOW; cur_pass < NUM_PASSES; cur_pass++)
{
- for (LLInitParam::ParamIterator<UIImageDeclaration>::const_iterator image_it = images.textures.begin();
- image_it != images.textures.end();
+ for (std::map<std::string, UIImageDeclaration>::const_iterator image_it = merged_declarations.begin();
+ image_it != merged_declarations.end();
++image_it)
{
- std::string file_name = image_it->file_name.isProvided() ? image_it->file_name() : image_it->name();
+ const UIImageDeclaration& image = image_it->second;
+ std::string file_name = image.file_name.isProvided() ? image.file_name() : image.name();
// load high priority textures on first pass (to kick off decode)
- enum e_decode_pass decode_pass = image_it->preload ? PASS_DECODE_NOW : PASS_DECODE_LATER;
+ enum e_decode_pass decode_pass = image.preload ? PASS_DECODE_NOW : PASS_DECODE_LATER;
if (decode_pass != cur_pass)
{
continue;
}
- preloadUIImage(image_it->name, file_name, image_it->use_mips, image_it->scale);
+ preloadUIImage(image.name, file_name, image.use_mips, image.scale);
}
if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload"))
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..8e049e76df 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -296,22 +296,34 @@ private:
line_list_t mLineList;
LLColor4 mTextColor;
-public:
- LLDebugText(LLViewerWindow* window) : mWindow(window) {}
-
void addText(S32 x, S32 y, const std::string &text)
{
mLineList.push_back(Line(text, x, y));
}
+
+ void clearText() { mLineList.clear(); }
+
+public:
+ LLDebugText(LLViewerWindow* window) : mWindow(window) {}
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;
std::string rwind_vector_text;
std::string audio_text;
+ static const std::string beacon_particle = LLTrans::getString("BeaconParticle");
+ static const std::string beacon_physical = LLTrans::getString("BeaconPhysical");
+ static const std::string beacon_scripted = LLTrans::getString("BeaconScripted");
+ static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch");
+ static const std::string beacon_sound = LLTrans::getString("BeaconSound");
+ static const std::string beacon_media = LLTrans::getString("BeaconMedia");
+ static const std::string particle_hiding = LLTrans::getString("ParticleHiding");
+
// Draw the statistics in a light gray
// and in a thin font
mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
@@ -321,6 +333,8 @@ public:
U32 ypos = 64;
const U32 y_inc = 20;
+ clearText();
+
if (gSavedSettings.getBOOL("DebugShowTime"))
{
const U32 y_inc2 = 15;
@@ -345,6 +359,14 @@ public:
addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
}
+#if LL_WINDOWS
+ if (gSavedSettings.getBOOL("DebugShowMemory"))
+ {
+ addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024));
+ ypos += y_inc;
+ }
+#endif
+
if (gDisplayCameraPos)
{
std::string camera_view_text;
@@ -550,38 +572,109 @@ public:
// only display these messages if we are actually rendering beacons at this moment
if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
{
- if (LLPipeline::getRenderParticleBeacons(NULL))
+ if (LLPipeline::getRenderMOAPBeacons(NULL))
{
- addText(xpos, ypos, "Viewing particle beacons (blue)");
+ addText(xpos, ypos, "Viewing media beacons (white)");
ypos += y_inc;
}
+
if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
{
- addText(xpos, ypos, "Hiding particles");
+ addText(xpos, ypos, particle_hiding);
ypos += y_inc;
}
- if (LLPipeline::getRenderPhysicalBeacons(NULL))
+
+ if (LLPipeline::getRenderParticleBeacons(NULL))
{
- addText(xpos, ypos, "Viewing physical object beacons (green)");
+ addText(xpos, ypos, "Viewing particle beacons (blue)");
+ ypos += y_inc;
+ }
+
+ if (LLPipeline::getRenderSoundBeacons(NULL))
+ {
+ addText(xpos, ypos, "Viewing sound beacons (yellow)");
ypos += y_inc;
}
+
if (LLPipeline::getRenderScriptedBeacons(NULL))
{
- addText(xpos, ypos, "Viewing scripted object beacons (red)");
+ addText(xpos, ypos, beacon_scripted);
ypos += y_inc;
}
else
if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
{
- addText(xpos, ypos, "Viewing scripted object with touch function beacons (red)");
+ addText(xpos, ypos, beacon_scripted_touch);
ypos += y_inc;
}
- if (LLPipeline::getRenderSoundBeacons(NULL))
+
+ if (LLPipeline::getRenderPhysicalBeacons(NULL))
{
- addText(xpos, ypos, "Viewing sound beacons (yellow)");
+ addText(xpos, ypos, "Viewing physical object beacons (green)");
+ 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;
}
}
+
+ if (gSavedSettings.getBOOL("DebugShowTextureInfo"))
+ {
+ LLViewerObject* objectp = NULL ;
+ //objectp = = gAgentCamera.getFocusObject();
+
+ LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
+ if (nodep)
+ {
+ objectp = nodep->getObject();
+ }
+ if (objectp && !objectp->isDead())
+ {
+ S32 num_faces = objectp->mDrawable->getNumFaces() ;
+
+ for(S32 i = 0 ; i < num_faces; i++)
+ {
+ LLFace* facep = objectp->mDrawable->getFace(i) ;
+ if(facep)
+ {
+ //addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0],
+ // facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1]));
+ //ypos += y_inc;
+
+ addText(xpos, ypos, llformat("v_size: %.3f: p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea()));
+ ypos += y_inc;
+
+ //const LLTextureEntry *tep = facep->getTextureEntry();
+ //if(tep)
+ //{
+ // addText(xpos, ypos, llformat("scale_s: %.3f: scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ;
+ // ypos += y_inc;
+ //}
+
+ LLViewerTexture* tex = facep->getTexture() ;
+ if(tex)
+ {
+ addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize()));
+ ypos += y_inc;
+ }
+ }
+ }
+ }
+ }
}
void draw()
@@ -1348,6 +1441,15 @@ LLViewerWindow::LLViewerWindow(
LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
}
+ LLCoordScreen scr;
+ mWindow->getSize(&scr);
+
+ if(fullscreen && ( scr.mX!=width || scr.mY!=height))
+ {
+ llwarns << "Fullscreen has forced us in to a different resolution now using "<<scr.mX<<" x "<<scr.mY<<llendl;
+ gSavedSettings.setS32("FullScreenWidth",scr.mX);
+ gSavedSettings.setS32("FullScreenHeight",scr.mY);
+ }
if (NULL == mWindow)
{
@@ -1359,7 +1461,7 @@ LLViewerWindow::LLViewerWindow(
LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
<< LL_ENDL;
#endif
- LLAppViewer::instance()->forceExit(1);
+ LLAppViewer::instance()->fastQuit(1);
}
// Get the real window rect the window was created with (since there are various OS-dependent reasons why
@@ -1393,7 +1495,7 @@ LLViewerWindow::LLViewerWindow(
{
gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
}
- LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"));
+ LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
if (LLFeatureManager::getInstance()->isSafe()
|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
@@ -1404,6 +1506,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"))
{
@@ -1521,11 +1628,13 @@ void LLViewerWindow::initBase()
mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();
mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();
- mPopupView = main_view->findChild<LLPopupView>("popup_holder");
+ mPopupView = main_view->getChild<LLPopupView>("popup_holder");
mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();
+ mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle();
// Constrain floaters to inside the menu and status bar regions.
gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
+ gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
@@ -1656,7 +1765,7 @@ void LLViewerWindow::initWorldUI()
{
LLRect hud_rect = full_window;
hud_rect.mBottom += 50;
- if (gMenuBarView)
+ if (gMenuBarView && gMenuBarView->isInVisibleChain())
{
hud_rect.mTop -= gMenuBarView->getRect().getHeight();
}
@@ -1685,6 +1794,26 @@ void LLViewerWindow::initWorldUI()
buttons_panel->setShape(buttons_panel_container->getLocalRect());
buttons_panel->setFollowsAll();
buttons_panel_container->addChild(buttons_panel);
+
+ LLView* avatar_picker_destination_guide_container = gViewerWindow->getRootView()->getChild<LLView>("avatar_picker_and_destination_guide_container");
+ avatar_picker_destination_guide_container->getChild<LLButton>("close")->setCommitCallback(boost::bind(toggle_destination_and_avatar_picker, LLSD()));
+ LLMediaCtrl* destinations = avatar_picker_destination_guide_container->findChild<LLMediaCtrl>("destination_guide_contents");
+ LLMediaCtrl* avatar_picker = avatar_picker_destination_guide_container->findChild<LLMediaCtrl>("avatar_picker_contents");
+ if (destinations)
+ {
+ destinations->navigateTo(gSavedSettings.getString("DestinationGuideURL"), "text/html");
+ }
+
+ if (avatar_picker)
+ {
+ avatar_picker->navigateTo(gSavedSettings.getString("AvatarPickerURL"), "text/html");
+ }
+
+ if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+ {
+ toggle_destination_and_avatar_picker(0);
+ gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
+ }
}
// Destroy the UI
@@ -1839,6 +1968,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 +2371,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))
@@ -2935,18 +3080,20 @@ void LLViewerWindow::updateKeyboardFocus()
LLUICtrl* parent = cur_focus->getParentUICtrl();
const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
+ bool new_focus_found = false;
while(parent)
{
- if (parent->isCtrl() &&
- (parent->hasTabStop() || parent == focus_root) &&
- !parent->getIsChrome() &&
- parent->isInVisibleChain() &&
- parent->isInEnabledChain())
+ if (parent->isCtrl()
+ && (parent->hasTabStop() || parent == focus_root)
+ && !parent->getIsChrome()
+ && parent->isInVisibleChain()
+ && parent->isInEnabledChain())
{
if (!parent->focusFirstItem())
{
parent->setFocus(TRUE);
}
+ new_focus_found = true;
break;
}
parent = parent->getParentUICtrl();
@@ -2955,7 +3102,7 @@ void LLViewerWindow::updateKeyboardFocus()
// if we didn't find a better place to put focus, just release it
// hasFocus() will return true if and only if we didn't touch focus since we
// are only moving focus higher in the hierarchy
- if (cur_focus->hasFocus())
+ if (!new_focus_found)
{
cur_focus->setFocus(FALSE);
}
@@ -3875,18 +4022,26 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLPipeline::sShowHUDAttachments = FALSE;
}
+ // if not showing ui, use full window to render world view
+ updateWorldViewRect(!show_ui);
+
// Copy screen to a buffer
// crop sides or top and bottom, if taking a snapshot of different aspect ratio
// from window
- S32 snapshot_width = mWindowRectRaw.getWidth();
- S32 snapshot_height = mWindowRectRaw.getHeight();
+ LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw();
+
+ S32 snapshot_width = window_rect.getWidth();
+ S32 snapshot_height = window_rect.getHeight();
// SNAPSHOT
- S32 window_width = mWindowRectRaw.getWidth();
- S32 window_height = mWindowRectRaw.getHeight();
- LLRect window_rect = mWindowRectRaw;
- BOOL use_fbo = FALSE;
+ S32 window_width = snapshot_width;
+ S32 window_height = snapshot_height;
+
+ if (show_ui)
+ {
+ image_width = llmin(image_width, window_width);
+ image_height = llmin(image_height, window_height);
+ }
- LLRenderTarget target;
F32 scale_factor = 1.0f ;
if(!keep_window_aspect) //image cropping
{
@@ -3899,45 +4054,24 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
if(image_width > window_width || image_height > window_height) //need to enlarge the scene
{
- if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui)
- {
- GLint max_size = 0;
- glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
-
- if (image_width <= max_size && image_height <= max_size) //re-project the scene
- {
- use_fbo = TRUE;
-
- snapshot_width = image_width;
- snapshot_height = image_height;
- target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE);
- window_width = snapshot_width;
- window_height = snapshot_height;
- scale_factor = 1.f;
- mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0);
- target.bindTarget();
- }
- }
-
- if(!use_fbo) //no re-projection, so tiling the scene
- {
- F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
- snapshot_width = (S32)(ratio * image_width) ;
- snapshot_height = (S32)(ratio * image_height) ;
- scale_factor = llmax(1.0f, 1.0f / ratio) ;
- }
+ F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
+ snapshot_width = (S32)(ratio * image_width) ;
+ snapshot_height = (S32)(ratio * image_height) ;
+ scale_factor = llmax(1.0f, 1.0f / ratio) ;
}
- //else: keep the current scene scale, re-scale it if necessary after reading out.
}
- // if not showing ui, use full window to render world view
- updateWorldViewRect(!show_ui);
+ if (show_ui && scale_factor > 1.f)
+ {
+ llwarns << "over scaling UI not supported." << llendl;
+ }
S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
+
if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
{
scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
@@ -3946,7 +4080,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
}
if(image_buffer_x > 0 && image_buffer_y > 0)
{
- raw->resize(image_buffer_x, image_buffer_y, 3);
+ raw->resize(image_buffer_x, image_buffer_y, 3);
}
else
{
@@ -3958,12 +4092,13 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
}
BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
- if (high_res)
+ if (high_res && show_ui)
{
- send_agent_pause();
+ llwarns << "High res UI snapshot not supported. " << llendl;
+ /*send_agent_pause();
//rescale fonts
initFonts(scale_factor);
- LLHUDObject::reshapeAll();
+ LLHUDObject::reshapeAll();*/
}
S32 output_buffer_offset_y = 0;
@@ -3985,30 +4120,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 +4155,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,
@@ -4070,12 +4194,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
output_buffer_offset_y += subimage_y_offset;
}
- if (use_fbo)
- {
- mWindowRectRaw = window_rect;
- target.flush();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- }
gDisplaySwapBuffers = FALSE;
gDepthDirty = TRUE;
@@ -4090,11 +4208,11 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
LLPipeline::sShowHUDAttachments = TRUE;
}
- if (high_res)
+ /*if (high_res)
{
initFonts(1.f);
LLHUDObject::reshapeAll();
- }
+ }*/
// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
// Note: this formula depends on the number of components being 3. Not obvious, but it's correct.
@@ -4252,17 +4370,8 @@ void LLViewerWindow::setup3DRender()
void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
{
- if (LLRenderTarget::getCurrentBoundTarget() != NULL)
- {
- // don't use translation component of mWorldViewRectRaw, as we are already in a properly sized render target
- gGLViewport[0] = x_offset;
- gGLViewport[1] = y_offset;
- }
- else
- {
- gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
- gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
- }
+ gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
+ gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
gGLViewport[2] = mWorldViewRectRaw.getWidth();
gGLViewport[3] = mWorldViewRectRaw.getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
@@ -4415,6 +4524,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..5eeb02b080 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -186,11 +186,6 @@ public:
/*virtual*/ std::string translateString(const char* tag,
const std::map<std::string, std::string>& args);
- // signal on bottom tray width changed
- typedef boost::function<void (void)> bottom_tray_callback_t;
- typedef boost::signals2::signal<void (void)> bottom_tray_signal_t;
- bottom_tray_signal_t mOnBottomTrayWidthChanged;
- boost::signals2::connection setOnBottomTrayWidthChanged(bottom_tray_callback_t cb) { return mOnBottomTrayWidthChanged.connect(cb); }
// signal on update of WorldView rect
typedef boost::function<void (LLRect old_world_rect, LLRect new_world_rect)> world_rect_callback_t;
typedef boost::signals2::signal<void (LLRect old_world_rect, LLRect new_world_rect)> world_rect_signal_t;
@@ -288,6 +283,7 @@ public:
LLView* getNonSideTrayView() { return mNonSideTrayView.get(); }
LLView* getFloaterViewHolder() { return mFloaterViewHolder.get(); }
LLView* getHintHolder() { return mHintHolder.get(); }
+ LLView* getLoginPanelHolder() { return mLoginPanelHolder.get(); }
BOOL handleKey(KEY key, MASK mask);
void handleScrollWheel (S32 clicks);
@@ -316,8 +312,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,
@@ -448,6 +443,7 @@ protected:
LLHandle<LLView> mNonSideTrayView; // parent of world view + bottom bar, etc...everything but the side tray
LLHandle<LLView> mFloaterViewHolder; // container for floater_view
LLHandle<LLView> mHintHolder; // container for hints
+ LLHandle<LLView> mLoginPanelHolder; // container for login panel
LLPopupView* mPopupView; // container for transient popups
class LLDebugText* mDebugText; // Internal class for debug text
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..2c5e728c87 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -48,6 +48,7 @@
#include "llanimationstates.h"
#include "llavatarnamecache.h"
#include "llavatarpropertiesprocessor.h"
+#include "llphysicsmotion.h"
#include "llviewercontrol.h"
#include "llcallingcard.h" // IDEVO for LLAvatarTracker
#include "lldrawpoolavatar.h"
@@ -108,6 +109,8 @@ extern F32 ANIM_SPEED_MIN;
#include <boost/lexical_cast.hpp>
+// #define OUTPUT_BREAST_DATA
+
using namespace LLVOAvatarDefines;
//-----------------------------------------------------------------------------
@@ -123,6 +126,7 @@ const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d"
const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix"
const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target"
const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust"
+const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion"
//-----------------------------------------------------------------------------
@@ -599,16 +603,16 @@ F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
-const LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
+const LLUUID LLVOAvatar::sStepSoundOnLand("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
{
- LLUUID(SND_STONE_RUBBER),
- LLUUID(SND_METAL_RUBBER),
- LLUUID(SND_GLASS_RUBBER),
- LLUUID(SND_WOOD_RUBBER),
- LLUUID(SND_FLESH_RUBBER),
- LLUUID(SND_RUBBER_PLASTIC),
- LLUUID(SND_RUBBER_RUBBER)
+ SND_STONE_RUBBER,
+ SND_METAL_RUBBER,
+ SND_GLASS_RUBBER,
+ SND_WOOD_RUBBER,
+ SND_FLESH_RUBBER,
+ SND_RUBBER_PLASTIC,
+ SND_RUBBER_RUBBER
};
S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS;
@@ -620,6 +624,7 @@ BOOL LLVOAvatar::sShowAnimationDebug = FALSE;
BOOL LLVOAvatar::sShowFootPlane = FALSE;
BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
F32 LLVOAvatar::sLODFactor = 1.f;
+F32 LLVOAvatar::sPhysicsLODFactor = 1.f;
BOOL LLVOAvatar::sUseImpostors = FALSE;
BOOL LLVOAvatar::sJointDebug = FALSE;
@@ -1144,6 +1149,7 @@ void LLVOAvatar::initClass()
gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise");
gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion");
gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing");
gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye");
gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust");
@@ -1282,6 +1288,7 @@ void LLVOAvatar::initInstance(void)
// motions without a start/stop bit
registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create );
registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create );
+ registerMotion( ANIM_AGENT_PHYSICS_MOTION, LLPhysicsMotionController::create );
registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create );
registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create );
registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
@@ -1695,6 +1702,7 @@ void LLVOAvatar::startDefaultMotions()
startMotion( ANIM_AGENT_EYE );
startMotion( ANIM_AGENT_BODY_NOISE );
startMotion( ANIM_AGENT_BREATHE_ROT );
+ startMotion( ANIM_AGENT_PHYSICS_MOTION );
startMotion( ANIM_AGENT_HAND_MOTION );
startMotion( ANIM_AGENT_PELVIS_FIX );
@@ -2106,31 +2114,6 @@ void LLVOAvatar::computeBodySize()
gAgent.sendAgentSetAppearance();
}
}
-
-/* debug spam
- std::cout << "skull = " << skull << std::endl; // adebug
- std::cout << "head = " << head << std::endl; // adebug
- std::cout << "head_scale = " << head_scale << std::endl; // adebug
- std::cout << "neck = " << neck << std::endl; // adebug
- std::cout << "neck_scale = " << neck_scale << std::endl; // adebug
- std::cout << "chest = " << chest << std::endl; // adebug
- std::cout << "chest_scale = " << chest_scale << std::endl; // adebug
- std::cout << "torso = " << torso << std::endl; // adebug
- std::cout << "torso_scale = " << torso_scale << std::endl; // adebug
- std::cout << std::endl; // adebug
-
- std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug
- std::cout << std::endl; // adebug
-
- std::cout << "hip = " << hip << std::endl; // adebug
- std::cout << "hip_scale = " << hip_scale << std::endl; // adebug
- std::cout << "ankle = " << ankle << std::endl; // adebug
- std::cout << "ankle_scale = " << ankle_scale << std::endl; // adebug
- std::cout << "foot = " << foot << std::endl; // adebug
- std::cout << "mBodySize = " << mBodySize << std::endl; // adebug
- std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl; // adebug
- std::cout << std::endl; // adebug
-*/
}
//------------------------------------------------------------------------
@@ -2333,8 +2316,19 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
{
- // disable voice visualizer when in mouselook
- mVoiceVisualizer->setVoiceEnabled( voice_enabled && !(isSelf() && gAgentCamera.cameraMouselook()) );
+ bool render_visualizer = voice_enabled;
+
+ // Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled.
+ if(isSelf())
+ {
+ if(gAgentCamera.cameraMouselook() || gSavedSettings.getBOOL("VoiceDisableMic"))
+ {
+ render_visualizer = false;
+ }
+ }
+
+ mVoiceVisualizer->setVoiceEnabled(render_visualizer);
+
if ( voice_enabled )
{
//----------------------------------------------------------------
@@ -3024,7 +3018,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 +3986,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]);
@@ -6225,11 +6219,9 @@ void LLVOAvatar::updateMeshTextures()
// When an avatar is changing clothes and not in Appearance mode,
// use the last-known good baked texture until it finish the first
// render of the new layerset.
-
const BOOL layerset_invalid = mBakedTextureDatas[i].mTexLayerSet
&& ( !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized()
|| !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable() );
-
use_lkg_baked_layer[i] = (!is_layer_baked[i]
&& (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR)
&& layerset_invalid);
@@ -7864,6 +7856,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/llvoavatar.h b/indra/newview/llvoavatar.h
index a779a1735c..3659fb055f 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -50,6 +50,7 @@
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
+extern const LLUUID ANIM_AGENT_PHYSICS_MOTION;
extern const LLUUID ANIM_AGENT_EDITING;
extern const LLUUID ANIM_AGENT_EYE;
extern const LLUUID ANIM_AGENT_FLY_ADJUST;
@@ -240,6 +241,7 @@ public:
static BOOL sDebugInvisible;
static BOOL sShowAttachmentPoints;
static F32 sLODFactor; // user-settable LOD factor
+ static F32 sPhysicsLODFactor; // user-settable physics LOD factor
static BOOL sJointDebug; // output total number of joints being touched for each avatar
static BOOL sDebugAvatarRotation;
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index e5cbf65682..5f9e343907 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -783,11 +783,19 @@ void LLVOAvatarSelf::removeMissingBakedTextures()
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
const S32 te = mBakedTextureDatas[i].mTextureIndex;
- LLViewerTexture* tex = getTEImage(te) ;
+ const LLViewerTexture* tex = getTEImage(te);
+
+ // Replace with default if we can't find the asset, assuming the
+ // default is actually valid (which it should be unless something
+ // is seriously wrong).
if (!tex || tex->isMissingAsset())
{
- setTEImage(te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR));
- removed = TRUE;
+ LLViewerTexture *imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
+ if (imagep)
+ {
+ setTEImage(te, imagep);
+ removed = TRUE;
+ }
}
}
@@ -806,7 +814,23 @@ 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 +844,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 +854,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..b888a263d0 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)
{
@@ -39,6 +40,7 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
return apr_file->write(src, n_bytes) == n_bytes ;
}
+
//---------------------------------------------------------------------------
// LLVOCacheEntry
//---------------------------------------------------------------------------
@@ -69,6 +71,7 @@ LLVOCacheEntry::LLVOCacheEntry()
}
LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
+ : mBuffer(NULL)
{
S32 size = -1;
BOOL success;
@@ -133,7 +136,10 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
LLVOCacheEntry::~LLVOCacheEntry()
{
- delete [] mBuffer;
+ if(mBuffer)
+ {
+ delete[] mBuffer;
+ }
}
@@ -211,8 +217,8 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
if(success)
{
success = check_write(apr_file, (void*)mBuffer, size);
+ }
}
-}
return success ;
}
@@ -223,7 +229,9 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
// Format string used to construct filename for the object cache
static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc";
-const U32 NUM_ENTRIES_TO_PURGE = 16 ;
+const U32 MAX_NUM_OBJECT_ENTRIES = 128 ;
+const U32 MIN_ENTRIES_TO_PURGE = 16 ;
+const U32 INVALID_TIME = 0 ;
const char* object_cache_dirname = "objectcache";
const char* header_filename = "object.cache";
@@ -231,11 +239,11 @@ LLVOCache* LLVOCache::sInstance = NULL;
//static
LLVOCache* LLVOCache::getInstance()
-{
+{
if(!sInstance)
{
sInstance = new LLVOCache() ;
-}
+ }
return sInstance ;
}
@@ -261,13 +269,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,22 +293,27 @@ void LLVOCache::setDirNames(ELLPath location)
void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
{
+ if(!mEnabled)
+ {
+ llwarns << "Not initializing cache: Cache is currently disabled." << llendl;
+ return ;
+ }
+
if(mInitialized)
{
+ llwarns << "Cache already initialized." << llendl;
return ;
}
+ mInitialized = TRUE ;
setDirNames(location);
if (!mReadOnly)
{
LLFile::mkdir(mObjectCacheDirName);
}
-
- mCacheSize = size;
-
+ mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES);
mMetaInfo.mVersion = cache_version;
- readCacheHeader();
- mInitialized = TRUE ;
+ readCacheHeader();
if(mMetaInfo.mVersion != cache_version)
{
@@ -316,12 +333,16 @@ void LLVOCache::removeCache(ELLPath location)
{
if(mReadOnly)
{
+ llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl;
return ;
}
+ llinfos << "about to remove the object cache due to settings." << llendl ;
+
std::string delem = gDirUtilp->getDirDelimiter();
std::string mask = delem + "*";
std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
+ llinfos << "Removing cache at " << cache_dir << llendl;
gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files
LLFile::rmdir(cache_dir);
@@ -334,17 +355,56 @@ void LLVOCache::removeCache()
llassert_always(mInitialized) ;
if(mReadOnly)
{
+ llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl;
return ;
}
+ llinfos << "about to remove the object cache due to some error." << llendl ;
+
std::string delem = gDirUtilp->getDirDelimiter();
std::string mask = delem + "*";
+ llinfos << "Removing cache at " << mObjectCacheDirName << llendl;
gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);
clearCacheInMemory() ;
writeCacheHeader();
}
+void LLVOCache::removeEntry(HeaderEntryInfo* entry)
+{
+ llassert_always(mInitialized) ;
+ if(mReadOnly)
+ {
+ return ;
+ }
+ if(!entry)
+ {
+ return ;
+ }
+
+ header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry) ;
+ if(iter != mHeaderEntryQueue.end())
+ {
+ mHandleEntryMap.erase(entry->mHandle) ;
+ mHeaderEntryQueue.erase(iter) ;
+ removeFromCache(entry) ;
+ delete entry ;
+
+ mNumEntries = mHandleEntryMap.size() ;
+ }
+}
+
+void LLVOCache::removeEntry(U64 handle)
+{
+ handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
+ if(iter == mHandleEntryMap.end()) //no cache
+ {
+ return ;
+ }
+ HeaderEntryInfo* entry = iter->second ;
+ removeEntry(entry) ;
+}
+
void LLVOCache::clearCacheInMemory()
{
if(!mHeaderEntryQueue.empty())
@@ -357,6 +417,7 @@ void LLVOCache::clearCacheInMemory()
mHandleEntryMap.clear();
mNumEntries = 0 ;
}
+
}
void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename)
@@ -370,280 +431,326 @@ void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename)
return ;
}
-void LLVOCache::removeFromCache(U64 handle)
+void LLVOCache::removeFromCache(HeaderEntryInfo* entry)
{
if(mReadOnly)
{
+ llwarns << "Not removing cache for handle " << entry->mHandle << ": Cache is currently in read-only mode." << llendl;
return ;
}
std::string filename;
- getObjectCacheFilename(handle, filename);
- LLAPRFile::remove(filename, mLocalAPRFilePoolp);
+ getObjectCacheFilename(entry->mHandle, filename);
+ LLAPRFile::remove(filename, mLocalAPRFilePoolp);
+ entry->mTime = INVALID_TIME ;
+ updateEntry(entry) ; //update the head file.
}
-BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes)
-{
- if(!check_read(apr_file, src, n_bytes))
- {
- delete apr_file ;
- removeCache() ;
- return FALSE ;
- }
-
- return TRUE ;
-}
-
-BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes)
+void LLVOCache::readCacheHeader()
{
- if(!check_write(apr_file, src, n_bytes))
+ if(!mEnabled)
{
- delete apr_file ;
- removeCache() ;
- return FALSE ;
+ llwarns << "Not reading cache header: Cache is currently disabled." << llendl;
+ return;
}
- return TRUE ;
-}
-
-void LLVOCache::readCacheHeader()
-{
//clear stale info.
clearCacheInMemory();
+ bool success = true ;
if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp))
{
- LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp);
+ LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp);
//read the meta element
- if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)))
- {
- return ;
- }
-
- HeaderEntryInfo* entry ;
- mNumEntries = 0 ;
- while(mNumEntries < mCacheSize)
+ success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ;
+
+ if(success)
{
- entry = new HeaderEntryInfo() ;
- if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo)))
+ HeaderEntryInfo* entry = NULL ;
+ mNumEntries = 0 ;
+ U32 num_read = 0 ;
+ while(num_read++ < MAX_NUM_OBJECT_ENTRIES)
{
- delete entry ;
- return ;
+ if(!entry)
+ {
+ entry = new HeaderEntryInfo() ;
+ }
+ success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo));
+
+ if(!success) //failed
+ {
+ llwarns << "Error reading cache header entry. (entry_index=" << mNumEntries << ")" << llendl;
+ delete entry ;
+ entry = NULL ;
+ break ;
+ }
+ else if(entry->mTime == INVALID_TIME)
+ {
+ continue ; //an empty entry
+ }
+
+ entry->mIndex = mNumEntries++ ;
+ mHeaderEntryQueue.insert(entry) ;
+ mHandleEntryMap[entry->mHandle] = entry ;
+ entry = NULL ;
}
- else if(!entry->mTime) //end of the cache.
+ if(entry)
{
delete entry ;
- return ;
}
-
- entry->mIndex = mNumEntries++ ;
- mHeaderEntryQueue.insert(entry) ;
- mHandleEntryMap[entry->mHandle] = entry ;
}
- delete apr_file ;
+ //---------
+ //debug code
+ //----------
+ //std::string name ;
+ //for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter)
+ //{
+ // getObjectCacheFilename((*iter)->mHandle, name) ;
+ // llinfos << name << llendl ;
+ //}
+ //-----------
}
else
{
writeCacheHeader() ;
}
+
+ if(!success)
+ {
+ removeCache() ; //failed to read header, clear the cache
+ }
+ else if(mNumEntries >= mCacheSize)
+ {
+ purgeEntries(mCacheSize) ;
+ }
+
+ return ;
}
void LLVOCache::writeCacheHeader()
{
- if(mReadOnly)
+ if (!mEnabled)
{
- return ;
- }
-
- LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
+ llwarns << "Not writing cache header: Cache is currently disabled." << llendl;
+ return;
+ }
- //write the meta element
- if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)))
+ if(mReadOnly)
{
- return ;
+ llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl;
+ return;
}
- mNumEntries = 0 ;
- for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; iter != mHeaderEntryQueue.end(); ++iter)
+ bool success = true ;
{
- (*iter)->mIndex = mNumEntries++ ;
- if(!checkWrite(apr_file, (void*)*iter, sizeof(HeaderEntryInfo)))
+ LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
+
+ //write the meta element
+ success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ;
+
+
+ mNumEntries = 0 ;
+ for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter)
{
- return ;
+ (*iter)->mIndex = mNumEntries++ ;
+ success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo));
}
- }
-
- mNumEntries = mHeaderEntryQueue.size() ;
- if(mNumEntries < mCacheSize)
- {
- HeaderEntryInfo* entry = new HeaderEntryInfo() ;
- for(U32 i = mNumEntries ; i < mCacheSize; i++)
+
+ mNumEntries = mHeaderEntryQueue.size() ;
+ if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES)
{
- //fill the cache with the default entry.
- if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo)))
+ HeaderEntryInfo* entry = new HeaderEntryInfo() ;
+ entry->mTime = INVALID_TIME ;
+ for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++)
{
- mReadOnly = TRUE ; //disable the cache.
- return ;
+ //fill the cache with the default entry.
+ success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ;
+
}
+ delete entry ;
}
- delete entry ;
}
- delete apr_file ;
+
+ if(!success)
+ {
+ clearCacheInMemory() ;
+ mReadOnly = TRUE ; //disable the cache.
+ }
+ return ;
}
BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry)
{
- LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
- apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ;
+ LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
+ apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ;
- return checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ;
+ return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ;
}
void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)
{
+ if(!mEnabled)
+ {
+ llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl;
+ return ;
+ }
llassert_always(mInitialized);
handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
if(iter == mHandleEntryMap.end()) //no cache
{
+ llwarns << "No handle map entry for " << handle << llendl;
return ;
}
- std::string filename;
- getObjectCacheFilename(handle, filename);
- LLAPRFile* apr_file = new LLAPRFile(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp);
-
- LLUUID cache_id ;
- if(!checkRead(apr_file, cache_id.mData, UUID_BYTES))
+ bool success = true ;
{
- return ;
- }
- if(cache_id != id)
- {
- llinfos << "Cache ID doesn't match for this region, discarding"<< llendl;
-
- delete apr_file ;
- return ;
- }
+ std::string filename;
+ getObjectCacheFilename(handle, filename);
+ LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp);
+
+ LLUUID cache_id ;
+ success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ;
+
+ if(success)
+ {
+ if(cache_id != id)
+ {
+ llinfos << "Cache ID doesn't match for this region, discarding"<< llendl;
+ success = false ;
+ }
- S32 num_entries;
- if(!checkRead(apr_file, &num_entries, sizeof(S32)))
- {
- return ;
+ if(success)
+ {
+ S32 num_entries;
+ success = check_read(&apr_file, &num_entries, sizeof(S32)) ;
+
+ for (S32 i = 0; success && i < num_entries; i++)
+ {
+ LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file);
+ if (!entry->getLocalID())
+ {
+ llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
+ delete entry ;
+ success = false ;
+ }
+ cache_entry_map[entry->getLocalID()] = entry;
+ }
+ }
+ }
}
- for (S32 i = 0; i < num_entries; i++)
+ if(!success)
{
- LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file);
- if (!entry->getLocalID())
+ if(cache_entry_map.empty())
{
- llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
- delete entry ;
- break;
+ removeEntry(iter->second) ;
}
- cache_entry_map[entry->getLocalID()] = entry;
}
- num_entries = cache_entry_map.size() ;
- delete apr_file ;
return ;
}
-void LLVOCache::purgeEntries()
+void LLVOCache::purgeEntries(U32 size)
{
- U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ;
- while(mHeaderEntryQueue.size() > limit)
+ while(mHeaderEntryQueue.size() > size)
{
header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ;
- HeaderEntryInfo* entry = *iter ;
-
- removeFromCache(entry->mHandle) ;
- mHandleEntryMap.erase(entry->mHandle) ;
+ HeaderEntryInfo* entry = *iter ;
+ mHandleEntryMap.erase(entry->mHandle);
mHeaderEntryQueue.erase(iter) ;
- delete entry ;
+ removeFromCache(entry) ;
+ delete entry;
}
-
- writeCacheHeader() ;
- readCacheHeader() ;
mNumEntries = mHandleEntryMap.size() ;
}
void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache)
{
+ if(!mEnabled)
+ {
+ llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl;
+ return ;
+ }
llassert_always(mInitialized);
if(mReadOnly)
{
+ llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl;
return ;
- }
+ }
HeaderEntryInfo* entry;
handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
if(iter == mHandleEntryMap.end()) //new entry
- {
- if(mNumEntries >= mCacheSize)
+ {
+ if(mNumEntries >= mCacheSize - 1)
{
- purgeEntries() ;
+ purgeEntries(mCacheSize - 1) ;
}
-
+
entry = new HeaderEntryInfo();
entry->mHandle = handle ;
entry->mTime = time(NULL) ;
- entry->mIndex = mNumEntries++ ;
+ entry->mIndex = mNumEntries++;
mHeaderEntryQueue.insert(entry) ;
mHandleEntryMap[handle] = entry ;
}
else
{
- entry = iter->second ;
- entry->mTime = time(NULL) ;
+ // Update access time.
+ entry = iter->second ;
//resort
mHeaderEntryQueue.erase(entry) ;
+
+ entry->mTime = time(NULL) ;
mHeaderEntryQueue.insert(entry) ;
}
//update cache header
if(!updateEntry(entry))
{
+ llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl;
return ; //update failed.
}
if(!dirty_cache)
{
+ llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl;
return ; //nothing changed, no need to update.
}
//write to cache file
- std::string filename;
- getObjectCacheFilename(handle, filename);
- LLAPRFile* apr_file = new LLAPRFile(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
-
- if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES))
+ bool success = true ;
{
- return ;
- }
+ std::string filename;
+ getObjectCacheFilename(handle, filename);
+ LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
+
+ success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ;
- S32 num_entries = cache_entry_map.size() ;
- if(!checkWrite(apr_file, &num_entries, sizeof(S32)))
- {
- return ;
+
+ if(success)
+ {
+ S32 num_entries = cache_entry_map.size() ;
+ success = check_write(&apr_file, &num_entries, sizeof(S32));
+
+ for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
+ {
+ success = iter->second->writeToFile(&apr_file) ;
+ }
+ }
}
- for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); iter != cache_entry_map.end(); ++iter)
+ if(!success)
{
- if(!iter->second->writeToFile(apr_file))
- {
- //failed
- delete apr_file ;
- removeCache() ;
- return ;
- }
+ removeEntry(entry) ;
+
}
- delete apr_file ;
return ;
}
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index ccdff5e96c..14e3b4c793 100644
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -95,7 +95,12 @@ private:
{
bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const
{
- return lhs->mTime < rhs->mTime; // older entry in front of queue (set)
+ if(lhs->mTime == rhs->mTime)
+ {
+ return lhs < rhs ;
+ }
+
+ return lhs->mTime < rhs->mTime ; // older entry in front of queue (set)
}
};
typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t;
@@ -111,6 +116,7 @@ public:
void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ;
void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) ;
+ void removeEntry(U64 handle) ;
void setReadOnly(BOOL read_only) {mReadOnly = read_only;}
@@ -118,17 +124,17 @@ private:
void setDirNames(ELLPath location);
// determine the cache filename for the region from the region handle
void getObjectCacheFilename(U64 handle, std::string& filename);
- void removeFromCache(U64 handle);
+ void removeFromCache(HeaderEntryInfo* entry);
void readCacheHeader();
void writeCacheHeader();
void clearCacheInMemory();
void removeCache() ;
- void purgeEntries();
+ void removeEntry(HeaderEntryInfo* entry) ;
+ void purgeEntries(U32 size);
BOOL updateEntry(const HeaderEntryInfo* entry);
- BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) ;
- BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) ;
private:
+ BOOL mEnabled;
BOOL mInitialized ;
BOOL mReadOnly ;
HeaderMetaInfo mMetaInfo;
@@ -143,7 +149,7 @@ private:
static LLVOCache* sInstance ;
public:
static LLVOCache* getInstance() ;
- static BOOL hasInstance() ;
+ static BOOL hasInstance() ;
static void destroyClass() ;
};
diff --git a/indra/newview/llvoicecallhandler.cpp b/indra/newview/llvoicecallhandler.cpp
new file mode 100644
index 0000000000..2050dab689
--- /dev/null
+++ b/indra/newview/llvoicecallhandler.cpp
@@ -0,0 +1,69 @@
+ /**
+ * @file llvoicecallhandler.cpp
+ * @brief slapp to handle avatar to avatar voice call.
+ *
+ * $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 "llcommandhandler.h"
+#include "llavataractions.h"
+#include "llnotificationsutil.h"
+#include "llui.h"
+
+class LLVoiceCallAvatarHandler : public LLCommandHandler
+{
+public:
+ // requires trusted browser to trigger
+ LLVoiceCallAvatarHandler() : LLCommandHandler("voicecallavatar", UNTRUSTED_THROTTLE)
+ {
+ }
+
+ bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+ {
+ if (!LLUI::sSettingGroups["config"]->getBOOL("EnableVoiceCall"))
+ {
+ LLNotificationsUtil::add("NoVoiceCall", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
+ return true;
+ }
+
+ //Make sure we have some parameters
+ if (params.size() == 0)
+ {
+ return false;
+ }
+
+ //Get the ID
+ LLUUID id;
+ if (!id.set( params[0], FALSE ))
+ {
+ return false;
+ }
+
+ //instigate call with this avatar
+ LLAvatarActions::startCall( id );
+ return true;
+ }
+};
+
+LLVoiceCallAvatarHandler gVoiceCallAvatarHandler;
+
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index b692093fb9..a71539266d 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -853,7 +853,7 @@ void LLVoiceChannelP2P::activate()
}
// Add the party to the list of people with which we've recently interacted.
- LLRecentPeople::instance().add(mOtherUserID);
+ addToTheRecentPeopleList();
//Default mic is ON on initiating/joining P2P calls
if (!LLVoiceClient::getInstance()->getUserPTTState() && LLVoiceClient::getInstance()->getPTTIsToggle())
@@ -938,3 +938,25 @@ void LLVoiceChannelP2P::setState(EState state)
LLVoiceChannel::setState(state);
}
+
+void LLVoiceChannelP2P::addToTheRecentPeopleList()
+{
+ bool avaline_call = LLIMModel::getInstance()->findIMSession(mSessionID)->isAvalineSessionType();
+
+ if (avaline_call)
+ {
+ LLSD call_data;
+ std::string call_number = LLVoiceChannel::getSessionName();
+
+ call_data["avaline_call"] = true;
+ call_data["session_id"] = mSessionID;
+ call_data["call_number"] = call_number;
+ call_data["date"] = LLDate::now();
+
+ LLRecentPeople::instance().add(mOtherUserID, call_data);
+ }
+ else
+ {
+ LLRecentPeople::instance().add(mOtherUserID);
+ }
+}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 7cef3c13d1..b8597ee5cb 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -191,6 +191,13 @@ protected:
virtual void setState(EState state);
private:
+
+ /**
+ * Add the caller to the list of people with which we've recently interacted
+ *
+ **/
+ void addToTheRecentPeopleList();
+
std::string mSessionHandle;
LLUUID mOtherUserID;
BOOL mReceivedCall;
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 6c44f639ec..730f022c50 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -35,6 +35,7 @@
#include "llnotificationsutil.h"
#include "llsdserialize.h"
#include "llui.h"
+#include "llkeyboard.h"
const F32 LLVoiceClient::OVERDRIVEN_POWER_LEVEL = 0.7f;
@@ -113,8 +114,18 @@ LLVoiceClient::LLVoiceClient()
mVoiceModule(NULL),
m_servicePump(NULL),
mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled")),
- mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault"))
+ mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault")),
+ mPTTDirty(true),
+ mPTT(true),
+ mUsePTT(true),
+ mPTTIsMiddleMouse(false),
+ mPTTKey(0),
+ mPTTIsToggle(false),
+ mUserPTTState(false),
+ mMuteMic(false),
+ mDisableMic(false)
{
+ updateSettings();
}
//---------------------------------------------------
@@ -173,6 +184,14 @@ const LLVoiceVersionInfo LLVoiceClient::getVersion()
void LLVoiceClient::updateSettings()
{
+ setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
+ std::string keyString = gSavedSettings.getString("PushToTalkButton");
+ setPTTKey(keyString);
+ setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
+ mDisableMic = gSavedSettings.getBOOL("VoiceDisableMic");
+
+ updateMicMuteLogic();
+
if (mVoiceModule) mVoiceModule->updateSettings();
}
@@ -481,6 +500,26 @@ void LLVoiceClient::setVoiceEnabled(bool enabled)
if (mVoiceModule) mVoiceModule->setVoiceEnabled(enabled);
}
+void LLVoiceClient::updateMicMuteLogic()
+{
+ // If not configured to use PTT, the mic should be open (otherwise the user will be unable to speak).
+ bool new_mic_mute = false;
+
+ if(mUsePTT)
+ {
+ // If configured to use PTT, track the user state.
+ new_mic_mute = !mUserPTTState;
+ }
+
+ if(mMuteMic || mDisableMic)
+ {
+ // Either of these always overrides any other PTT setting.
+ new_mic_mute = true;
+ }
+
+ if (mVoiceModule) mVoiceModule->setMuteMic(new_mic_mute);
+}
+
void LLVoiceClient::setLipSyncEnabled(BOOL enabled)
{
if (mVoiceModule) mVoiceModule->setLipSyncEnabled(enabled);
@@ -500,7 +539,8 @@ BOOL LLVoiceClient::lipSyncEnabled()
void LLVoiceClient::setMuteMic(bool muted)
{
- if (mVoiceModule) mVoiceModule->setMuteMic(muted);
+ mMuteMic = muted;
+ updateMicMuteLogic();
}
@@ -509,64 +549,116 @@ void LLVoiceClient::setMuteMic(bool muted)
void LLVoiceClient::setUserPTTState(bool ptt)
{
- if (mVoiceModule) mVoiceModule->setUserPTTState(ptt);
+ mUserPTTState = ptt;
+ updateMicMuteLogic();
}
bool LLVoiceClient::getUserPTTState()
{
- if (mVoiceModule)
- {
- return mVoiceModule->getUserPTTState();
- }
- else
- {
- return false;
- }
+ return mUserPTTState;
}
void LLVoiceClient::setUsePTT(bool usePTT)
{
- if (mVoiceModule) mVoiceModule->setUsePTT(usePTT);
+ if(usePTT && !mUsePTT)
+ {
+ // When the user turns on PTT, reset the current state.
+ mUserPTTState = false;
+ }
+ mUsePTT = usePTT;
+
+ updateMicMuteLogic();
}
void LLVoiceClient::setPTTIsToggle(bool PTTIsToggle)
{
- if (mVoiceModule) mVoiceModule->setPTTIsToggle(PTTIsToggle);
+ if(!PTTIsToggle && mPTTIsToggle)
+ {
+ // When the user turns off toggle, reset the current state.
+ mUserPTTState = false;
+ }
+
+ mPTTIsToggle = PTTIsToggle;
+
+ updateMicMuteLogic();
}
bool LLVoiceClient::getPTTIsToggle()
{
- if (mVoiceModule)
+ return mPTTIsToggle;
+}
+
+void LLVoiceClient::setPTTKey(std::string &key)
+{
+ if(key == "MiddleMouse")
{
- return mVoiceModule->getPTTIsToggle();
+ mPTTIsMiddleMouse = true;
}
- else {
- return false;
+ else
+ {
+ mPTTIsMiddleMouse = false;
+ if(!LLKeyboard::keyFromString(key, &mPTTKey))
+ {
+ // If the call failed, don't match any key.
+ key = KEY_NONE;
+ }
}
-
}
void LLVoiceClient::inputUserControlState(bool down)
{
- if (mVoiceModule) mVoiceModule->inputUserControlState(down);
+ if(mPTTIsToggle)
+ {
+ if(down) // toggle open-mic state on 'down'
+ {
+ toggleUserPTTState();
+ }
+ }
+ else // set open-mic state as an absolute
+ {
+ setUserPTTState(down);
+ }
}
void LLVoiceClient::toggleUserPTTState(void)
{
- if (mVoiceModule) mVoiceModule->toggleUserPTTState();
+ setUserPTTState(!getUserPTTState());
}
void LLVoiceClient::keyDown(KEY key, MASK mask)
{
- if (mVoiceModule) mVoiceModule->keyDown(key, mask);
+ if (gKeyboard->getKeyRepeated(key))
+ {
+ // ignore auto-repeat keys
+ return;
+ }
+
+ if(!mPTTIsMiddleMouse)
+ {
+ bool down = (mPTTKey != KEY_NONE)
+ && gKeyboard->getKeyDown(mPTTKey);
+ inputUserControlState(down);
+ }
+
}
void LLVoiceClient::keyUp(KEY key, MASK mask)
{
- if (mVoiceModule) mVoiceModule->keyUp(key, mask);
+ if(!mPTTIsMiddleMouse)
+ {
+ bool down = (mPTTKey != KEY_NONE)
+ && gKeyboard->getKeyDown(mPTTKey);
+ inputUserControlState(down);
+ }
}
void LLVoiceClient::middleMouseState(bool down)
{
- if (mVoiceModule) mVoiceModule->middleMouseState(down);
+ if(mPTTIsMiddleMouse)
+ {
+ if(mPTTIsMiddleMouse)
+ {
+ inputUserControlState(down);
+ }
+ }
}
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 24d7d7163e..c9aeea35a9 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -191,25 +191,9 @@ public:
virtual void setVoiceEnabled(bool enabled)=0;
virtual void setLipSyncEnabled(BOOL enabled)=0;
virtual BOOL lipSyncEnabled()=0;
- virtual void setMuteMic(bool muted)=0; // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
+ virtual void setMuteMic(bool muted)=0; // Set the mute state of the local mic.
//@}
-
- ////////////////////////
- /// @name PTT
- //@{
- virtual void setUserPTTState(bool ptt)=0;
- virtual bool getUserPTTState()=0;
- virtual void setUsePTT(bool usePTT)=0;
- virtual void setPTTIsToggle(bool PTTIsToggle)=0;
- virtual bool getPTTIsToggle()=0;
- virtual void toggleUserPTTState(void)=0;
- virtual void inputUserControlState(bool down)=0; // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
-
- virtual void keyDown(KEY key, MASK mask)=0;
- virtual void keyUp(KEY key, MASK mask)=0;
- virtual void middleMouseState(bool down)=0;
- //@}
-
+
//////////////////////////
/// @name nearby speaker accessors
//@{
@@ -406,6 +390,9 @@ public:
void setUsePTT(bool usePTT);
void setPTTIsToggle(bool PTTIsToggle);
bool getPTTIsToggle();
+ void setPTTKey(std::string &key);
+
+ void updateMicMuteLogic();
BOOL lipSyncEnabled();
@@ -471,6 +458,17 @@ protected:
LLCachedControl<bool> mVoiceEffectEnabled;
LLCachedControl<std::string> mVoiceEffectDefault;
+
+ bool mPTTDirty;
+ bool mPTT;
+
+ bool mUsePTT;
+ bool mPTTIsMiddleMouse;
+ KEY mPTTKey;
+ bool mPTTIsToggle;
+ bool mUserPTTState;
+ bool mMuteMic;
+ bool mDisableMic;
};
/**
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 019629084f..08e242af8e 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -46,7 +46,6 @@
#include "llviewernetwork.h" // for gGridChoice
#include "llbase64.h"
#include "llviewercontrol.h"
-#include "llkeyboard.h"
#include "llappviewer.h" // for gDisconnected, gDisableVoice
// Viewer includes
@@ -326,14 +325,8 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
mRenderDeviceDirty(false),
mSpatialCoordsDirty(false),
- mPTTDirty(true),
- mPTT(true),
- mUsePTT(true),
- mPTTIsMiddleMouse(false),
- mPTTKey(0),
- mPTTIsToggle(false),
- mUserPTTState(false),
mMuteMic(false),
+ mMuteMicDirty(false),
mFriendsListDirty(true),
mEarLocation(0),
@@ -435,10 +428,6 @@ const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion()
void LLVivoxVoiceClient::updateSettings()
{
setVoiceEnabled(gSavedSettings.getBOOL("EnableVoiceChat"));
- setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
- std::string keyString = gSavedSettings.getString("PushToTalkButton");
- setPTTKey(keyString);
- setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
setEarLocation(gSavedSettings.getS32("VoiceEarLocation"));
std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
@@ -950,7 +939,7 @@ void LLVivoxVoiceClient::stateMachine()
setState(stateDaemonLaunched);
// Dirty the states we'll need to sync with the daemon when it comes up.
- mPTTDirty = true;
+ mMuteMicDirty = true;
mMicVolumeDirty = true;
mSpeakerVolumeDirty = true;
mSpeakerMuteDirty = true;
@@ -1535,7 +1524,7 @@ void LLVivoxVoiceClient::stateMachine()
if(mAudioSession && mAudioSession->mVoiceEnabled)
{
// Dirty state that may need to be sync'ed with the daemon.
- mPTTDirty = true;
+ mMuteMicDirty = true;
mSpeakerVolumeDirty = true;
mSpatialCoordsDirty = true;
@@ -1576,35 +1565,6 @@ void LLVivoxVoiceClient::stateMachine()
}
else
{
-
- // Figure out whether the PTT state needs to change
- {
- bool newPTT;
- if(mUsePTT)
- {
- // If configured to use PTT, track the user state.
- newPTT = mUserPTTState;
- }
- else
- {
- // If not configured to use PTT, it should always be true (otherwise the user will be unable to speak).
- newPTT = true;
- }
-
- if(mMuteMic)
- {
- // This always overrides any other PTT setting.
- newPTT = false;
- }
-
- // Dirty if state changed.
- if(newPTT != mPTT)
- {
- mPTT = newPTT;
- mPTTDirty = true;
- }
- }
-
if(!inSpatialChannel())
{
// When in a non-spatial channel, never send positional updates.
@@ -1626,7 +1586,7 @@ void LLVivoxVoiceClient::stateMachine()
// Send an update only if the ptt or mute state has changed (which shouldn't be able to happen that often
// -- the user can only click so fast) or every 10hz, whichever is sooner.
// Sending for every volume update causes an excessive flood of messages whenever a volume slider is dragged.
- if((mAudioSession && mAudioSession->mMuteDirty) || mPTTDirty || mUpdateTimer.hasExpired())
+ if((mAudioSession && mAudioSession->mMuteDirty) || mMuteMicDirty || mUpdateTimer.hasExpired())
{
mUpdateTimer.setTimerExpirySec(UPDATE_THROTTLE_SECONDS);
sendPositionalUpdate();
@@ -2749,19 +2709,17 @@ void LLVivoxVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
buildSetRenderDevice(stream);
- if(mPTTDirty)
+ if(mMuteMicDirty)
{
- mPTTDirty = false;
+ mMuteMicDirty = false;
// Send a local mute command.
- // NOTE that the state of "PTT" is the inverse of "local mute".
- // (i.e. when PTT is true, we send a mute command with "false", and vice versa)
- LL_DEBUGS("Voice") << "Sending MuteLocalMic command with parameter " << (mPTT?"false":"true") << LL_ENDL;
+ LL_DEBUGS("Voice") << "Sending MuteLocalMic command with parameter " << (mMuteMic?"true":"false") << LL_ENDL;
stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
- << "<Value>" << (mPTT?"false":"true") << "</Value>"
+ << "<Value>" << (mMuteMic?"true":"false") << "</Value>"
<< "</Request>\n\n\n";
}
@@ -5238,40 +5196,13 @@ void LLVivoxVoiceClient::leaveChannel(void)
void LLVivoxVoiceClient::setMuteMic(bool muted)
{
- mMuteMic = muted;
-}
-
-void LLVivoxVoiceClient::setUserPTTState(bool ptt)
-{
- mUserPTTState = ptt;
-}
-
-bool LLVivoxVoiceClient::getUserPTTState()
-{
- return mUserPTTState;
-}
-
-void LLVivoxVoiceClient::inputUserControlState(bool down)
-{
- if(mPTTIsToggle)
+ if(mMuteMic != muted)
{
- if(down) // toggle open-mic state on 'down'
- {
- toggleUserPTTState();
- }
- }
- else // set open-mic state as an absolute
- {
- setUserPTTState(down);
+ mMuteMic = muted;
+ mMuteMicDirty = true;
}
}
-
-void LLVivoxVoiceClient::toggleUserPTTState(void)
-{
- mUserPTTState = !mUserPTTState;
-}
-
void LLVivoxVoiceClient::setVoiceEnabled(bool enabled)
{
if (enabled != mVoiceEnabled)
@@ -5320,48 +5251,6 @@ BOOL LLVivoxVoiceClient::lipSyncEnabled()
}
}
-void LLVivoxVoiceClient::setUsePTT(bool usePTT)
-{
- if(usePTT && !mUsePTT)
- {
- // When the user turns on PTT, reset the current state.
- mUserPTTState = false;
- }
- mUsePTT = usePTT;
-}
-
-void LLVivoxVoiceClient::setPTTIsToggle(bool PTTIsToggle)
-{
- if(!PTTIsToggle && mPTTIsToggle)
- {
- // When the user turns off toggle, reset the current state.
- mUserPTTState = false;
- }
-
- mPTTIsToggle = PTTIsToggle;
-}
-
-bool LLVivoxVoiceClient::getPTTIsToggle()
-{
- return mPTTIsToggle;
-}
-
-void LLVivoxVoiceClient::setPTTKey(std::string &key)
-{
- if(key == "MiddleMouse")
- {
- mPTTIsMiddleMouse = true;
- }
- else
- {
- mPTTIsMiddleMouse = false;
- if(!LLKeyboard::keyFromString(key, &mPTTKey))
- {
- // If the call failed, don't match any key.
- key = KEY_NONE;
- }
- }
-}
void LLVivoxVoiceClient::setEarLocation(S32 loc)
{
@@ -5402,44 +5291,6 @@ void LLVivoxVoiceClient::setMicGain(F32 volume)
}
}
-void LLVivoxVoiceClient::keyDown(KEY key, MASK mask)
-{
- if (gKeyboard->getKeyRepeated(key))
- {
- // ignore auto-repeat keys
- return;
- }
-
- if(!mPTTIsMiddleMouse)
- {
- bool down = (mPTTKey != KEY_NONE)
- && gKeyboard->getKeyDown(mPTTKey);
- inputUserControlState(down);
- }
-
-
-}
-void LLVivoxVoiceClient::keyUp(KEY key, MASK mask)
-{
- if(!mPTTIsMiddleMouse)
- {
- bool down = (mPTTKey != KEY_NONE)
- && gKeyboard->getKeyDown(mPTTKey);
- inputUserControlState(down);
- }
-
-}
-void LLVivoxVoiceClient::middleMouseState(bool down)
-{
- if(mPTTIsMiddleMouse)
- {
- if(mPTTIsMiddleMouse)
- {
- inputUserControlState(down);
- }
- }
-}
-
/////////////////////////////
// Accessors for data related to nearby speakers
BOOL LLVivoxVoiceClient::getVoiceEnabled(const LLUUID& id)
@@ -7015,8 +6866,8 @@ void LLVivoxVoiceClient::captureBufferRecordStartSendMessage()
<< "<Value>false</Value>"
<< "</Request>\n\n\n";
- // Dirty the PTT state so that it will get reset when we finishing previewing
- mPTTDirty = true;
+ // Dirty the mute mic state so that it will get reset when we finishing previewing
+ mMuteMicDirty = true;
writeString(stream.str());
}
@@ -7030,7 +6881,7 @@ void LLVivoxVoiceClient::captureBufferRecordStopSendMessage()
LL_DEBUGS("Voice") << "Stopping audio capture to buffer." << LL_ENDL;
- // Mute the mic. PTT state was dirtied at recording start, so will be reset when finished previewing.
+ // Mute the mic. Mic mute state was dirtied at recording start, so will be reset when finished previewing.
stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Connector.MuteLocalMic.1\">"
<< "<ConnectorHandle>" << mConnectorHandle << "</ConnectorHandle>"
<< "<Value>true</Value>"
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 3ba517bf36..471545de56 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -173,25 +173,9 @@ public:
virtual void setVoiceEnabled(bool enabled);
virtual BOOL lipSyncEnabled();
virtual void setLipSyncEnabled(BOOL enabled);
- virtual void setMuteMic(bool muted); // Use this to mute the local mic (for when the client is minimized, etc), ignoring user PTT state.
+ virtual void setMuteMic(bool muted); // Set the mute state of the local mic.
//@}
-
- ////////////////////////
- /// @name PTT
- //@{
- virtual void setUserPTTState(bool ptt);
- virtual bool getUserPTTState();
- virtual void setUsePTT(bool usePTT);
- virtual void setPTTIsToggle(bool PTTIsToggle);
- virtual bool getPTTIsToggle();
- virtual void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs
- virtual void toggleUserPTTState(void);
-
- virtual void keyDown(KEY key, MASK mask);
- virtual void keyUp(KEY key, MASK mask);
- virtual void middleMouseState(bool down);
- //@}
-
+
//////////////////////////
/// @name nearby speaker accessors
//@{
@@ -534,9 +518,6 @@ protected:
// Use this to determine whether to show a "no speech" icon in the menu bar.
- // PTT
- void setPTTKey(std::string &key);
-
/////////////////////////////
// Recording controls
void recordingLoopStart(int seconds = 3600, int deltaFramesPerControlFrame = 200);
@@ -800,15 +781,8 @@ private:
LLVector3 mAvatarVelocity;
LLMatrix3 mAvatarRot;
- bool mPTTDirty;
- bool mPTT;
-
- bool mUsePTT;
- bool mPTTIsMiddleMouse;
- KEY mPTTKey;
- bool mPTTIsToggle;
- bool mUserPTTState;
bool mMuteMic;
+ bool mMuteMicDirty;
// Set to true when the friends list is known to have changed.
bool mFriendsListDirty;
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 7ae8c2c07d..80f43e51d2 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -77,9 +77,6 @@ static const LLVector2 TEX11 = LLVector2(1.f, 1.f);
LLUUID gSunTextureID = IMG_SUN;
LLUUID gMoonTextureID = IMG_MOON;
-//static
-LLColor3 LLHaze::sAirScaSeaLevel;
-
class LLFastLn
{
public:
@@ -182,6 +179,23 @@ inline void color_gamma_correct(LLColor3 &col)
}
}
+static LLColor3 calc_air_sca_sea_level()
+{
+ static LLColor3 WAVE_LEN(675, 520, 445);
+ static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
+ static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
+ static LLColor3 n4 = n21 * n21;
+ static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
+ static LLColor3 wl4 = wl2 * wl2;
+ static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
+ static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
+ return dens_div_N * color_div ( mult_const, wl4 );
+}
+
+// static constants.
+LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level();
+F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel);
+F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f;
/***************************************
@@ -394,12 +408,6 @@ LLVOSky::~LLVOSky()
mCubeMap = NULL;
}
-void LLVOSky::initClass()
-{
- LLHaze::initClass();
-}
-
-
void LLVOSky::init()
{
const F32 haze_int = color_intens(mHaze.calcSigSca(0));
@@ -2147,17 +2155,8 @@ void LLVOSky::updateFog(const F32 distance)
stop_glerror();
}
-// static
-void LLHaze::initClass()
-{
- sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel();
-}
-
-
// Functions used a lot.
-
-
F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
{
F32 mv = color_max(col);
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 6b3e7873a1..d3a42583ea 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -292,23 +292,6 @@ LL_FORCE_INLINE LLColor3 refr_ind_calc(const LLColor3 &wave_length)
}
-LL_FORCE_INLINE LLColor3 calc_air_sca_sea_level()
-{
- const static LLColor3 WAVE_LEN(675, 520, 445);
- const static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
- const static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
- const static LLColor3 n4 = n21 * n21;
- const static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
- const static LLColor3 wl4 = wl2 * wl2;
- const static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
- const static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
- return dens_div_N * color_div ( mult_const, wl4 );
-}
-
-const LLColor3 gAirScaSeaLevel = calc_air_sca_sea_level();
-const F32 AIR_SCA_INTENS = color_intens(gAirScaSeaLevel);
-const F32 AIR_SCA_AVG = AIR_SCA_INTENS / 3.f;
-
class LLHaze
{
public:
@@ -316,18 +299,15 @@ public:
LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2.f) :
mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0.f)
{
- mAbsCoef = color_intens(mSigSca) / AIR_SCA_INTENS;
+ mAbsCoef = color_intens(mSigSca) / sAirScaIntense;
}
LLHaze(const F32 g, const F32 sca, const F32 fo = 2.f) : mG(g),
mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo)
{
- mAbsCoef = 0.01f * sca / AIR_SCA_AVG;
+ mAbsCoef = 0.01f * sca / sAirScaAvg;
}
- static void initClass();
-
-
F32 getG() const { return mG; }
void setG(const F32 g)
@@ -343,12 +323,12 @@ public:
void setSigSca(const LLColor3& s)
{
mSigSca = s;
- mAbsCoef = 0.01f * color_intens(mSigSca) / AIR_SCA_INTENS;
+ mAbsCoef = 0.01f * color_intens(mSigSca) / sAirScaIntense;
}
void setSigSca(const F32 s0, const F32 s1, const F32 s2)
{
- mSigSca = AIR_SCA_AVG * LLColor3 (s0, s1, s2);
+ mSigSca = sAirScaAvg * LLColor3 (s0, s1, s2);
mAbsCoef = 0.01f * (s0 + s1 + s2) / 3;
}
@@ -392,10 +372,11 @@ public:
static inline LLColor3 calcAirSca(const F32 h);
static inline void calcAirSca(const F32 h, LLColor3 &result);
- static LLColor3 calcAirScaSeaLevel() { return gAirScaSeaLevel; }
- static const LLColor3 &getAirScaSeaLevel() { return sAirScaSeaLevel; }
-public:
- static LLColor3 sAirScaSeaLevel;
+
+private:
+ static LLColor3 const sAirScaSeaLevel;
+ static F32 const sAirScaIntense;
+ static F32 const sAirScaAvg;
protected:
F32 mG;
@@ -473,7 +454,6 @@ public:
LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
// Initialize/delete data that's only inited once per class.
- static void initClass();
void init();
void initCubeMap();
void initEmpty();
@@ -654,14 +634,12 @@ F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE);
inline LLColor3 LLHaze::calcAirSca(const F32 h)
{
- static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
- return calcFalloff(h) * air_sca_sea_level;
+ return calcFalloff(h) * sAirScaSeaLevel;
}
inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result)
{
- static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
- result = air_sca_sea_level;
+ result = sAirScaSeaLevel;
result *= calcFalloff(h);
}
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/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 761e12020b..a207d3e050 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -388,10 +388,12 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
// There's something bogus in the data that we're unpacking.
dp->dumpBufferToLog();
llwarns << "Flushing cache files" << llendl;
- std::string mask;
- mask = gDirUtilp->getDirDelimiter() + "*.slc";
- gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), mask);
-// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl;
+
+ if(LLVOCache::hasInstance() && getRegion())
+ {
+ LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ;
+ }
+
llwarns << "Bogus TE data in " << getID() << llendl;
}
else
@@ -667,11 +669,32 @@ void LLVOVolume::updateTextures()
}
}
+BOOL LLVOVolume::isVisible() const
+{
+ if(mDrawable.notNull() && mDrawable->isVisible())
+ {
+ return TRUE ;
+ }
+
+ if(isAttachment())
+ {
+ LLViewerObject* objp = (LLViewerObject*)getParent() ;
+ while(objp && !objp->isAvatar())
+ {
+ objp = (LLViewerObject*)objp->getParent() ;
+ }
+
+ return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ;
+ }
+
+ return FALSE ;
+}
+
void LLVOVolume::updateTextureVirtualSize()
{
// Update the pixel area of all faces
- if(mDrawable.isNull() || !mDrawable->isVisible())
+ if(!isVisible())
{
return ;
}
@@ -2142,7 +2165,7 @@ void LLVOVolume::removeMediaImpl(S32 texture_index)
}
//make the face referencing to mMediaImplList[texture_index] to point back to the old texture.
- if(mDrawable)
+ if(mDrawable && texture_index < mDrawable->getNumFaces())
{
LLFace* facep = mDrawable->getFace(texture_index) ;
if(facep)
@@ -2738,14 +2761,7 @@ void LLVOVolume::updateRadius()
BOOL LLVOVolume::isAttachment() const
{
- if (mState == 0)
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
+ return mState != 0 ;
}
BOOL LLVOVolume::isHUDAttachment() const
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 1e9b9737b1..8b68e7c78a 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -102,6 +102,7 @@ public:
void animateTextures();
/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+ BOOL isVisible() const ;
/*virtual*/ BOOL isActive() const;
/*virtual*/ BOOL isAttachment() const;
/*virtual*/ BOOL isRootEdit() const; // overridden for sake of attachments treating themselves as a root object
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/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index a49dc1b59d..92697fb2eb 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -287,6 +287,9 @@ BOOL LLPanelBodyPartsListItem::postBuild()
addWidgetToRightSide("btn_lock");
addWidgetToRightSide("btn_edit_panel");
+ setWidgetsVisible(false);
+ reshapeWidgets();
+
return TRUE;
}
@@ -443,6 +446,7 @@ clothing_to_string_map_t init_clothing_string_map()
w_map.insert(std::make_pair(LLWearableType::WT_SKIRT, "skirt_not_worn"));
w_map.insert(std::make_pair(LLWearableType::WT_ALPHA, "alpha_not_worn"));
w_map.insert(std::make_pair(LLWearableType::WT_TATTOO, "tattoo_not_worn"));
+ w_map.insert(std::make_pair(LLWearableType::WT_PHYSICS, "physics_not_worn"));
return w_map;
}
@@ -888,6 +892,7 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1);
setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1);
setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1);
+ setMenuItemEnabled(menu, "create_new", canAddWearables(ids));
setMenuItemVisible(menu, "show_original", !standalone);
setMenuItemEnabled(menu, "show_original", n_items == 1 && n_links == n_items);
setMenuItemVisible(menu, "take_off", mask == MASK_CLOTHING && n_worn == n_items);
@@ -1038,6 +1043,10 @@ bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_id
U32 n_clothes = m_it->second;
U32 wearable_count = gAgentWearables.getWearableCount(w_type);
+ if ((wearable_count > 0) && !LLWearableType::getAllowMultiwear(w_type))
+ {
+ return false;
+ }
if ((wearable_count + n_clothes) > LLAgentWearables::MAX_CLOTHING_PER_TYPE)
{
return false;
diff --git a/indra/newview/llwearabletype.cpp b/indra/newview/llwearabletype.cpp
index 0d707d65bf..f933be4d8f 100644
--- a/indra/newview/llwearabletype.cpp
+++ b/indra/newview/llwearabletype.cpp
@@ -34,25 +34,27 @@ struct WearableEntry : public LLDictionaryEntry
WearableEntry(const std::string &name,
const std::string& default_new_name,
LLAssetType::EType assetType,
- LLInventoryIcon::EIconName iconName);
+ LLInventoryIcon::EIconName iconName,
+ BOOL disable_camera_switch = FALSE,
+ BOOL allow_multiwear = TRUE) :
+ LLDictionaryEntry(name),
+ mAssetType(assetType),
+ mDefaultNewName(default_new_name),
+ mLabel(LLTrans::getString(name)),
+ mIconName(iconName),
+ mDisableCameraSwitch(disable_camera_switch),
+ mAllowMultiwear(allow_multiwear)
+ {
+
+ }
const LLAssetType::EType mAssetType;
const std::string mLabel;
const std::string mDefaultNewName; //keep mLabel for backward compatibility
LLInventoryIcon::EIconName mIconName;
+ BOOL mDisableCameraSwitch;
+ BOOL mAllowMultiwear;
};
-WearableEntry::WearableEntry(const std::string &name,
- const std::string& default_new_name,
- LLAssetType::EType assetType,
- LLInventoryIcon::EIconName iconName) :
- LLDictionaryEntry(name),
- mAssetType(assetType),
- mDefaultNewName(default_new_name),
- mLabel(LLTrans::getString(name)),
- mIconName(iconName)
-{
-}
-
class LLWearableDictionary : public LLSingleton<LLWearableDictionary>,
public LLDictionary<LLWearableType::EType, WearableEntry>
{
@@ -62,23 +64,26 @@ public:
LLWearableDictionary::LLWearableDictionary()
{
- addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE));
- addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN));
- addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR));
- addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES));
- addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT));
- addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS));
- addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES));
- addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS));
- addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET));
- addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES));
- addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT));
- addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS));
- addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT));
- addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA));
- addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO));
- addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_INVALID));
- addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_INVALID));
+ addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
+ addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
+ addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryIcon::ICONNAME_BODYPART_EYES, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
+ addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
+ addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
+
+ addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryIcon::ICONNAME_CLOTHING_PHYSICS, TRUE, FALSE));
+
+ addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryIcon::ICONNAME_NONE, FALSE, FALSE));
}
// static
@@ -134,3 +139,19 @@ LLInventoryIcon::EIconName LLWearableType::getIconName(LLWearableType::EType typ
return entry->mIconName;
}
+// static
+BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
+{
+ const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
+ const WearableEntry *entry = dict->lookup(type);
+ return entry->mDisableCameraSwitch;
+}
+
+// static
+BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
+{
+ const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
+ const WearableEntry *entry = dict->lookup(type);
+ return entry->mAllowMultiwear;
+}
+
diff --git a/indra/newview/llwearabletype.h b/indra/newview/llwearabletype.h
index 3bbf8ba0bd..d633b4807e 100644
--- a/indra/newview/llwearabletype.h
+++ b/indra/newview/llwearabletype.h
@@ -52,7 +52,8 @@ public:
WT_SKIRT = 12,
WT_ALPHA = 13,
WT_TATTOO = 14,
- WT_COUNT = 15,
+ WT_PHYSICS = 15,
+ WT_COUNT = 16,
WT_INVALID = 255,
WT_NONE = -1,
@@ -64,6 +65,8 @@ public:
static LLAssetType::EType getAssetType(EType type);
static EType typeNameToType(const std::string& type_name);
static LLInventoryIcon::EIconName getIconName(EType type);
+ static BOOL getDisableCameraSwitch(EType type);
+ static BOOL getAllowMultiwear(EType type);
protected:
LLWearableType() {}
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 73a37a6993..b73017a51a 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -35,6 +35,7 @@
#include "llagent.h"
#include "llappviewer.h"
#include "llfloatermediabrowser.h"
+#include "llfloaterwebcontent.h"
#include "llfloaterreg.h"
#include "lllogininstance.h"
#include "llparcel.h"
@@ -95,6 +96,23 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std
}
}
+// static
+void LLWeb::loadWebURL(const std::string& url, const std::string& target, const std::string& uuid)
+{
+ if(target == "_internal")
+ {
+ // Force load in the internal browser, as if with a blank target.
+ loadWebURLInternal(url, "", uuid);
+ }
+ else if (gSavedSettings.getBOOL("UseExternalBrowser") || (target == "_external"))
+ {
+ loadURLExternal(url);
+ }
+ else
+ {
+ loadWebURLInternal(url, target, uuid);
+ }
+}
// static
void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
@@ -102,6 +120,13 @@ void LLWeb::loadURLInternal(const std::string &url, const std::string& target, c
LLFloaterMediaBrowser::create(url, target, uuid);
}
+// static
+// Explicitly open a Web URL using the Web content floater
+void LLWeb::loadWebURLInternal(const std::string &url, const std::string& target, const std::string& uuid)
+{
+ LLFloaterWebContent::create(url, target, uuid);
+}
+
// static
void LLWeb::loadURLExternal(const std::string& url, const std::string& uuid)
@@ -116,6 +141,13 @@ void LLWeb::loadURLExternal(const std::string& url, bool async, const std::strin
// Act like the proxy window was closed, since we won't be able to track targeted windows in the external browser.
LLViewerMedia::proxyWindowClosed(uuid);
+ if(gSavedSettings.getBOOL("DisableExternalBrowser"))
+ {
+ // Don't open an external browser under any circumstances.
+ llwarns << "Blocked attempt to open external browser." << llendl;
+ return;
+ }
+
LLSD payload;
payload["url"] = url;
LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, boost::bind(on_load_url_external_response, _1, _2, async));
diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h
index 2915376583..dc5958e57f 100644
--- a/indra/newview/llweb.h
+++ b/indra/newview/llweb.h
@@ -57,6 +57,11 @@ public:
static void loadURLExternal(const std::string& url, const std::string& uuid);
static void loadURLExternal(const std::string& url, bool async, const std::string& uuid = LLStringUtil::null);
+ // Explicitly open a Web URL using the Web content floater vs. the more general media browser
+ static void loadWebURL(const std::string& url, const std::string& target, const std::string& uuid);
+ static void loadWebURLInternal(const std::string &url, const std::string& target, const std::string& uuid);
+ static void loadWebURLInternal(const std::string &url) { loadWebURLInternal(url, LLStringUtil::null, LLStringUtil::null); }
+
/// Returns escaped url (eg, " " to "%20") - used by all loadURL methods
static std::string escapeURL(const std::string& url);
/// Expands various strings like [LANG], [VERSION], etc. in a URL
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..8f7197c607 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();
}
@@ -273,6 +281,10 @@ void LLWorld::removeRegion(const LLHost &host)
delete regionp;
updateWaterObjects();
+
+ //double check all objects of this region are removed.
+ gObjectList.clearAllMapObjectsInRegion(regionp) ;
+ //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
}
@@ -423,14 +435,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 +847,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 +922,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);
@@ -1267,6 +1476,42 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi
}
}
}
+ // retrieve the list of close avatars from viewer objects as well
+ // for when we are above 1000m, only do this when we are retrieving
+ // uuid's too as there could be duplicates
+ if(avatar_ids != NULL)
+ {
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
+ {
+ LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter;
+ if(pVOAvatar->isDead() || pVOAvatar->isSelf())
+ continue;
+ LLUUID uuid = pVOAvatar->getID();
+ if(uuid.isNull())
+ continue;
+ LLVector3d pos_global = pVOAvatar->getPositionGlobal();
+ if(dist_vec(pos_global, relative_to) <= radius)
+ {
+ bool found = false;
+ uuid_vec_t::iterator sel_iter = avatar_ids->begin();
+ for (; sel_iter != avatar_ids->end(); sel_iter++)
+ {
+ if(*sel_iter == uuid)
+ {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ if(positions != NULL)
+ positions->push_back(pos_global);
+ avatar_ids->push_back(uuid);
+ }
+ }
+ }
+ }
}
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/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
index be8298daab..74ed844376 100644
--- a/indra/newview/llworldmipmap.cpp
+++ b/indra/newview/llworldmipmap.cpp
@@ -181,8 +181,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32
LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)
{
// Get the grid coordinates
- std::string imageurl = gSavedSettings.getString("MapServerURL") + llformat("map-%d-%d-%d-objects.jpg", level, grid_x, grid_y);
-
+ std::string imageurl = gSavedSettings.getString("CurrentMapServerURL") + llformat("map-%d-%d-%d-objects.jpg", level, grid_x, grid_y);
// DO NOT COMMIT!! DEBUG ONLY!!!
// Use a local jpeg for every tile to test map speed without S3 access
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 03e6e65788..58dc90ccd9 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;
@@ -255,6 +253,7 @@ S32 LLPipeline::sCompiles = 0;
BOOL LLPipeline::sPickAvatar = TRUE;
BOOL LLPipeline::sDynamicLOD = TRUE;
BOOL LLPipeline::sShowHUDAttachments = TRUE;
+BOOL LLPipeline::sRenderMOAPBeacons = FALSE;
BOOL LLPipeline::sRenderPhysicalBeacons = TRUE;
BOOL LLPipeline::sRenderScriptedBeacons = FALSE;
BOOL LLPipeline::sRenderScriptedTouchBeacons = TRUE;
@@ -629,14 +628,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 +1637,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) &&
@@ -1975,12 +1968,12 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
if(drawablep && !drawablep->isDead())
{
- if (drawablep->isSpatialBridge())
- {
+ if (drawablep->isSpatialBridge())
+ {
const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
llassert(root); // trying to catch a bad assumption
if (root && // // this test may not be needed, see above
- root->getVObj()->isAttachment())
+ root->getVObj()->isAttachment())
{
LLDrawable* rootparent = root->getParent();
if (rootparent) // this IS sometimes NULL
@@ -1988,24 +1981,24 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
LLViewerObject *vobj = rootparent->getVObj();
llassert(vobj); // trying to catch a bad assumption
if (vobj) // this test may not be needed, see above
- {
+ {
const LLVOAvatar* av = vobj->asAvatar();
- if (av && av->isImpostor())
- {
- return;
- }
- }
+ if (av && av->isImpostor())
+ {
+ return;
+ }
+ }
}
}
- sCull->pushBridge((LLSpatialBridge*) drawablep);
- }
- else
- {
- sCull->pushDrawable(drawablep);
- }
+ sCull->pushBridge((LLSpatialBridge*) drawablep);
+ }
+ else
+ {
+ sCull->pushDrawable(drawablep);
+ }
- drawablep->setVisible(camera);
-}
+ drawablep->setVisible(camera);
+ }
}
void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
@@ -2221,6 +2214,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))
{
@@ -2517,6 +2511,42 @@ void renderPhysicalBeacons(LLDrawable* drawablep)
}
}
+void renderMOAPBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+
+ if(!vobj || vobj->isAvatar())
+ return;
+
+ BOOL beacon=FALSE;
+ U8 tecount=vobj->getNumTEs();
+ for(int x=0;x<tecount;x++)
+ {
+ if(vobj->getTE(x)->hasMedia())
+ {
+ beacon=TRUE;
+ break;
+ }
+ }
+ if(beacon==TRUE)
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
+ }
+
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
void renderParticleBeacons(LLDrawable* drawablep)
{
// Look for attachments, objects, etc.
@@ -2722,6 +2752,11 @@ void LLPipeline::postSort(LLCamera& camera)
forAllVisibleDrawables(renderPhysicalBeacons);
}
+ if(sRenderMOAPBeacons)
+ {
+ forAllVisibleDrawables(renderMOAPBeacons);
+ }
+
if (sRenderParticleBeacons)
{
forAllVisibleDrawables(renderParticleBeacons);
@@ -3812,185 +3847,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 +4868,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
@@ -5120,6 +4980,24 @@ BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
}
// static
+void LLPipeline::setRenderMOAPBeacons(BOOL val)
+{
+ sRenderMOAPBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderMOAPBeacons(void*)
+{
+ sRenderMOAPBeacons = !sRenderMOAPBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderMOAPBeacons(void*)
+{
+ return sRenderMOAPBeacons;
+}
+
+// static
void LLPipeline::setRenderPhysicalBeacons(BOOL val)
{
sRenderPhysicalBeacons = val;
@@ -5495,7 +5373,25 @@ void LLPipeline::setUseVBO(BOOL use_vbo)
}
resetVertexBuffers();
- LLVertexBuffer::initClass(use_vbo);
+ LLVertexBuffer::initClass(use_vbo, gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+ }
+}
+
+void LLPipeline::setDisableVBOMapping(BOOL no_vbo_mapping)
+{
+ if (LLVertexBuffer::sEnableVBOs && no_vbo_mapping != LLVertexBuffer::sDisableVBOMapping)
+ {
+ if (no_vbo_mapping)
+ {
+ llinfos << "Disabling VBO glMapBufferARB." << llendl;
+ }
+ else
+ {
+ llinfos << "Enabling VBO glMapBufferARB." << llendl;
+ }
+
+ resetVertexBuffers();
+ LLVertexBuffer::initClass(true, no_vbo_mapping);
}
}
@@ -5614,7 +5510,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.setColorMask(true, true);
glClearColor(0,0,0,0);
- if (for_snapshot)
+ /*if (for_snapshot)
{
gGL.getTexUnit(0)->bind(&mGlow[1]);
{
@@ -5625,14 +5521,21 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
// If the snapshot is constructed from tiles, calculate which
// tile we're in.
- const S32 num_horizontal_tiles = llceil(zoom_factor);
- const LLVector2 tile(subfield % num_horizontal_tiles,
- (S32)(subfield / num_horizontal_tiles));
- llassert(zoom_factor > 0.0); // Non-zero, non-negative.
- const F32 tile_size = 1.0/zoom_factor;
-
- tc1 = tile*tile_size; // Top left texture coordinates
- tc2 = (tile+LLVector2(1,1))*tile_size; // Bottom right texture coordinates
+
+ //from LLViewerCamera::setPerpsective
+ if (zoom_factor > 1.f)
+ {
+ int pos_y = subfield / llceil(zoom_factor);
+ int pos_x = subfield - (pos_y*llceil(zoom_factor));
+ F32 size = 1.f/zoom_factor;
+
+ tc1.set(pos_x*size, pos_y*size);
+ tc2 = tc1 + LLVector2(size,size);
+ }
+ else
+ {
+ tc2.set(1,1);
+ }
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_ADD);
@@ -5665,7 +5568,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
glPopMatrix();
return;
- }
+ }*/
{
{
@@ -7008,7 +6911,6 @@ void LLPipeline::renderDeferredLighting()
{
// Render debugging beacons.
gObjectList.renderObjectBeacons();
- LLHUDObject::renderAll();
gObjectList.resetObjectBeacons();
}
}
@@ -7339,6 +7241,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 +7294,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 +7811,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 +7995,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..92ae40ebb0 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -111,6 +111,7 @@ public:
void resetVertexBuffers(LLDrawable* drawable);
void setUseVBO(BOOL use_vbo);
+ void setDisableVBOMapping(BOOL no_vbo_mapping);
void generateImpostor(LLVOAvatar* avatar);
void bindScreenToTexture();
void renderBloom(BOOL for_snapshot, F32 zoom_factor = 1.f, int subfield = 0);
@@ -245,7 +246,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
@@ -312,6 +312,10 @@ public:
static void toggleRenderSoundBeacons(void* data);
static BOOL getRenderSoundBeacons(void* data);
+ static void setRenderMOAPBeacons(BOOL val);
+ static void toggleRenderMOAPBeacons(void * data);
+ static BOOL getRenderMOAPBeacons(void * data);
+
static void setRenderPhysicalBeacons(BOOL val);
static void toggleRenderPhysicalBeacons(void* data);
static BOOL getRenderPhysicalBeacons(void* data);
@@ -359,6 +363,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,
@@ -424,6 +429,7 @@ public:
RENDER_DEBUG_AVATAR_VOLUME = 0x0100000,
RENDER_DEBUG_BUILD_QUEUE = 0x0200000,
RENDER_DEBUG_AGENT_TARGET = 0x0400000,
+ RENDER_DEBUG_UPDATE_TYPE = 0x0800000,
};
public:
@@ -696,6 +702,7 @@ protected:
S32 mLightingDetail;
static BOOL sRenderPhysicalBeacons;
+ static BOOL sRenderMOAPBeacons;
static BOOL sRenderScriptedTouchBeacons;
static BOOL sRenderScriptedBeacons;
static BOOL sRenderParticleBeacons;
@@ -712,7 +719,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/res/toolbuy.cur b/indra/newview/res/toolbuy.cur
index a1bc278116..65bbf01d45 100644
--- a/indra/newview/res/toolbuy.cur
+++ b/indra/newview/res/toolbuy.cur
Binary files differ
diff --git a/indra/newview/res/toolopen.cur b/indra/newview/res/toolopen.cur
index a72cdfe4c0..22ecbd5228 100644
--- a/indra/newview/res/toolopen.cur
+++ b/indra/newview/res/toolopen.cur
Binary files differ
diff --git a/indra/newview/res/toolsit.cur b/indra/newview/res/toolsit.cur
index 6327bdb281..d26b6f8638 100644
--- a/indra/newview/res/toolsit.cur
+++ b/indra/newview/res/toolsit.cur
Binary files differ
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index ddd2ff196b..75aec21f93 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -115,9 +115,6 @@
name="AlertCautionTextColor"
reference="LtYellow" />
<color
- name="AgentLinkColor"
- reference="EmphasisColor" />
- <color
name="AlertTextColor"
value="0.58 0.66 0.84 1" />
<color
@@ -139,9 +136,6 @@
name="AvatarListItemIconVoiceLeftColor"
reference="AvatarListItemIconOfflineColor" />
<color
- name="BackgroundChatColor"
- reference="DkGray_66" />
- <color
name="ButtonBorderColor"
reference="Unused?" />
<color
@@ -352,9 +346,6 @@
name="GridlineShadowColor"
value="0 0 0 0.31" />
<color
- name="GroupLinkColor"
- reference="White" />
- <color
name="GroupNotifyBoxColor"
value="0.3344 0.5456 0.5159 1" />
<color
@@ -400,9 +391,6 @@
name="HighlightParentColor"
value="0.67 0.83 0.96 1" />
<color
- name="IMChatColor"
- reference="LtGray" />
- <color
name="IMHistoryBgColor"
reference="Unused?" />
<color
@@ -767,9 +755,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/textures/arrow_keys.png b/indra/newview/skins/default/textures/arrow_keys.png
new file mode 100644
index 0000000000..f19af59251
--- /dev/null
+++ b/indra/newview/skins/default/textures/arrow_keys.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/bottomtray/ChatBarHandle.png b/indra/newview/skins/default/textures/bottomtray/ChatBarHandle.png
new file mode 100644
index 0000000000..8b58db0cba
--- /dev/null
+++ b/indra/newview/skins/default/textures/bottomtray/ChatBarHandle.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_Physics.png b/indra/newview/skins/default/textures/icons/Inv_Physics.png
new file mode 100644
index 0000000000..ddd36b446b
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Physics.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Web_Profile_Off.png b/indra/newview/skins/default/textures/icons/Web_Profile_Off.png
new file mode 100644
index 0000000000..f5fb774a6f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Web_Profile_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b2658d2525..1ca48b01a8 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -107,6 +107,7 @@ with the same filename but different name
<texture name="ComboButton_Selected" file_name="widgets/ComboButton_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="ComboButton_UpSelected" file_name="widgets/ComboButton_UpSelected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="ComboButton_Up_On_Selected" file_name="widgets/ComboButton_Up_On_Selected.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
+ <texture name="ComboButton_On" file_name="widgets/ComboButton_On.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="ComboButton_Off" file_name="widgets/ComboButton_Off.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="ComboButton_UpOff" file_name="widgets/ComboButton_UpOff.png" preload="true" scale.left="2" scale.top="19" scale.right="18" scale.bottom="2" />
<texture name="Container" file_name="containers/Container.png" preload="false" />
@@ -114,6 +115,7 @@ with the same filename but different name
<texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" />
+ <texture name="ChatBarHandle" file_name="bottomtray/ChatBarHandle.png" preload="false" />
<texture name="DownArrow" file_name="bottomtray/DownArrow.png" preload="false" />
<texture name="DownArrow_Off" file_name="icons/DownArrow_Off.png" preload="false" />
<texture name="Dragbar" file_name="windows/Dragbar.png" preload="false" scale.left="35" scale.top="5" scale.right="29" scale.bottom="5" />
@@ -224,6 +226,7 @@ with the same filename but different name
<texture name="Inv_SysClosed" file_name="icons/Inv_SysClosed.png" preload="false" />
<texture name="Inv_SysOpen" file_name="icons/Inv_SysOpen.png" preload="false" />
<texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" />
+ <texture name="Inv_Physics" file_name="icons/Inv_Physics.png" preload="false" />
<texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" />
<texture name="Inv_TrashClosed" file_name="icons/Inv_TrashClosed.png" preload="false" />
<texture name="Inv_TrashOpen" file_name="icons/Inv_TrashOpen.png" preload="false" />
@@ -371,8 +374,8 @@ with the same filename but different name
<texture name="Play_Off" file_name="icons/Play_Off.png" preload="false" />
<texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" />
<texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" />
-
- <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="10" scale.right="48" scale.bottom="2" />
+
+ <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
<texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" />
<texture name="PushButton_Disabled" file_name="widgets/PushButton_Disabled.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
@@ -392,7 +395,7 @@ with the same filename but different name
<texture name="RadioButton_On_Disabled" file_name="widgets/RadioButton_On_Disabled.png" preload="true" />
- <texture name="Refresh_Off" file_name="icons/Refresh_Off.png" preload="false" />
+ <texture name="Refresh_Off" file_name="icons/Refresh_Off.png" preload="true" />
<texture name="Resize_Corner" file_name="windows/Resize_Corner.png" preload="true" />
@@ -468,7 +471,7 @@ with the same filename but different name
<texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="false" />
<texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="false" />
- <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="false" />
+ <texture name="Stop_Off" file_name="icons/Stop_Off.png" preload="true" />
<texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
<texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
@@ -553,11 +556,11 @@ with the same filename but different name
<texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" />
+ <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" />
+
<texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
<texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" />
-
-
<texture name="Window_Background" file_name="windows/Window_Background.png" preload="true"
scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" />
<texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true"
@@ -671,4 +674,5 @@ with the same filename but different name
<texture name="Yellow_Gradient" file_name="windows/yellow_gradient.png"/>
<texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>
+ <texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
</textures>
diff --git a/indra/newview/skins/default/textures/widgets/ProgressBar.png b/indra/newview/skins/default/textures/widgets/ProgressBar.png
index edf11ac1f5..3f0e4eba28 100644
--- a/indra/newview/skins/default/textures/widgets/ProgressBar.png
+++ b/indra/newview/skins/default/textures/widgets/ProgressBar.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/world/CameraDragDot.png b/indra/newview/skins/default/textures/world/CameraDragDot.png
new file mode 100644
index 0000000000..57698e1956
--- /dev/null
+++ b/indra/newview/skins/default/textures/world/CameraDragDot.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_self.xml b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
index d727294cc8..d9bdfece38 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_self.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_self.xml
@@ -152,6 +152,18 @@
</menu_item_call>
<menu_item_call
enabled="false"
+ label="Physics"
+ layout="topleft"
+ name="Self Physics">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="physics" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="physics" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
label="Alpha"
layout="topleft"
name="Self Alpha">
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index c0046d8e28..e91f4458ae 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -200,6 +200,14 @@
function="Inventory.DoCreate"
parameter="tattoo" />
</menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="physics" />
+ </menu_item_call>
</menu>
<menu
label="New Body Parts"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index ae98abf4fb..90e8db3709 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -188,6 +188,14 @@
function="Inventory.DoCreate"
parameter="tattoo" />
</menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="physics" />
+ </menu_item_call>
</menu>
<menu
height="85"
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 5fc25b8f0f..fc7272b904 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -133,6 +133,14 @@
parameter="alpha" />
</menu_item_call>
<menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Gear.Create"
+ parameter="physics" />
+ </menu_item_call>
+ <menu_item_call
label="New Tattoo"
layout="topleft"
name="New Tattoo">
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 934cae93db..51610c0ae0 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3429,6 +3429,16 @@
parameter="tattoo" />
</menu_item_call>
<menu_item_call
+ label="Physics"
+ name="Physics">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="physics" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="physics" />
+ </menu_item_call>
+ <menu_item_call
label="All Clothes"
name="All Clothes">
<menu_item_call.on_click
diff --git a/indra/newview/skins/default/xui/en/panel_edit_physics.xml b/indra/newview/skins/default/xui/en/panel_edit_physics.xml
new file mode 100644
index 0000000000..c6f974f4f1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_physics.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ <panel
+ background_visible="true"
+ follows="all"
+ height="400"
+ layout="topleft"
+ left="0"
+ name="edit_physics_panel"
+ top_pad="10"
+ width="333" >
+ <panel
+ border="false"
+ bg_alpha_color="DkGray2"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ follows="all"
+ height="388"
+ label=""
+ layout="topleft"
+ left="10"
+ name="accordion_panel"
+ top_pad="0"
+ width="313">
+ <accordion
+ follows="all"
+ height ="388"
+ layout="topleft"
+ left="0"
+ single_expansion="true"
+ fit_parent="true"
+ name="physics_accordion"
+ top="0"
+ width="313">
+ <accordion_tab
+ layout="topleft"
+ fit_panel="false"
+ min_height="50"
+ name="physics_breasts_updown_tab"
+ title="Breasts Bounce">
+ <scrolling_panel_list
+ follows="all"
+ layout="topleft"
+ left="10"
+ name="physics_breasts_updown_param_list"
+ top="10"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ fit_panel="false"
+ min_height="50"
+ name="physics_breasts_inout_tab"
+ title="Breasts Cleavage">
+ <scrolling_panel_list
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="physics_breasts_inout_param_list"
+ top_pad="50"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ fit_panel="false"
+ min_height="50"
+ name="physics_belly_tab"
+ title="Belly Bounce">
+ <scrolling_panel_list
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="physics_belly_updown_param_list"
+ top_pad="40"
+ width="303" />
+ </accordion_tab>
+
+ <accordion_tab
+ layout="topleft"
+ fit_panel="false"
+ min_height="50"
+ name="physics_butt_tab"
+ title="Butt Bounce">
+ <scrolling_panel_list
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="physics_butt_updown_param_list"
+ top_pad="30"
+ width="303" />
+ </accordion_tab>
+
+ <accordion_tab
+ layout="topleft"
+ fit_panel="false"
+ min_height="50"
+ name="physics_butt_leftright_tab"
+ title="Butt Sway">
+ <scrolling_panel_list
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="physics_butt_leftright_param_list"
+ top_pad="20"
+ width="303" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ fit_panel="false"
+ min_height="50"
+ name="physics_advanced_tab"
+ title="Advanced Parameters">
+ <scrolling_panel_list
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="physics_advanced_param_list"
+ top_pad="10"
+ width="303" />
+ </accordion_tab>
+ </accordion>
+ </panel>
+</panel>
+
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 ac8917d272..c8764a6a84 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -72,6 +72,10 @@
Editing Tattoo
</string>
<string
+ name="edit_physics_title">
+ Editing Physics
+ </string>
+ <string
name="shape_desc_text">
Shape:
</string>
@@ -131,6 +135,10 @@
name="tattoo_desc_text">
Tattoo:
</string>
+ <string
+ name="physics_desc_text">
+ Physics:
+ </string>
<!-- Default width of the button should be to show it without label.
Button will be extedned in code to show whole label when wearable is being changed.
-->
@@ -410,6 +418,16 @@
top="8"
visible="false"
width="333" />
+ <panel
+ filename="panel_edit_physics.xml"
+ follows="all"
+ height="425"
+ layout="topleft"
+ left="0"
+ name="edit_physics_panel"
+ top="8"
+ visible="false"
+ width="333" />
</panel>
<panel
follows="bottom|left|right"
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 6573822d1a..d74197d965 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -2,7 +2,7 @@
<panel
border="true"
follows="left|top|right|bottom"
- height="408"
+ height="418"
label="Graphics"
layout="topleft"
left="102"
@@ -327,6 +327,37 @@
value="4"/>
</combo_box>
+ <slider
+ control_name="RenderAvatarPhysicsLODFactor"
+ follows="left|top"
+ height="16"
+ initial_value="100"
+ increment=".05"
+ label=" Avatar Physics:"
+ label_width="85"
+ layout="topleft"
+ left_delta="-16"
+ name="AvatarPhysicsDetail"
+ show_text="false"
+ top_pad="12"
+ width="160">
+ <slider.commit_callback
+ function="Pref.UpdateSliderText"
+ parameter="AvatarPhysicsDetailText" />
+ </slider>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left_delta="165"
+ name="AvatarPhysicsDetailText"
+ top_pad="-16"
+ width="128">
+ Low
+ </text>
+
<slider
control_name="RenderFarClip"
decimal_digits="0"
@@ -618,6 +649,7 @@
width="128">
Low
</text>
+
<text
type="string"
length="1"
@@ -628,7 +660,7 @@
name="AvatarRenderingText"
top_pad="18"
width="128">
- Avatar rendering:
+ Avatar Rendering:
</text>
<check_box
control_name="RenderUseImpostors"
@@ -672,7 +704,7 @@
left="358"
left_pad="-30"
name="TerrainDetailText"
- top="226"
+ top="250"
width="155">
Terrain detail:
</text>
@@ -710,7 +742,7 @@
layout="topleft"
left="10"
name="Apply"
- top="383"
+ top="390"
width="115">
<button.commit_callback
function="Pref.Apply" />
@@ -722,7 +754,7 @@
layout="topleft"
left_pad="3"
name="Defaults"
- top="383"
+ top="390"
width="115">
<button.commit_callback
function="Pref.HardwareDefaults" />
diff --git a/indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml b/indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml
new file mode 100644
index 0000000000..1351f75623
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_scrolling_param_base.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ layout="topleft"
+ left="0"
+ name="LLScrollingPanelParamBase"
+ height="16"
+ width="290">
+ <slider
+ can_edit_text="true"
+ decimal_digits="0"
+ enabled="false"
+ height="12"
+ increment="1"
+ initial_value="0"
+ label="[DESC]"
+ label_width="125"
+ layout="bottom|left"
+ left="16"
+ max_val="100"
+ name="param slider"
+ bottom="0"
+ width="264"
+ />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 14ea43a8f8..ed7814e0f0 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -1853,6 +1853,7 @@ Requests name of an avatar. When data is available the dataserver event will be
<string name="skirt">Skirt</string>
<string name="alpha">Alpha</string>
<string name="tattoo">Tattoo</string>
+ <string name="physics">Physics</string>
<string name="invalid">invalid</string>
<string name="none">none</string>
@@ -1868,6 +1869,7 @@ Requests name of an avatar. When data is available the dataserver event will be
<string name="skirt_not_worn">Skirt not worn</string>
<string name="alpha_not_worn">Alpha not worn</string>
<string name="tattoo_not_worn">Tattoo not worn</string>
+ <string name="physics_not_worn">Physics not worn</string>
<string name="invalid_not_worn">invalid</string>
<!-- Create new wearable of the specified type -->
@@ -1886,6 +1888,7 @@ Requests name of an avatar. When data is available the dataserver event will be
<string name="create_new_skirt">Create new skirt</string>
<string name="create_new_alpha">Create new alpha</string>
<string name="create_new_tattoo">Create new tattoo</string>
+ <string name="create_new_physics">Create new physics</string>
<string name="create_new_invalid">invalid</string>
<!-- Wearable List-->
@@ -2497,8 +2500,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Body Thin">Body Thin</string>
<string name="Bow Legged">Bow Legged</string>
-<string name="Breast Buoyancy">Breast Buoyancy</string>
-<string name="Breast Cleavage">Breast Cleavage</string>
+<string name="Breast Physics UpDown Controller">Breast Buoyancy</string>
+<string name="Breast Physics InOut Controller">Breast Cleavage</string>
<string name="Breast Size">Breast Size</string>
<string name="Bridge Width">Bridge Width</string>
<string name="Broad">Broad</string>
@@ -2508,10 +2511,52 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Bulbous">Bulbous</string>
<string name="Bulbous Nose">Bulbous Nose</string>
+<string name="Breast Physics Mass">Breast Mass</string>
+<string name="Breast Physics Smoothing">Breast Smoothing</string>
+<string name="Breast Physics Gravity">Breast Gravity</string>
+
+<string name="Breast Physics InOut Max Speed">Max Effect</string>
+<string name="Breast Physics InOut Spring">Spring</string>
+<string name="Breast Physics InOut Gain">Gain</string>
+<string name="Breast Physics InOut Damping">Damping</string>
+<string name="Breast Physics InOut Drag">Breast Cleavage Drag</string>
+
+<string name="Breast Physics UpDown Max Speed">Max Effect</string>
+<string name="Breast Physics UpDown Spring">Spring</string>
+<string name="Breast Physics UpDown Gain">Gain</string>
+<string name="Breast Physics UpDown Damping">Damping</string>
+<string name="Breast Physics UpDown Drag">Breast Bounce Drag</string>
+
+<string name="Belly Physics Mass">Belly Mass</string>
+<string name="Belly Physics Smoothing">Belly Smoothing</string>
+<string name="Belly Physics Gravity">Belly Gravity</string>
+
+<string name="Belly Physics UpDown Max Speed">Max Effect</string>
+<string name="Belly Physics UpDown Spring">Spring</string>
+<string name="Belly Physics UpDown Gain">Gain</string>
+<string name="Belly Physics UpDown Damping">Damping</string>
+<string name="Belly Physics UpDown Drag">Belly Bounce Drag</string>
+
+<string name="Butt Physics Mass">Butt Mass</string>
+<string name="Butt Physics Smoothing">Butt Smoothing</string>
+<string name="Butt Physics Gravity">Butt Gravity</string>
+
+<string name="Butt Physics UpDown Max Speed">Max Effect</string>
+<string name="Butt Physics UpDown Spring">Spring</string>
+<string name="Butt Physics UpDown Gain">Gain</string>
+<string name="Butt Physics UpDown Damping">Damping</string>
+<string name="Butt Physics UpDown Drag">Butt Bounce Drag</string>
+
+<string name="Butt Physics LeftRight Max Speed">Max Effect</string>
+<string name="Butt Physics LeftRight Spring">Spring</string>
+<string name="Butt Physics LeftRight Gain">Gain</string>
+<string name="Butt Physics LeftRight Damping">Damping</string>
+<string name="Butt Physics LeftRight Drag">Butt Sway Drag</string>
<string name="Bushy Eyebrows">Bushy Eyebrows</string>
<string name="Bushy Hair">Bushy Hair</string>
<string name="Butt Size">Butt Size</string>
+<string name="Butt Gravity">Butt Gravity</string>
<string name="bustle skirt">Bustle Skirt</string>
<string name="no bustle">No Bustle</string>
<string name="more bustle">More Bustle</string>
@@ -3215,6 +3260,7 @@ Abuse Report</string>
<string name="New Skirt">New Skirt</string>
<string name="New Alpha">New Alpha</string>
<string name="New Tattoo">New Tattoo</string>
+ <string name="New Physics">New Physics</string>
<string name="Invalid Wearable">Invalid Wearable</string>
<string name="New Gesture">New Gesture</string>
<string name="New Script">New Script</string>
diff --git a/indra/newview/skins/minimal/colors.xml b/indra/newview/skins/minimal/colors.xml
new file mode 100644
index 0000000000..097a298ce5
--- /dev/null
+++ b/indra/newview/skins/minimal/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<colors>
+ <color
+ name="MenuBarBgColor"
+ value="0 0 0 0" />
+</colors>
diff --git a/indra/newview/skins/minimal/textures/arrow_keys.png b/indra/newview/skins/minimal/textures/arrow_keys.png
new file mode 100644
index 0000000000..f19af59251
--- /dev/null
+++ b/indra/newview/skins/minimal/textures/arrow_keys.png
Binary files differ
diff --git a/indra/newview/skins/minimal/textures/bottomtray/button_separator.png b/indra/newview/skins/minimal/textures/bottomtray/button_separator.png
new file mode 100644
index 0000000000..71ed25f931
--- /dev/null
+++ b/indra/newview/skins/minimal/textures/bottomtray/button_separator.png
Binary files differ
diff --git a/indra/newview/skins/minimal/textures/bottomtray/close_off.png b/indra/newview/skins/minimal/textures/bottomtray/close_off.png
new file mode 100644
index 0000000000..241a24bde9
--- /dev/null
+++ b/indra/newview/skins/minimal/textures/bottomtray/close_off.png
Binary files differ
diff --git a/indra/newview/skins/minimal/textures/bottomtray/close_over.png b/indra/newview/skins/minimal/textures/bottomtray/close_over.png
new file mode 100644
index 0000000000..4630cb6dd6
--- /dev/null
+++ b/indra/newview/skins/minimal/textures/bottomtray/close_over.png
Binary files differ
diff --git a/indra/newview/skins/minimal/textures/bottomtray/close_press.png b/indra/newview/skins/minimal/textures/bottomtray/close_press.png
new file mode 100644
index 0000000000..3ed9c99a26
--- /dev/null
+++ b/indra/newview/skins/minimal/textures/bottomtray/close_press.png
Binary files differ
diff --git a/indra/newview/skins/minimal/textures/textures.xml b/indra/newview/skins/minimal/textures/textures.xml
new file mode 100644
index 0000000000..3e2f5cd397
--- /dev/null
+++ b/indra/newview/skins/minimal/textures/textures.xml
@@ -0,0 +1,8 @@
+
+<textures version="101">
+ <texture name="Button_Separator" file_name="bottomtray/button_separator.png" preload="true" />
+ <texture name="arrow_keys.png"/>
+ <texture name="bottomtray_close_off" file_name="bottomtray/close_off.png" preload="true" />
+ <texture name="bottomtray_close_over" file_name="bottomtray/close_over.png" preload="true" />
+ <texture name="bottomtray_close_press" file_name="bottomtray/close_press.png" preload="true" />
+</textures>
diff --git a/indra/newview/skins/minimal/xui/de/floater_camera.xml b/indra/newview/skins/minimal/xui/de/floater_camera.xml
new file mode 100644
index 0000000000..d49c207f98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/floater_camera.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
+ Kamera um Fokus drehen
+ </floater.string>
+ <floater.string name="zoom_tooltip">
+ Kamera auf Fokus zoomen
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Kamera nach oben, unten, links und rechts bewegen
+ </floater.string>
+ <floater.string name="camera_modes_title">
+ Kameramodi
+ </floater.string>
+ <floater.string name="pan_mode_title">
+ Kreisen - Zoomen - Schwenken
+ </floater.string>
+ <floater.string name="presets_mode_title">
+ Ansichten
+ </floater.string>
+ <floater.string name="free_mode_title">
+ Objekt ansehen
+ </floater.string>
+ <panel name="controls">
+ <panel name="preset_views_list">
+ <panel_camera_item name="front_view">
+ <panel_camera_item.text name="front_view_text">
+ Vorderansicht
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="group_view">
+ <panel_camera_item.text name="side_view_text">
+ Seitenansicht
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="rear_view">
+ <panel_camera_item.text name="rear_view_text">
+ Hinteransicht
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="camera_modes_list">
+ <panel_camera_item name="object_view">
+ <panel_camera_item.text name="object_view_text">
+ Objektansicht
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="mouselook_view">
+ <panel_camera_item.text name="mouselook_view_text">
+ Mouselook
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="zoom" tool_tip="Kamera auf Fokus zoomen">
+ <joystick_rotate name="cam_rotate_stick" tool_tip="Kamera um Fokus kreisen"/>
+ <slider_bar name="zoom_slider" tool_tip="Kamera auf Fokus zoomen"/>
+ <joystick_track name="cam_track_stick" tool_tip="Kamera nach oben, unten, links und rechts bewegen"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="presets_btn" tool_tip="Ansichten"/>
+ <button label="" name="pan_btn" tool_tip="Kreisen - Zoomen - Schwenken"/>
+ <button label="" name="avatarview_btn" tool_tip="Kameramodi"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/floater_help_browser.xml b/indra/newview/skins/minimal/xui/de/floater_help_browser.xml
new file mode 100644
index 0000000000..459dfb66c0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/floater_help_browser.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="ANWEISUNGEN">
+ <floater.string name="loading_text">
+ Wird geladen...
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls"/>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/floater_media_browser.xml b/indra/newview/skins/minimal/xui/de/floater_media_browser.xml
new file mode 100644
index 0000000000..63cf4a6cba
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/floater_media_browser.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="MEDIEN-BROWSER">
+ <floater.string name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button label="Zurück" name="back"/>
+ <button label="Vorwärts" name="forward"/>
+ <button label="Neu laden" name="reload"/>
+ <button label="Los" name="go"/>
+ </layout_panel>
+ <layout_panel name="time_controls">
+ <button label="zurück" name="rewind"/>
+ <button label="anhalten" name="stop"/>
+ <button label="vorwärts" name="seek"/>
+ </layout_panel>
+ <layout_panel name="parcel_owner_controls">
+ <button label="Aktuelle Seite an Parzelle senden" name="assign"/>
+ </layout_panel>
+ <layout_panel name="external_controls">
+ <button label="In meinem Browser öffnen" name="open_browser"/>
+ <check_box label="Immer in meinem Browser öffnen" name="open_always"/>
+ <button label="Schließen" name="close"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/floater_nearby_chat.xml b/indra/newview/skins/minimal/xui/de/floater_nearby_chat.xml
new file mode 100644
index 0000000000..bbb4114200
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/floater_nearby_chat.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="CHAT IN DER NÄHE">
+ <check_box label="Chat übersetzen (Service von Google)" name="translate_chat_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/floater_web_content.xml b/indra/newview/skins/minimal/xui/de/floater_web_content.xml
new file mode 100644
index 0000000000..6ab119eeab
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/floater_web_content.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_web_content" title="">
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button name="back" tool_tip="Rückwärts"/>
+ <button name="forward" tool_tip="Vorwärts"/>
+ <button name="stop" tool_tip="Navigation stoppen"/>
+ <button name="reload" tool_tip="Seite neu laden"/>
+ <combo_box name="address" tool_tip="URL hier eingeben"/>
+ <icon name="media_secure_lock_flag" tool_tip="Sicheres Browsen"/>
+ <button name="popexternal" tool_tip="Aktuelle URL im Desktop-Browser öffnen"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/inspect_avatar.xml b/indra/newview/skins/minimal/xui/de/inspect_avatar.xml
new file mode 100644
index 0000000000..4b8fd8a0ad
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/inspect_avatar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [AGE]
+ </string>
+ <string name="Details">
+ [SL_PROFILE]
+ </string>
+ <text name="user_subtitle" value="11 Monate und 3 Tage alt"/>
+ <text name="user_details">
+ Dies ist meine Second Life-Beschreibung und ich finde sie wirklich gut! Meine Beschreibung ist deshalb so lang, weil ich gerne rede.
+ </text>
+ <slider name="volume_slider" tool_tip="Lautstärke" value="0.5"/>
+ <button label="Freund hinzufügen" name="add_friend_btn" width="110"/>
+ <button label="IM" name="im_btn"/>
+ <button label="Profil" left_delta="120" name="view_profile_btn" width="44"/>
+ <panel name="moderator_panel">
+ <button label="Voice deaktivieren" name="disable_voice"/>
+ <button label="Voice aktivieren" name="enable_voice"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/inspect_object.xml b/indra/newview/skins/minimal/xui/de/inspect_object.xml
new file mode 100644
index 0000000000..72b8235828
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/inspect_object.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ Von [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ Von [CREATOR]
+Besitzer [OWNER]
+ </string>
+ <string name="Price">
+ [AMOUNT] L$
+ </string>
+ <string name="PriceFree">
+ Kostenlos!
+ </string>
+ <string name="Touch">
+ Berühren
+ </string>
+ <string name="Sit">
+ Sitzen
+ </string>
+ <text name="object_name" value="Test für ein Objektname der sehr lange ist und über zwei Zeilen geht."/>
+ <text name="object_creator">
+ von secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+Besitzer secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <text name="price_text">
+ 30.000 L$
+ </text>
+ <text name="object_description">
+ Dies ist eine wirklich lange Beschreibung für ein Objekt, mindestens 80 Zeichen lang oder jetzt schon mindestens 120 Zeichen lang und länger als der englische Originaltext. Niemand weiß es genau.
+ </text>
+ <text name="object_media_url">
+ http://www.superdupertest.com
+ </text>
+ <button label="Kaufen" name="buy_btn"/>
+ <button label="Bezahlen" name="pay_btn"/>
+ <button label="Kopie nehmen" name="take_free_copy_btn" width="100"/>
+ <button label="Berühren" name="touch_btn"/>
+ <button label="Sitzen" name="sit_btn"/>
+ <button label="Öffnen" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="Sicheres Browsen"/>
+ <button label="Mehr" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/de/menu_add_wearable_gear.xml b/indra/newview/skins/minimal/xui/de/menu_add_wearable_gear.xml
new file mode 100644
index 0000000000..f3775a05ec
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_add_wearable_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Add Wearable Gear Menu">
+ <menu_item_check label="Nach aktuellesten Objekten sortieren" name="sort_by_most_recent"/>
+ <menu_item_check label="Nach Name sortieren" name="sort_by_name"/>
+ <menu_item_check label="Nach Typ sortieren" name="sort_by_type"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_attachment_other.xml b/indra/newview/skins/minimal/xui/de/menu_attachment_other.xml
new file mode 100644
index 0000000000..237c92f7d2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_attachment_other.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_avatar_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Profil anzeigen" name="Profile..."/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="IM" name="Send IM..."/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="In Gruppe einladen" name="Invite..."/>
+ <menu_item_call label="Ignorieren" name="Avatar Mute"/>
+ <menu_item_call label="Melden" name="abuse"/>
+ <menu_item_call label="Einfrieren" name="Freeze..."/>
+ <menu_item_call label="Hinauswerfen" name="Eject..."/>
+ <menu_item_call label="Fehler in Texturen beseitigen" name="Debug..."/>
+ <menu_item_call label="Hineinzoomen" name="Zoom In"/>
+ <menu_item_call label="Bezahlen" name="Pay..."/>
+ <menu_item_call label="Objektprofil" name="Object Inspect"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_attachment_self.xml b/indra/newview/skins/minimal/xui/de/menu_attachment_self.xml
new file mode 100644
index 0000000000..644fc68ba4
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_attachment_self.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Attachment Pie">
+ <menu_item_call label="Berühren" name="Attachment Object Touch"/>
+ <menu_item_call label="Bearbeiten" name="Edit..."/>
+ <menu_item_call label="Abnehmen" name="Detach"/>
+ <menu_item_call label="Hinsetzen" name="Sit Down Here"/>
+ <menu_item_call label="Aufstehen" name="Stand Up"/>
+ <menu_item_call label="Outfit ändern" name="Change Outfit"/>
+ <menu_item_call label="Mein Outfit bearbeiten" name="Edit Outfit"/>
+ <menu_item_call label="Meine Form bearbeiten" name="Edit My Shape"/>
+ <menu_item_call label="Meine Freunde" name="Friends..."/>
+ <menu_item_call label="Meine Gruppen" name="Groups..."/>
+ <menu_item_call label="Mein Profil" name="Profile..."/>
+ <menu_item_call label="Fehler in Texturen beseitigen" name="Debug..."/>
+ <menu_item_call label="Fallen lassen" name="Drop"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_avatar_icon.xml b/indra/newview/skins/minimal/xui/de/menu_avatar_icon.xml
new file mode 100644
index 0000000000..c036cf5515
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="Profil anzeigen" name="Show Profile"/>
+ <menu_item_call label="IM senden..." name="Send IM"/>
+ <menu_item_call label="Freund hinzufügen..." name="Add Friend"/>
+ <menu_item_call label="Freund entfernen..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_avatar_other.xml b/indra/newview/skins/minimal/xui/de/menu_avatar_other.xml
new file mode 100644
index 0000000000..8aee0be3d2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_avatar_other.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Profil anzeigen" name="Profile..."/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="IM" name="Send IM..."/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="In Gruppe einladen" name="Invite..."/>
+ <menu_item_call label="Ignorieren" name="Avatar Mute"/>
+ <menu_item_call label="Melden" name="abuse"/>
+ <menu_item_call label="Einfrieren" name="Freeze..."/>
+ <menu_item_call label="Hinauswerfen" name="Eject..."/>
+ <menu_item_call label="Fehler in Texturen beseitigen" name="Debug..."/>
+ <menu_item_call label="Hineinzoomen" name="Zoom In"/>
+ <menu_item_call label="Bezahlen" name="Pay..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_avatar_self.xml b/indra/newview/skins/minimal/xui/de/menu_avatar_self.xml
new file mode 100644
index 0000000000..582c76ac94
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_avatar_self.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Self Pie">
+ <menu_item_call label="Hinsetzen" name="Sit Down Here"/>
+ <menu_item_call label="Aufstehen" name="Stand Up"/>
+ <context_menu label="Ausziehen" name="Take Off &gt;">
+ <context_menu label="Kleidung" name="Clothes &gt;">
+ <menu_item_call label="Hemd" name="Shirt"/>
+ <menu_item_call label="Hose" name="Pants"/>
+ <menu_item_call label="Rock" name="Skirt"/>
+ <menu_item_call label="Schuhe" name="Shoes"/>
+ <menu_item_call label="Strümpfe" name="Socks"/>
+ <menu_item_call label="Jacke" name="Jacket"/>
+ <menu_item_call label="Handschuhe" name="Gloves"/>
+ <menu_item_call label="Unterhemd" name="Self Undershirt"/>
+ <menu_item_call label="Unterhose" name="Self Underpants"/>
+ <menu_item_call label="Tätowierung" name="Self Tattoo"/>
+ <menu_item_call label="Alpha" name="Self Alpha"/>
+ <menu_item_call label="Alle Kleider" name="All Clothes"/>
+ </context_menu>
+ <context_menu label="HUD" name="Object Detach HUD"/>
+ <context_menu label="Abnehmen" name="Object Detach"/>
+ <menu_item_call label="Alles abnehmen" name="Detach All"/>
+ </context_menu>
+ <menu_item_call label="Outfit ändern" name="Chenge Outfit"/>
+ <menu_item_call label="Mein Outfit bearbeiten" name="Edit Outfit"/>
+ <menu_item_call label="Meine Form bearbeiten" name="Edit My Shape"/>
+ <menu_item_call label="Meine Freunde" name="Friends..."/>
+ <menu_item_call label="Meine Gruppen" name="Groups..."/>
+ <menu_item_call label="Mein Profil" name="Profile..."/>
+ <menu_item_call label="Fehler in Texturen beseitigen" name="Debug..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_bottomtray.xml b/indra/newview/skins/minimal/xui/de/menu_bottomtray.xml
new file mode 100644
index 0000000000..6c4308286a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_bottomtray.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="Schaltfläche Gesten" name="ShowGestureButton"/>
+ <menu_item_check label="Schaltfläche Bewegungssteuerung" name="ShowMoveButton"/>
+ <menu_item_check label="Schaltfläche Ansicht" name="ShowCameraButton"/>
+ <menu_item_check label="Schaltfläche Foto" name="ShowSnapshotButton"/>
+ <menu_item_check label="Schaltfläche „Seitenleiste“" name="ShowSidebarButton"/>
+ <menu_item_check label="Schaltfläche „Bauen“" name="ShowBuildButton"/>
+ <menu_item_check label="Schaltfläche „Suchen“" name="ShowSearchButton"/>
+ <menu_item_check label="Schaltfläche „Karte“" name="ShowWorldMapButton"/>
+ <menu_item_check label="Schaltfläche „Minikarte“" name="ShowMiniMapButton"/>
+ <menu_item_call label="Ausschneiden" name="NearbyChatBar_Cut"/>
+ <menu_item_call label="Kopieren" name="NearbyChatBar_Copy"/>
+ <menu_item_call label="Einfügen" name="NearbyChatBar_Paste"/>
+ <menu_item_call label="Löschen" name="NearbyChatBar_Delete"/>
+ <menu_item_call label="Alle auswählen" name="NearbyChatBar_Select_All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_cof_attachment.xml b/indra/newview/skins/minimal/xui/de/menu_cof_attachment.xml
new file mode 100644
index 0000000000..05d3dfca9d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_cof_attachment.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Attachment">
+ <menu_item_call label="Abnehmen" name="detach"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_cof_body_part.xml b/indra/newview/skins/minimal/xui/de/menu_cof_body_part.xml
new file mode 100644
index 0000000000..07960a525c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_cof_body_part.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Body">
+ <menu_item_call label="Ersetzen" name="replace"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_cof_clothing.xml b/indra/newview/skins/minimal/xui/de/menu_cof_clothing.xml
new file mode 100644
index 0000000000..7fced273a7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_cof_clothing.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Clothing">
+ <menu_item_call label="Ausziehen" name="take_off"/>
+ <menu_item_call label="Ersetzen" name="replace"/>
+ <menu_item_call label="Eine Kategorie nach oben" name="move_up"/>
+ <menu_item_call label="Eine Kategorie nach unten" name="move_down"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_cof_gear.xml b/indra/newview/skins/minimal/xui/de/menu_cof_gear.xml
new file mode 100644
index 0000000000..54b218d22f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_cof_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear COF">
+ <menu label="Neue Kleider" name="COF.Gear.New_Clothes"/>
+ <menu label="Neue Körperteile" name="COF.Geear.New_Body_Parts"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_edit.xml b/indra/newview/skins/minimal/xui/de/menu_edit.xml
new file mode 100644
index 0000000000..37f68d68d5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_edit.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu label="Bearbeiten" name="Edit">
+ <menu_item_call label="Rückgängig" name="Undo"/>
+ <menu_item_call label="Wiederherstellen" name="Redo"/>
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Duplizieren" name="Duplicate"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+ <menu_item_call label="Auswahl aufheben" name="Deselect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_favorites.xml b/indra/newview/skins/minimal/xui/de/menu_favorites.xml
new file mode 100644
index 0000000000..0d0491d2eb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Teleportieren" name="Teleport To Landmark"/>
+ <menu_item_call label="Landmarken anzeigen/bearbeiten" name="Landmark Open"/>
+ <menu_item_call label="SLurl kopieren" name="Copy slurl"/>
+ <menu_item_call label="Auf Karte zeigen" name="Show On Map"/>
+ <menu_item_call label="Kopieren" name="Landmark Copy"/>
+ <menu_item_call label="Einfügen" name="Landmark Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_gesture_gear.xml b/indra/newview/skins/minimal/xui/de/menu_gesture_gear.xml
new file mode 100644
index 0000000000..953c0eeed5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="Zu Favoriten hinzufügen/daraus entfernen" name="activate"/>
+ <menu_item_call label="Kopieren" name="copy_gesture"/>
+ <menu_item_call label="Einfügen" name="paste"/>
+ <menu_item_call label="UUID kopieren" name="copy_uuid"/>
+ <menu_item_call label="Aktuelles Outfit speichern" name="save_to_outfit"/>
+ <menu_item_call label="Bearbeiten" name="edit_gesture"/>
+ <menu_item_call label="Untersuchen" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_group_plus.xml b/indra/newview/skins/minimal/xui/de/menu_group_plus.xml
new file mode 100644
index 0000000000..583ee793be
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Werden Sie Mitglied..." name="item_join"/>
+ <menu_item_call label="Neue Gruppe..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_hide_navbar.xml b/indra/newview/skins/minimal/xui/de/menu_hide_navbar.xml
new file mode 100644
index 0000000000..9acf96dc6d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_hide_navbar.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="Navigationsleiste anzeigen" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="Favoritenleiste anzeigen" name="ShowNavbarFavoritesPanel"/>
+ <menu_item_check label="Mini-Standortleiste anzeigen" name="ShowMiniLocationPanel"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_im_well_button.xml b/indra/newview/skins/minimal/xui/de/menu_im_well_button.xml
new file mode 100644
index 0000000000..f464b71f4a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_im_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="IM Well Button Context Menu">
+ <menu_item_call label="Alle schließen" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_imchiclet_adhoc.xml b/indra/newview/skins/minimal/xui/de/menu_imchiclet_adhoc.xml
new file mode 100644
index 0000000000..11f93f47b4
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_imchiclet_adhoc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet AdHoc Menu">
+ <menu_item_call label="Sitzung beenden" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_imchiclet_group.xml b/indra/newview/skins/minimal/xui/de/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..81ef3b6569
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="Gruppeninfo" name="Show Profile"/>
+ <menu_item_call label="Sitzung anzeigen" name="Chat"/>
+ <menu_item_call label="Sitzung beenden" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_imchiclet_p2p.xml b/indra/newview/skins/minimal/xui/de/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..d123238246
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="Profil anzeigen" name="Show Profile"/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="Sitzung anzeigen" name="Send IM"/>
+ <menu_item_call label="Sitzung beenden" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..fbc119c483
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<toggleable_menu name="Gear Menu">
+ <menu_item_call label="Profil anzeigen" name="view_profile"/>
+ <menu_item_call label="Freund hinzufügen" name="add_friend"/>
+ <menu_item_call label="IM" name="im"/>
+ <menu_item_call label="Teleportieren" name="teleport"/>
+ <menu_item_call label="Ignorieren" name="block"/>
+ <menu_item_call label="Freischalten" name="unblock"/>
+ <menu_item_call label="Melden" name="report"/>
+ <menu_item_call label="Einfrieren" name="freeze"/>
+ <menu_item_call label="Hinauswerfen" name="eject"/>
+ <menu_item_call label="Hinauswerfen" name="kick"/>
+ <menu_item_call label="CSR" name="csr"/>
+ <menu_item_call label="Fehler in Texturen beseitigen" name="debug"/>
+ <menu_item_call label="Auf Karte anzeigen" name="find_on_map"/>
+ <menu_item_call label="Hineinzoomen" name="zoom_in"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inspect_object_gear.xml b/indra/newview/skins/minimal/xui/de/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..7c47913e30
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inspect_object_gear.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Berühren" name="touch"/>
+ <menu_item_call label="Sitzen" name="sit"/>
+ <menu_item_call label="Bezahlen" name="pay"/>
+ <menu_item_call label="Kaufen" name="buy"/>
+ <menu_item_call label="Nehmen" name="take"/>
+ <menu_item_call label="Kopie nehmen" name="take_copy"/>
+ <menu_item_call label="Öffnen" name="open"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+ <menu_item_call label="Anziehen" name="wear"/>
+ <menu_item_call label="Hinzufügen" name="add"/>
+ <menu_item_call label="Melden" name="report"/>
+ <menu_item_call label="Ignorieren" name="block"/>
+ <menu_item_call label="Hineinzoomen" name="zoom_in"/>
+ <menu_item_call label="Entfernen" name="remove"/>
+ <menu_item_call label="Weitere Infos" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inspect_self_gear.xml b/indra/newview/skins/minimal/xui/de/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..443092319b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="Self Pie">
+ <menu_item_call label="Hinsetzen" name="Sit Down Here"/>
+ <menu_item_call label="Aufstehen" name="Stand Up"/>
+ <menu_item_call label="Meine Freunde" name="Friends..."/>
+ <menu_item_call label="Mein Profil" name="Profile..."/>
+ <menu_item_call label="Fehler in Texturen beseitigen" name="Debug..."/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inv_offer_chiclet.xml b/indra/newview/skins/minimal/xui/de/menu_inv_offer_chiclet.xml
new file mode 100644
index 0000000000..71cff7136b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inv_offer_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="InvOfferChiclet Menu">
+ <menu_item_call label="Schließen" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inventory.xml b/indra/newview/skins/minimal/xui/de/menu_inventory.xml
new file mode 100644
index 0000000000..43722e0dcf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inventory.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Kaufen" name="Task Buy"/>
+ <menu_item_call label="Öffnen" name="Task Open"/>
+ <menu_item_call label="Abspielen" name="Task Play"/>
+ <menu_item_call label="Eigenschaften" name="Task Properties"/>
+ <menu_item_call label="Umbenennen" name="Task Rename"/>
+ <menu_item_call label="Löschen" name="Task Remove"/>
+ <menu_item_call label="Papierkorb ausleeren" name="Empty Trash"/>
+ <menu_item_call label="Fundstücke ausleeren" name="Empty Lost And Found"/>
+ <menu_item_call label="Neuer Ordner" name="New Folder"/>
+ <menu_item_call label="Neues Skript" name="New Script"/>
+ <menu_item_call label="Neue Notizkarte" name="New Note"/>
+ <menu_item_call label="Neue Geste" name="New Gesture"/>
+ <menu label="Neue Kleider" name="New Clothes">
+ <menu_item_call label="Neues Hemd" name="New Shirt"/>
+ <menu_item_call label="Neue Hose" name="New Pants"/>
+ <menu_item_call label="Neue Schuhe" name="New Shoes"/>
+ <menu_item_call label="Neue Socken" name="New Socks"/>
+ <menu_item_call label="Neue Jacke" name="New Jacket"/>
+ <menu_item_call label="Neuer Rock" name="New Skirt"/>
+ <menu_item_call label="Neue Handschuhe" name="New Gloves"/>
+ <menu_item_call label="Neues Unterhemd" name="New Undershirt"/>
+ <menu_item_call label="Neue Unterhose" name="New Underpants"/>
+ <menu_item_call label="Neue Alpha-Maske" name="New Alpha Mask"/>
+ <menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+ </menu>
+ <menu label="Neue Körperteile" name="New Body Parts">
+ <menu_item_call label="Neue Form/Gestalt" name="New Shape"/>
+ <menu_item_call label="Neue Haut" name="New Skin"/>
+ <menu_item_call label="Neues Haar" name="New Hair"/>
+ <menu_item_call label="Neue Augen" name="New Eyes"/>
+ </menu>
+ <menu label="Typ ändern" name="Change Type">
+ <menu_item_call label="Standard" name="Default"/>
+ <menu_item_call label="Handschuhe" name="Gloves"/>
+ <menu_item_call label="Jacke" name="Jacket"/>
+ <menu_item_call label="Hose" name="Pants"/>
+ <menu_item_call label="Form" name="Shape"/>
+ <menu_item_call label="Schuhe" name="Shoes"/>
+ <menu_item_call label="Hemd" name="Shirt"/>
+ <menu_item_call label="Rock" name="Skirt"/>
+ <menu_item_call label="Unterhose" name="Underpants"/>
+ <menu_item_call label="Unterhemd" name="Undershirt"/>
+ </menu>
+ <menu_item_call label="Teleportieren" name="Landmark Open"/>
+ <menu_item_call label="Öffnen" name="Animation Open"/>
+ <menu_item_call label="Öffnen" name="Sound Open"/>
+ <menu_item_call label="Aktuelles Outfit ersetzen" name="Replace Outfit"/>
+ <menu_item_call label="Zum aktuellen Outfit hinzufügen" name="Add To Outfit"/>
+ <menu_item_call label="Vom aktuellen Outfit entfernen" name="Remove From Outfit"/>
+ <menu_item_call label="Original suchen" name="Find Original"/>
+ <menu_item_call label="Objekt löschen" name="Purge Item"/>
+ <menu_item_call label="Objekt wiederherstellen" name="Restore Item"/>
+ <menu_item_call label="Öffnen" name="Open"/>
+ <menu_item_call label="Original öffnen" name="Open Original"/>
+ <menu_item_call label="Eigenschaften" name="Properties"/>
+ <menu_item_call label="Umbenennen" name="Rename"/>
+ <menu_item_call label="Asset-UUID kopieren" name="Copy Asset UUID"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Als Link einfügen" name="Paste As Link"/>
+ <menu_item_call label="Löschen" name="Remove Link"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Systemordner löschen" name="Delete System Folder"/>
+ <menu_item_call label="Konferenz-Chat starten" name="Conference Chat Folder"/>
+ <menu_item_call label="Wiedergeben/Abspielen" name="Sound Play"/>
+ <menu_item_call label="Landmarken-Info" name="About Landmark"/>
+ <menu_item_call label="Inworld abspielen" name="Animation Play"/>
+ <menu_item_call label="Lokal abspielen" name="Animation Audition"/>
+ <menu_item_call label="Instant Message senden" name="Send Instant Message"/>
+ <menu_item_call label="Teleport anbieten..." name="Offer Teleport..."/>
+ <menu_item_call label="Konferenz-Chat starten" name="Conference Chat"/>
+ <menu_item_call label="Aktivieren" name="Activate"/>
+ <menu_item_call label="Deaktivieren" name="Deactivate"/>
+ <menu_item_call label="Speichern unter" name="Save As"/>
+ <menu_item_call label="Von Körper abnehmen" name="Detach From Yourself"/>
+ <menu_item_call label="Anziehen" name="Wearable And Object Wear"/>
+ <menu label="Anhängen an" name="Attach To"/>
+ <menu label="An HUD hängen" name="Attach To HUD"/>
+ <menu_item_call label="Bearbeiten" name="Wearable Edit"/>
+ <menu_item_call label="Hinzufügen" name="Wearable Add"/>
+ <menu_item_call label="Ausziehen" name="Take Off"/>
+ <menu_item_call label="--keine Optionen--" name="--no options--"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inventory_add.xml b/indra/newview/skins/minimal/xui/de/menu_inventory_add.xml
new file mode 100644
index 0000000000..dccee6712d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inventory_add.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Hochladen" name="upload">
+ <menu_item_call label="Bild ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Sound ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Mehrfach-Upload ([COST] L$ pro Datei)..." name="Bulk Upload"/>
+ <menu_item_call label="Hochlade-Berechtigungen (Standard) festlegen" name="perm prefs"/>
+ </menu>
+ <menu_item_call label="Neuer Ordner" name="New Folder"/>
+ <menu_item_call label="Neues Skript" name="New Script"/>
+ <menu_item_call label="Neue Notizkarte" name="New Note"/>
+ <menu_item_call label="Neue Geste" name="New Gesture"/>
+ <menu label="Neue Kleider" name="New Clothes">
+ <menu_item_call label="Neues Hemd" name="New Shirt"/>
+ <menu_item_call label="Neue Hose" name="New Pants"/>
+ <menu_item_call label="Neue Schuhe" name="New Shoes"/>
+ <menu_item_call label="Neue Socken" name="New Socks"/>
+ <menu_item_call label="Neue Jacke" name="New Jacket"/>
+ <menu_item_call label="Neuer Rock" name="New Skirt"/>
+ <menu_item_call label="Neue Handschuhe" name="New Gloves"/>
+ <menu_item_call label="Neues Unterhemd" name="New Undershirt"/>
+ <menu_item_call label="Neue Unterhose" name="New Underpants"/>
+ <menu_item_call label="Neues Alpha" name="New Alpha"/>
+ <menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+ </menu>
+ <menu label="Neue Körperteile" name="New Body Parts">
+ <menu_item_call label="Neue Form/Gestalt" name="New Shape"/>
+ <menu_item_call label="Neue Haut" name="New Skin"/>
+ <menu_item_call label="Neues Haar" name="New Hair"/>
+ <menu_item_call label="Neue Augen" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_inventory_gear_default.xml b/indra/newview/skins/minimal/xui/de/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..df86a5cf71
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_inventory_gear_default.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_gear_default">
+ <menu_item_call label="Neues Inventar-Fenster" name="new_window"/>
+ <menu_item_check label="Nach Name sortieren" name="sort_by_name"/>
+ <menu_item_check label="Nach aktuellesten Objekten sortieren" name="sort_by_recent"/>
+ <menu_item_check label="Systemordner nach oben" name="sort_system_folders_to_top"/>
+ <menu_item_call label="Filter anzeigen" name="show_filters"/>
+ <menu_item_call label="Filter zurücksetzen" name="reset_filters"/>
+ <menu_item_call label="Alle Ordner schließen" name="close_folders"/>
+ <menu_item_call label="Fundbüro ausleeren" name="empty_lostnfound"/>
+ <menu_item_call label="Textur speichern als" name="Save Texture As"/>
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Original suchen" name="Find Original"/>
+ <menu_item_call label="Alle Links suchen" name="Find All Links"/>
+ <menu_item_call label="Papierkorb ausleeren" name="empty_trash"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_land.xml b/indra/newview/skins/minimal/xui/de/menu_land.xml
new file mode 100644
index 0000000000..de679da3d8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_land.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Land Pie">
+ <menu_item_call label="Land-Info" name="Place Information..."/>
+ <menu_item_call label="Hier sitzen" name="Sit Here"/>
+ <menu_item_call label="Dieses Land kaufen" name="Land Buy"/>
+ <menu_item_call label="Pass kaufen" name="Land Buy Pass"/>
+ <menu_item_call label="Bauen" name="Create"/>
+ <menu_item_call label="Land bearbeiten" name="Edit Terrain"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_landmark.xml b/indra/newview/skins/minimal/xui/de/menu_landmark.xml
new file mode 100644
index 0000000000..2aff0eec95
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="SLurl kopieren" name="copy"/>
+ <menu_item_call label="Löschen" name="delete"/>
+ <menu_item_call label="Auswahl erstellen" name="pick"/>
+ <menu_item_call label="Zu Favoritenleiste hinzufügen" name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_login.xml b/indra/newview/skins/minimal/xui/de/menu_login.xml
new file mode 100644
index 0000000000..a373e15338
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_login.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Login Menu">
+ <menu label="Ich" name="File">
+ <menu_item_call label="Einstellungen" name="Preferences..."/>
+ <menu_item_call label="[APP_NAME] schließen" name="Quit"/>
+ </menu>
+ <menu label="Hilfe" name="Help">
+ <menu_item_call label="[SECOND_LIFE]-Hilfe" name="Second Life Help"/>
+ <menu_item_call label="INFO ÜBER [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu_item_check label="Debug-Menü anzeigen" name="Show Debug Menu"/>
+ <menu label="Debug" name="Debug">
+ <menu_item_call label="Debug-Einstellungen anzeigen" name="Debug Settings"/>
+ <menu_item_call label="UI/Farb-Einstellungen" name="UI/Color Settings"/>
+ <menu_item_call label="XUI-Editor" name="UI Preview Tool"/>
+ <menu label="UI-Tests" name="UI Tests"/>
+ <menu_item_call label="Fenstergröße einstellen..." name="Set Window Size..."/>
+ <menu_item_call label="Servicebedingungen anzeigen" name="TOS"/>
+ <menu_item_call label="Wichtige Meldung anzeigen" name="Critical"/>
+ <menu_item_call label="Test Medienbrowser" name="Web Browser Test"/>
+ <menu_item_call label="Test Webinhalt-Floater" name="Web Content Floater Test"/>
+ <menu_item_check label="Grid-Auswahl anzeigen" name="Show Grid Picker"/>
+ <menu_item_call label="Benachrichtigungs-Konsole anzeigen" name="Show Notifications Console"/>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/de/menu_mini_map.xml b/indra/newview/skins/minimal/xui/de/menu_mini_map.xml
new file mode 100644
index 0000000000..2e0d72c40c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_mini_map.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Zoom Nah" name="Zoom Close"/>
+ <menu_item_call label="Zoom Mittel" name="Zoom Medium"/>
+ <menu_item_call label="Zoom Weit" name="Zoom Far"/>
+ <menu_item_call label="Zoom-Standard" name="Zoom Default"/>
+ <menu_item_check label="Karte drehen" name="Rotate Map"/>
+ <menu_item_check label="Automatisch zentrieren" name="Auto Center"/>
+ <menu_item_call label="Verfolgung abschalten" name="Stop Tracking"/>
+ <menu_item_call label="Weltkarte" name="World Map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_navbar.xml b/indra/newview/skins/minimal/xui/de/menu_navbar.xml
new file mode 100644
index 0000000000..5175f34b41
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="Koordinaten anzeigen" name="Show Coordinates"/>
+ <menu_item_check label="Parzelleneigenschaften anzeigen" name="Show Parcel Properties"/>
+ <menu_item_call label="Landmarke" name="Landmark"/>
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_nearby_chat.xml b/indra/newview/skins/minimal/xui/de/menu_nearby_chat.xml
new file mode 100644
index 0000000000..99d6428c3f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="Leute in der Nähe anzeigen..." name="nearby_people"/>
+ <menu_item_check label="Ignorierten Text anzeigen" name="muted_text"/>
+ <menu_item_check label="Bilder von Freunden anzeigen" name="show_buddy_icons"/>
+ <menu_item_check label="Namen anzeigen" name="show_names"/>
+ <menu_item_check label="Namen und Symbole anzeigen" name="show_icons_and_names"/>
+ <menu_item_call label="Schriftgröße" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_notification_well_button.xml b/indra/newview/skins/minimal/xui/de/menu_notification_well_button.xml
new file mode 100644
index 0000000000..0f2784f160
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_notification_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Notification Well Button Context Menu">
+ <menu_item_call label="Alle schließen" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_object.xml b/indra/newview/skins/minimal/xui/de/menu_object.xml
new file mode 100644
index 0000000000..19057d4228
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_object.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Object Pie">
+ <menu_item_call label="Berühren" name="Object Touch">
+ <menu_item_call.on_enable name="EnableTouch" parameter="Berühren"/>
+ </menu_item_call>
+ <menu_item_call label="Bearbeiten" name="Edit..."/>
+ <menu_item_call label="Bauen" name="Build"/>
+ <menu_item_call label="Öffnen" name="Open"/>
+ <menu_item_call label="Hier sitzen" name="Object Sit"/>
+ <menu_item_call label="Aufstehen" name="Object Stand Up"/>
+ <menu_item_call label="Objektprofil" name="Object Inspect"/>
+ <menu_item_call label="Hineinzoomen" name="Zoom In"/>
+ <context_menu label="Anziehen" name="Put On">
+ <menu_item_call label="Anziehen" name="Wear"/>
+ <menu_item_call label="Hinzufügen" name="Add"/>
+ <context_menu label="Anhängen" name="Object Attach"/>
+ <context_menu label="HUD anhängen" name="Object Attach HUD"/>
+ </context_menu>
+ <context_menu label="Entfernen" name="Remove">
+ <menu_item_call label="Missbrauch melden" name="Report Abuse..."/>
+ <menu_item_call label="Ignorieren" name="Object Mute"/>
+ <menu_item_call label="Zurückgeben" name="Return..."/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ </context_menu>
+ <menu_item_call label="Nehmen" name="Pie Object Take"/>
+ <menu_item_call label="Kopie nehmen" name="Take Copy"/>
+ <menu_item_call label="Bezahlen" name="Pay..."/>
+ <menu_item_call label="Kaufen" name="Buy..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_object_icon.xml b/indra/newview/skins/minimal/xui/de/menu_object_icon.xml
new file mode 100644
index 0000000000..8b6c558416
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="Objektprofil..." name="Object Profile"/>
+ <menu_item_call label="Ignorieren..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_outfit_gear.xml b/indra/newview/skins/minimal/xui/de/menu_outfit_gear.xml
new file mode 100644
index 0000000000..897154ec56
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_outfit_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Outfit">
+ <menu_item_call label="Anziehen - Aktuelles Outfit ersetzen" name="wear"/>
+ <menu_item_call label="Anziehen - Aktuelles Outfit hinzufügen" name="wear_add"/>
+ <menu_item_call label="Ausziehen - Aus aktuellem Outfit entfernen" name="take_off"/>
+ <menu label="Neue Kleider" name="New Clothes">
+ <menu_item_call label="Neues Hemd" name="New Shirt"/>
+ <menu_item_call label="Neue Hose" name="New Pants"/>
+ <menu_item_call label="Neue Schuhe" name="New Shoes"/>
+ <menu_item_call label="Neue Socken" name="New Socks"/>
+ <menu_item_call label="Neue Jacke" name="New Jacket"/>
+ <menu_item_call label="Neuer Rock" name="New Skirt"/>
+ <menu_item_call label="Neue Handschuhe" name="New Gloves"/>
+ <menu_item_call label="Neues Unterhemd" name="New Undershirt"/>
+ <menu_item_call label="Neue Unterhose" name="New Underpants"/>
+ <menu_item_call label="Neues Alpha" name="New Alpha"/>
+ <menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+ </menu>
+ <menu label="Neue Körperteile" name="New Body Parts">
+ <menu_item_call label="Neue Form" name="New Shape"/>
+ <menu_item_call label="Neue Haut" name="New Skin"/>
+ <menu_item_call label="Neues Haar" name="New Hair"/>
+ <menu_item_call label="Neue Augen" name="New Eyes"/>
+ </menu>
+ <menu_item_call label="Outfit neu benennen" name="rename"/>
+ <menu_item_call label="Outfit löschen" name="delete_outfit"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_outfit_tab.xml b/indra/newview/skins/minimal/xui/de/menu_outfit_tab.xml
new file mode 100644
index 0000000000..32a65c96fc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_outfit_tab.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit">
+ <menu_item_call label="Anziehen - Aktuelles Outfit ersetzen" name="wear_replace"/>
+ <menu_item_call label="Anziehen - Aktuelles Outfit hinzufügen" name="wear_add"/>
+ <menu_item_call label="Ausziehen - Aus aktuellem Outfit entfernen" name="take_off"/>
+ <menu_item_call label="Outfit bearbeiten" name="edit"/>
+ <menu_item_call label="Outfit neu benennen" name="rename"/>
+ <menu_item_call label="Outfit löschen" name="delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_participant_list.xml b/indra/newview/skins/minimal/xui/de/menu_participant_list.xml
new file mode 100644
index 0000000000..160f2f97be
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_participant_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="Nach Name sortieren" name="SortByName"/>
+ <menu_item_check label="Nach letzten Sprechern sortieren" name="SortByRecentSpeakers"/>
+ <menu_item_call label="Profil anzeigen" name="View Profile"/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Bezahlen" name="Pay"/>
+ <menu_item_check label="Symbole für Personen anzeigen" name="View Icons"/>
+ <menu_item_check label="Voice ignorieren" name="Block/Unblock"/>
+ <menu_item_check label="Text ignorieren" name="MuteText"/>
+ <context_menu label="Moderator-Optionen" name="Moderator Options">
+ <menu_item_check label="Text-Chat zulassen" name="AllowTextChat"/>
+ <menu_item_call label="Diesen Teilnehmer stummschalten" name="ModerateVoiceMuteSelected"/>
+ <menu_item_call label="Stummschaltung für diesen Teilnehmer aufheben" name="ModerateVoiceUnMuteSelected"/>
+ <menu_item_call label="Alle stummschalten" name="ModerateVoiceMute"/>
+ <menu_item_call label="Alle freischalten" name="ModerateVoiceUnmute"/>
+ </context_menu>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_friends_view_sort.xml b/indra/newview/skins/minimal/xui/de/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..84d9d8938c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_friends_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Nach Name sortieren" name="sort_name"/>
+ <menu_item_check label="Nach Status sortieren" name="sort_status"/>
+ <menu_item_check label="Symbole für Personen anzeigen" name="view_icons"/>
+ <menu_item_check label="Erteilte Genehmigungen anzeigen" name="view_permissions"/>
+ <menu_item_call label="Ignorierte Einwohner &amp; Objekte anzeigen" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_groups.xml b/indra/newview/skins/minimal/xui/de/menu_people_groups.xml
new file mode 100644
index 0000000000..76225ba241
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_groups.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Info anzeigen" name="View Info"/>
+ <menu_item_call label="Chat" name="Chat"/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="Aktivieren" name="Activate"/>
+ <menu_item_call label="Verlassen" name="Leave"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_groups_view_sort.xml b/indra/newview/skins/minimal/xui/de/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..b68597d8aa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Gruppensymbole anzeigen" name="Display Group Icons"/>
+ <menu_item_call label="Ausgewählte Gruppe verlassen" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/de/menu_people_nearby.xml
new file mode 100644
index 0000000000..1db964357f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_nearby.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="Profil anzeigen" name="View Profile"/>
+ <menu_item_call label="Freund hinzufügen" name="Add Friend"/>
+ <menu_item_call label="Freund entfernen" name="Remove Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="Karte" name="Map"/>
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Bezahlen" name="Pay"/>
+ <menu_item_check label="Ignorieren/Freischalten" name="Block/Unblock"/>
+ <menu_item_call label="Teleport anbieten" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_nearby_multiselect.xml b/indra/newview/skins/minimal/xui/de/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..b6e99edfe1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_nearby_multiselect.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="Freunde hinzufügen" name="Add Friends"/>
+ <menu_item_call label="Freunde entfernen" name="Remove Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Anrufen" name="Call"/>
+ <menu_item_call label="Teilen" name="Share"/>
+ <menu_item_call label="Bezahlen" name="Pay"/>
+ <menu_item_call label="Teleport anbieten" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_nearby_view_sort.xml b/indra/newview/skins/minimal/xui/de/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..0f252ab46d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Nach letzten Sprechern sortieren" name="sort_by_recent_speakers"/>
+ <menu_item_check label="Nach Name sortieren" name="sort_name"/>
+ <menu_item_check label="Nach Entfernung sortieren" name="sort_distance"/>
+ <menu_item_check label="Symbole für Personen anzeigen" name="view_icons"/>
+ <menu_item_call label="Ignorierte Einwohner &amp; Objekte anzeigen" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_people_recent_view_sort.xml b/indra/newview/skins/minimal/xui/de/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..1ef020f5e1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Nach aktuellesten Sprechern sortieren" name="sort_most"/>
+ <menu_item_check label="Nach Name sortieren" name="sort_name"/>
+ <menu_item_check label="Symbole für Personen anzeigen" name="view_icons"/>
+ <menu_item_call label="Ignorierte Einwohner &amp; Objekte anzeigen" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_picks.xml b/indra/newview/skins/minimal/xui/de/menu_picks.xml
new file mode 100644
index 0000000000..9aec4c83b0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Info" name="pick_info"/>
+ <menu_item_call label="Bearbeiten" name="pick_edit"/>
+ <menu_item_call label="Teleportieren" name="pick_teleport"/>
+ <menu_item_call label="Karte" name="pick_map"/>
+ <menu_item_call label="Löschen" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_picks_plus.xml b/indra/newview/skins/minimal/xui/de/menu_picks_plus.xml
new file mode 100644
index 0000000000..385ff25b95
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="Neue Auswahl" name="create_pick"/>
+ <menu_item_call label="Neue Anzeige" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_place.xml b/indra/newview/skins/minimal/xui/de/menu_place.xml
new file mode 100644
index 0000000000..d9c85f5b92
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="Eine Landmarke setzen" name="landmark"/>
+ <menu_item_call label="Auswahl erstellen" name="pick"/>
+ <menu_item_call label="Pass kaufen" name="pass"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_place_add_button.xml b/indra/newview/skins/minimal/xui/de/menu_place_add_button.xml
new file mode 100644
index 0000000000..7c0ff4a46a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Ordner hinzufügen" name="add_folder"/>
+ <menu_item_call label="Landmarke hinzufügen" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_places_gear_folder.xml b/indra/newview/skins/minimal/xui/de/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..132d3f6466
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Landmarke hinzufügen" name="add_landmark"/>
+ <menu_item_call label="Ordner hinzufügen" name="add_folder"/>
+ <menu_item_call label="Ausschneiden" name="cut"/>
+ <menu_item_call label="Kopieren" name="copy_folder"/>
+ <menu_item_call label="Einfügen" name="paste"/>
+ <menu_item_call label="Umbenennen" name="rename"/>
+ <menu_item_call label="Löschen" name="delete"/>
+ <menu_item_call label="Erweitern Sie sich" name="expand"/>
+ <menu_item_call label="Zuklappen" name="collapse"/>
+ <menu_item_call label="Alle Ordner aufklappen" name="expand_all"/>
+ <menu_item_call label="Alle Ordner schließen" name="collapse_all"/>
+ <menu_item_check label="Nach Datum sortieren" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_places_gear_landmark.xml b/indra/newview/skins/minimal/xui/de/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..6af4d644af
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Teleportieren" name="teleport"/>
+ <menu_item_call label="Weitere Informationen" name="more_info"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Landmarke hinzufügen" name="add_landmark"/>
+ <menu_item_call label="Ordner hinzufügen" name="add_folder"/>
+ <menu_item_call label="Ausschneiden" name="cut"/>
+ <menu_item_call label="Landmarke kopieren" name="copy_landmark"/>
+ <menu_item_call label="SLurl kopieren" name="copy_slurl"/>
+ <menu_item_call label="Einfügen" name="paste"/>
+ <menu_item_call label="Umbenennen" name="rename"/>
+ <menu_item_call label="Löschen" name="delete"/>
+ <menu_item_call label="Alle Ordner aufklappen" name="expand_all"/>
+ <menu_item_call label="Alle Ordner schließen" name="collapse_all"/>
+ <menu_item_check label="Nach Datum sortieren" name="sort_by_date"/>
+ <menu_item_call label="Auswahl erstellen" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_profile_overflow.xml b/indra/newview/skins/minimal/xui/de/menu_profile_overflow.xml
new file mode 100644
index 0000000000..9f3fcbca1d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_profile_overflow.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="Karte" name="show_on_map"/>
+ <menu_item_call label="Bezahlen" name="pay"/>
+ <menu_item_call label="Teilen" name="share"/>
+ <menu_item_call label="Ignorieren" name="block"/>
+ <menu_item_call label="Freischalten" name="unblock"/>
+ <menu_item_call label="Hinauswerfen" name="kick"/>
+ <menu_item_call label="Einfrieren" name="freeze"/>
+ <menu_item_call label="Auftauen" name="unfreeze"/>
+ <menu_item_call label="CSR" name="csr"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_save_outfit.xml b/indra/newview/skins/minimal/xui/de/menu_save_outfit.xml
new file mode 100644
index 0000000000..986c78b318
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_save_outfit.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_outfit_menu">
+ <menu_item_call label="Speichern" name="save_outfit"/>
+ <menu_item_call label="Speichern unter" name="save_as_new_outfit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_script_chiclet.xml b/indra/newview/skins/minimal/xui/de/menu_script_chiclet.xml
new file mode 100644
index 0000000000..3256aa1a87
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_script_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="ScriptChiclet Menu">
+ <menu_item_call label="Schließen" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_slurl.xml b/indra/newview/skins/minimal/xui/de/menu_slurl.xml
new file mode 100644
index 0000000000..b2ec017f9f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_slurl.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="URL-Info" name="about_url"/>
+ <menu_item_call label="Zu URL teleportieren" name="teleport_to_url"/>
+ <menu_item_call label="Karte" name="show_on_map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_teleport_history_gear.xml b/indra/newview/skins/minimal/xui/de/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..68b8e21802
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="Alle Ordner aufklappen" name="Expand all folders"/>
+ <menu_item_call label="Alle Ordner schließen" name="Collapse all folders"/>
+ <menu_item_call label="Teleport-Liste löschen" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_teleport_history_item.xml b/indra/newview/skins/minimal/xui/de/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..ff8fb0b181
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Teleportieren" name="Teleport"/>
+ <menu_item_call label="Weitere Informationen" name="More Information"/>
+ <menu_item_call label="In Zwischenablage kopieren" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_teleport_history_tab.xml b/indra/newview/skins/minimal/xui/de/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..194dd16fd1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Öffnen" name="TabOpen"/>
+ <menu_item_call label="Schließen" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_text_editor.xml b/indra/newview/skins/minimal/xui/de/menu_text_editor.xml
new file mode 100644
index 0000000000..c00186c13e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="Ausschneiden" name="Cut"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+ <menu_item_call label="Einfügen" name="Paste"/>
+ <menu_item_call label="Löschen" name="Delete"/>
+ <menu_item_call label="Alle auswählen" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_topinfobar.xml b/indra/newview/skins/minimal/xui/de/menu_topinfobar.xml
new file mode 100644
index 0000000000..5b0a724244
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_topinfobar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_topinfobar">
+ <menu_item_check label="Koordinaten anzeigen" name="Show Coordinates"/>
+ <menu_item_check label="Parzellen-Eigenschaften anzeigen" name="Show Parcel Properties"/>
+ <menu_item_call label="Landmarke" name="Landmark"/>
+ <menu_item_call label="Kopieren" name="Copy"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_agent.xml b/indra/newview/skins/minimal/xui/de/menu_url_agent.xml
new file mode 100644
index 0000000000..9a808088fb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Einwohnerprofil anzeigen" name="show_agent"/>
+ <menu_item_call label="Name in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_group.xml b/indra/newview/skins/minimal/xui/de/menu_url_group.xml
new file mode 100644
index 0000000000..6bd86414bc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Gruppeninformation anzeigen" name="show_group"/>
+ <menu_item_call label="Gruppe in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_http.xml b/indra/newview/skins/minimal/xui/de/menu_url_http.xml
new file mode 100644
index 0000000000..30eb1668a5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Webseite öffnen" name="url_open"/>
+ <menu_item_call label="Im internen Browser öffnen" name="url_open_internal"/>
+ <menu_item_call label="Im externen Browser öffnen" name="url_open_external"/>
+ <menu_item_call label="URL in Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_inventory.xml b/indra/newview/skins/minimal/xui/de/menu_url_inventory.xml
new file mode 100644
index 0000000000..dc069df02b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Inventarobjekte anzeigen" name="show_item"/>
+ <menu_item_call label="Name in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_map.xml b/indra/newview/skins/minimal/xui/de/menu_url_map.xml
new file mode 100644
index 0000000000..2f6ffcd450
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Zu Position teleportieren" name="teleport_to_location"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_objectim.xml b/indra/newview/skins/minimal/xui/de/menu_url_objectim.xml
new file mode 100644
index 0000000000..90d3763d9c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Objektinformationen anzeigen" name="show_object"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Zu Objekt-Position teleportieren" name="teleport_to_object"/>
+ <menu_item_call label="Objektname in Zwischenablage kopieren" name="url_copy_label"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_parcel.xml b/indra/newview/skins/minimal/xui/de/menu_url_parcel.xml
new file mode 100644
index 0000000000..9169bca24f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Parzelleninformationen anzeigen" name="show_parcel"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_slapp.xml b/indra/newview/skins/minimal/xui/de/menu_url_slapp.xml
new file mode 100644
index 0000000000..72e916b902
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Diesen Befehl ausführen" name="run_slapp"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_slurl.xml b/indra/newview/skins/minimal/xui/de/menu_url_slurl.xml
new file mode 100644
index 0000000000..5d48230ebf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Ortsinformationen anzeigen" name="show_place"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="Zu Position teleportieren" name="teleport_to_location"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_url_teleport.xml b/indra/newview/skins/minimal/xui/de/menu_url_teleport.xml
new file mode 100644
index 0000000000..4cc1ecc70e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="An diesen Standort teleportieren" name="teleport"/>
+ <menu_item_call label="Auf Karte zeigen" name="show_on_map"/>
+ <menu_item_call label="SLurl in die Zwischenablage kopieren" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_viewer.xml b/indra/newview/skins/minimal/xui/de/menu_viewer.xml
new file mode 100644
index 0000000000..67dc618eb0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_viewer.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Main Menu">
+ <menu label="Hilfe" name="Help">
+ <menu_item_call label="[SECOND_LIFE]-Hilfe" name="Second Life Help"/>
+ </menu>
+ <menu label="Erweitert" name="Advanced">
+ <menu label="Tastaturkürzel" name="Shortcuts">
+ <menu_item_check label="Fliegen" name="Fly"/>
+ <menu_item_call label="Fenster schließen" name="Close Window"/>
+ <menu_item_call label="Alle Fenster schließen" name="Close All Windows"/>
+ <menu_item_call label="Ansicht zurücksetzen" name="Reset View"/>
+ </menu>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/de/menu_wearable_list_item.xml b/indra/newview/skins/minimal/xui/de/menu_wearable_list_item.xml
new file mode 100644
index 0000000000..283e454a06
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_wearable_list_item.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit Wearable Context Menu">
+ <menu_item_call label="Ersetzen" name="wear_replace"/>
+ <menu_item_call label="Anziehen" name="wear_wear"/>
+ <menu_item_call label="Hinzufügen" name="wear_add"/>
+ <menu_item_call label="Ausziehen / Abnehmen" name="take_off_or_detach"/>
+ <menu_item_call label="Abnehmen" name="detach"/>
+ <context_menu label="Anhängen an" name="wearable_attach_to"/>
+ <context_menu label="An HUD hängen" name="wearable_attach_to_hud"/>
+ <menu_item_call label="Ausziehen" name="take_off"/>
+ <menu_item_call label="Bearbeiten" name="edit"/>
+ <menu_item_call label="Objektprofil" name="object_profile"/>
+ <menu_item_call label="Original anzeigen" name="show_original"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_wearing_gear.xml b/indra/newview/skins/minimal/xui/de/menu_wearing_gear.xml
new file mode 100644
index 0000000000..80d4ff4d9f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_wearing_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Wearing">
+ <menu_item_call label="Outfit bearbeiten" name="edit"/>
+ <menu_item_call label="Ausziehen" name="takeoff"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/de/menu_wearing_tab.xml b/indra/newview/skins/minimal/xui/de/menu_wearing_tab.xml
new file mode 100644
index 0000000000..695451a105
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/menu_wearing_tab.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Wearing">
+ <menu_item_call label="Ausziehen" name="take_off"/>
+ <menu_item_call label="Abnehmen" name="detach"/>
+ <menu_item_call label="Outfit bearbeiten" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/de/notifications.xml b/indra/newview/skins/minimal/xui/de/notifications.xml
new file mode 100644
index 0000000000..1eee1d1c9b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/notifications.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<notifications>
+ <notification name="UserGiveItem">
+ [NAME_SLURL] bietet Ihnen [ITEM_SLURL] an. Zur Verwendung dieses Artikels müssen Sie in den erweiterten Modus umschalten, wo Sie den Artikel in Ihrem Inventar finden werden. Um in den erweiterten Modus umzuschalten, beenden Sie die Anwendung, starten Sie sie neu und ändern Sie die Moduseinstellung auf dem Anmeldebildschirm.
+ <form name="form">
+ <button name="Show" text="Artikel behalten"/>
+ <button name="Discard" text="Artikel ablehnen"/>
+ <button name="Mute" text="Benutzer blockieren"/>
+ </form>
+ </notification>
+ <notification name="ObjectGiveItem">
+ Ein Objekt namens &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt;, das [NAME_SLURL] gehört, bietet Ihnen [ITEM_SLURL] an. Zur Verwendung dieses Artikels müssen Sie in den erweiterten Modus umschalten, wo Sie den Artikel in Ihrem Inventar finden werden. Um in den erweiterten Modus umzuschalten, beenden Sie die Anwendung, starten Sie sie neu und ändern Sie die Moduseinstellung auf dem Anmeldebildschirm.
+ <form name="form">
+ <button name="Keep" text="Artikel behalten"/>
+ <button name="Discard" text="Artikel ablehnen"/>
+ <button name="Mute" text="Objekt blockieren"/>
+ </form>
+ </notification>
+</notifications>
diff --git a/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml
new file mode 100644
index 0000000000..a4d80921ec
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_bottomtray.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="DragIndicationImageName" value="Accordion_ArrowOpened_Off"/>
+ <string name="SpeakBtnToolTip" value="Schaltet Mikrofon ein/aus"/>
+ <string name="VoiceControlBtnToolTip" value="Voice-Chat-Steuerung anzeigen/ausblenden"/>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_list label="Gesten" name="Gesture" tool_tip="Gesten anzeigen/ausblenden"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <bottomtray_button label="Ansicht" name="camera_btn" tool_tip="Kamerasteuerung anzeigen/ausblenden"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Ziele" name="destination_btn" tool_tip="Zeigt Leutefenster an"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Mein Avatar" name="avatar_btn"/>
+ </layout_panel>
+ <layout_panel name="people_panel">
+ <bottomtray_button label="Leute" name="show_people_button" tool_tip="Zeigt Leutefenster an"/>
+ </layout_panel>
+ <layout_panel name="profile_panel">
+ <bottomtray_button label="Profil" name="show_profile_btn" tool_tip="Zeigt Profilfenster an"/>
+ </layout_panel>
+ <layout_panel name="howto_panel">
+ <bottomtray_button label="Anweisungen" name="show_help_btn" tool_tip="Second Life-Anweisungsthemen öffnen"/>
+ </layout_panel>
+ <layout_panel name="im_well_panel">
+ <chiclet_im_well name="im_well">
+ <button name="Unread IM messages" tool_tip="IMs"/>
+ </chiclet_im_well>
+ </layout_panel>
+ <layout_panel name="notification_well_panel">
+ <chiclet_notification name="notification_well">
+ <button name="Unread" tool_tip="Benachrichtigungen"/>
+ </chiclet_notification>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/de/panel_group_control_panel.xml
new file mode 100644
index 0000000000..81e6040f84
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_group_control_panel.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="vertical_stack">
+ <layout_panel name="end_call_btn_panel">
+ <button label="Anruf beenden" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Voice-Steuerung öffnen" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml
new file mode 100644
index 0000000000..abf8011d9d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_im_control_panel.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <text name="avatar_name" value="Unbekannt"/>
+ <layout_stack name="button_stack">
+ <layout_panel name="view_profile_btn_panel">
+ <button label="Profil" name="view_profile_btn"/>
+ </layout_panel>
+ <layout_panel name="add_friend_btn_panel">
+ <button label="Freund hinzufügen" name="add_friend_btn"/>
+ </layout_panel>
+ <layout_panel name="teleport_btn_panel">
+ <button label="Teleportieren" name="teleport_btn" tool_tip="Dieser Person einen Teleport anbieten."/>
+ </layout_panel>
+ <layout_panel name="share_btn_panel">
+ <button label="Teilen" name="share_btn"/>
+ </layout_panel>
+ <layout_panel name="pay_btn_panel">
+ <button label="Bezahlen" name="pay_btn"/>
+ </layout_panel>
+ <layout_panel name="call_btn_panel">
+ <button label="Anrufen" name="call_btn"/>
+ </layout_panel>
+ <layout_panel name="end_call_btn_panel">
+ <button label="Anruf beenden" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Voice-Steuerung" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_login.xml b/indra/newview/skins/minimal/xui/de/panel_login.xml
new file mode 100644
index 0000000000..2e82453aab
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_login.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_login">
+ <panel.string name="create_account_url">
+ http://de.secondlife.com/registration/
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=de
+ </panel.string>
+ <layout_stack name="login_widgets">
+ <layout_panel name="login">
+ <text name="username_text">
+ Benutzername:
+ </text>
+ <combo_box name="username_combo" tool_tip="Bei der Registrierung gewählter Benutzername wie „berndschmidt12“ oder „Liebe Sonne“"/>
+ <text name="password_text">
+ Kennwort:
+ </text>
+ <check_box label="Kennwort merken" name="remember_check"/>
+ <button label="Anmelden" name="connect_btn"/>
+ <text name="mode_selection_text">
+ Modus:
+ </text>
+ <combo_box name="mode_combo" tool_tip="Wählen Sie den gewünschten Modus aus. Basis: schnelles, einfaches Erkunden und Chatten. Erweitert: Zugriff auf zusätzliche Funktionen.">
+ <combo_box.item label="Basis" name="Basic"/>
+ <combo_box.item label="Erweitert" name="Advanced"/>
+ </combo_box>
+ </layout_panel>
+ <layout_panel name="links">
+ <text name="create_new_account_text">
+ Registrieren
+ </text>
+ <text name="forgot_password_text">
+ Benutzernamen oder Kennwort vergessen?
+ </text>
+ <text name="login_help">
+ Sie brauchen Hilfe?
+ </text>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/de/panel_navigation_bar.xml
new file mode 100644
index 0000000000..ee1a543aac
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_navigation_bar.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <pull_button name="back_btn" tool_tip="Zurück zum vorherigen Standort teleportieren"/>
+ <pull_button name="forward_btn" tool_tip="Um einen Standort weiter teleportieren"/>
+ <button name="home_btn" tool_tip="Zu meinem Zuhause teleportieren"/>
+ <location_input label="Standort" name="location_combo"/>
+ <search_combo_box label="Suche" name="search_combo_box" tool_tip="Suche">
+ <combo_editor label="[SECOND_LIFE] durchsuchen" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+ <favorites_bar name="favorite" tool_tip="Ziehen Sie Landmarken hier hin, damit Sie schnell zu Ihren Lieblingsplätzen in Second Life gelangen können!">
+ <label name="favorites_bar_label" tool_tip="Ziehen Sie Landmarken hier hin, damit Sie schnell zu Ihren Lieblingsplätzen in Second Life gelangen können!">
+ Favoritenleiste
+ </label>
+ <chevron_button name="&gt;&gt;" tool_tip="Mehr meiner Favoriten anzeigen"/>
+ </favorites_bar>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_people.xml b/indra/newview/skins/minimal/xui/de/panel_people.xml
new file mode 100644
index 0000000000..c6253e17de
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_people.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="Leute" name="people_panel">
+ <string name="no_recent_people" value="Sie haben in letzter Zeit mit niemandem interagiert. Suchen Sie nach Leuten, mit denen Sie sich unterhalten können? Klicken Sie unten auf die Schaltfläche „Ziele“."/>
+ <string name="no_filtered_recent_people" value="Es gibt keine Leute mit diesem Namen, mit denen Sie in letzter Zeit interagiert haben."/>
+ <string name="no_one_near" value="Es ist niemand in der Nähe. Suchen Sie nach Leuten, mit denen Sie sich unterhalten können? Klicken Sie unten auf die Schaltfläche „Ziele“."/>
+ <string name="no_one_filtered_near" value="Es ist niemand mit diesem Namen in der Nähe."/>
+ <string name="no_friends_online" value="Keine Freunde online"/>
+ <string name="no_friends" value="Keine Freunde"/>
+ <string name="no_friends_msg">
+ Klicken Sie mit der rechten Maustaste auf einen Einwohner, um ihn als Freund hinzuzufügen. Suchen Sie nach Leuten, mit denen Sie sich unterhalten können? Klicken Sie unten auf die Schaltfläche „Ziele“.
+ </string>
+ <string name="no_filtered_friends_msg">
+ Sie haben nicht das Richtige gefunden? Klicken Sie unten auf die Schaltfläche „Ziele“.
+ </string>
+ <string name="people_filter_label" value="Nach Leuten filtern"/>
+ <string name="groups_filter_label" value="Nach Gruppen filtern"/>
+ <string name="no_filtered_groups_msg" value="Sie haben nicht das Richtige gefunden? Versuchen Sie es mit der [secondlife:///app/search/groups/[SEARCH_TERM] Suche]."/>
+ <string name="no_groups_msg" value="Suchen Sie nach Gruppen? Versuchen Sie es mit der [secondlife:///app/search/groups Suche]."/>
+ <string name="MiniMapToolTipMsg" value="[REGION](Doppelklicken, um Karte zu öffnen; Umschalttaste gedrückt halten und ziehen, um zu schwenken)"/>
+ <string name="AltMiniMapToolTipMsg" value="[REGION](Doppelklicken, um zu teleportieren; Umschalttaste gedrückt halten und ziehen, um zu schwenken)"/>
+ <filter_editor label="Filter" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="IN DER NÄHE" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel"/>
+ </panel>
+ <panel label="MEINE FREUNDE" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="Online"/>
+ <accordion_tab name="tab_all" title="Alle"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <layout_stack name="bottom_panel">
+ <layout_panel name="trash_btn_panel">
+ <dnd_button name="del_btn" tool_tip="Ausgewählte Person aus Ihrer Freundesliste entfernen"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ </panel>
+ <panel label="AKTUELL" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="add_friend_btn" tool_tip="Ausgewählten Einwohner zur Freundeliste hinzufügen"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <layout_stack name="bottom_bar_ls">
+ <layout_panel name="view_profile_btn_lp">
+ <button label="Profil" name="view_profile_btn" tool_tip="Bilder, Gruppen und andere Einwohner-Informationen anzeigen"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="IM" name="im_btn" tool_tip="Instant Messenger öffnen"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Teleportieren" name="teleport_btn" tool_tip="Teleport anbieten"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack name="bottom_bar_ls1">
+ <layout_panel name="group_info_btn_lp">
+ <button label="Gruppenprofil" name="group_info_btn" tool_tip="Gruppeninformationen anzeigen"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Gruppen-Chat" name="chat_btn" tool_tip="Chat öffnen"/>
+ </layout_panel>
+ <layout_panel name="group_call_btn_lp">
+ <button label="Gruppe anrufen" name="group_call_btn" tool_tip="Diese Gruppe anrufen"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_side_tray_tab_caption.xml b/indra/newview/skins/minimal/xui/de/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..652fb7c836
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_side_tray_tab_caption.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="Klappmenü??"/>
+ <button name="undock" tool_tip="Abkoppeln"/>
+ <button name="dock" tool_tip="Andocken"/>
+ <button name="show_help" tool_tip="Hilfe anzeigen"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/de/panel_status_bar.xml b/indra/newview/skins/minimal/xui/de/panel_status_bar.xml
new file mode 100644
index 0000000000..04ed58f944
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/de/panel_status_bar.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="status">
+ <panel.string name="StatBarDaysOfWeek">
+ Sonntag:Montag:Dienstag:Mittwoch:Donnerstag:Freitag:Samstag
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
+ Januar:Februar:März:April:Mai:Juni:Juli:August:September:Oktober:November:Dezember
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
+ Paketverlust
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
+ Bandbreite
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ [AMT] L$
+ </panel.string>
+ <panel name="balance_bg">
+ <text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="20 L$"/>
+ <button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/>
+ </panel>
+ <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)">
+ 24:00 H PST
+ </text>
+ <button name="media_toggle_btn" tool_tip="Alle Medien starten/stoppen (Musik, Video, Webseiten)"/>
+ <button name="volume_btn" tool_tip="Steuerung der Gesamtlautstärke"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/floater_camera.xml b/indra/newview/skins/minimal/xui/en/floater_camera.xml
new file mode 100644
index 0000000000..4cf792444f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/floater_camera.xml
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_dock="true"
+ can_minimize="true"
+ can_close="false"
+ follows="bottom"
+ height="164"
+ layout="topleft"
+ name="camera_floater"
+ save_rect="true"
+ save_visibility="true"
+ save_dock_state="true"
+ single_instance="true"
+ width="228">
+ <floater.string
+ name="rotate_tooltip">
+ Rotate Camera Around Focus
+ </floater.string>
+ <floater.string
+ name="zoom_tooltip">
+ Zoom Camera Towards Focus
+ </floater.string>
+ <floater.string
+ name="move_tooltip">
+ Move Camera Up and Down, Left and Right
+ </floater.string>
+ <floater.string
+ name="camera_modes_title">
+ Camera modes
+ </floater.string>
+ <floater.string
+ name="pan_mode_title">
+ Orbit Zoom Pan
+ </floater.string>
+ <floater.string
+ name="presets_mode_title">
+ Preset Views
+ </floater.string>
+ <floater.string
+ name="free_mode_title">
+ View Object
+ </floater.string>
+ <panel
+ border="false"
+ height="123"
+ layout="topleft"
+ left="2"
+ top="0"
+ mouse_opaque="false"
+ name="controls"
+ width="226">
+ <panel
+ color="Transparent"
+ follows="all"
+ height="102"
+ layout="topleft"
+ left="8"
+ name="preset_views_list"
+ opaque="true"
+ top="24"
+ width="212"
+ visible="false">
+ <panel_camera_item
+ name="front_view">
+ <panel_camera_item.mousedown_callback
+ function="CameraPresets.ChangeView"
+ parameter="front_view" />
+ <panel_camera_item.picture
+ image_name="Cam_Preset_Front_Off" />
+ <panel_camera_item.selected_picture
+ image_name="Cam_Preset_Front_On" />
+ <panel_camera_item.text
+ name="front_view_text">
+ Front View
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item
+ name="group_view"
+ top_pad="4">
+ <panel_camera_item.mousedown_callback
+ function="CameraPresets.ChangeView"
+ parameter="group_view" />
+ <panel_camera_item.picture
+ image_name="Cam_Preset_Side_Off" />
+ <panel_camera_item.selected_picture
+ image_name="Cam_Preset_Side_On" />
+ <panel_camera_item.text
+ name="side_view_text">
+ Side View
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item
+ name="rear_view"
+ layout="topleft"
+ top_pad="4">
+ <panel_camera_item.mousedown_callback
+ function="CameraPresets.ChangeView"
+ parameter="rear_view" />
+ <panel_camera_item.picture
+ image_name="Cam_Preset_Back_Off" />
+ <panel_camera_item.selected_picture
+ image_name="Cam_Preset_Back_On" />
+ <panel_camera_item.text
+ name="rear_view_text">
+ Rear View
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel
+ color="Transparent"
+ follows="all"
+ height="68"
+ item_pad="4"
+ layout="topleft"
+ left="8"
+ name="camera_modes_list"
+ opaque="true"
+ top="24"
+ width="212"
+ visible="false">
+ <panel_camera_item
+ name="object_view">
+ <panel_camera_item.mousedown_callback
+ function="CameraPresets.ChangeView"
+ parameter="object_view" />
+ <panel_camera_item.text
+ name="object_view_text">
+ Object View
+ </panel_camera_item.text>
+ <panel_camera_item.picture
+ image_name="Object_View_Off" />
+ <panel_camera_item.selected_picture
+ image_name="Object_View_On" />
+ </panel_camera_item>
+ <panel_camera_item
+ name="mouselook_view"
+ layout="topleft">
+ <panel_camera_item.mousedown_callback
+ function="CameraPresets.ChangeView"
+ parameter="mouselook_view" />
+ <panel_camera_item.text
+ name="mouselook_view_text">
+ Mouselook View
+ </panel_camera_item.text>
+ <panel_camera_item.picture
+ image_name="MouseLook_View_Off" />
+ <panel_camera_item.selected_picture
+ image_name="MouseLook_View_On" />
+ </panel_camera_item>
+ </panel>
+ <!--TODO: replace + - images -->
+ <panel
+ border="false"
+ class="camera_zoom_panel"
+ height="114"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="zoom"
+ top="20"
+ width="226">
+ <joystick_rotate
+ follows="top|left"
+ height="78"
+ image_selected="Cam_Rotate_In"
+ image_unselected="Cam_Rotate_Out"
+ layout="topleft"
+ left="7"
+ mouse_opaque="false"
+ name="cam_rotate_stick"
+ quadrant="left"
+ scale_image="false"
+ sound_flags="3"
+ visible="true"
+ tool_tip="Orbit camera around focus"
+ top="20"
+ width="78">
+ <commit_callback
+ function="Camera.rotate" />
+ <mouse_held_callback
+ function="Camera.rotate" />
+ </joystick_rotate>
+ <button
+ follows="top|left"
+ height="18"
+ image_disabled="AddItem_Disabled"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ layout="topleft"
+ left_pad="14"
+ name="zoom_plus_btn"
+ width="18"
+ top="18">
+ <commit_callback
+ function="Zoom.plus" />
+ <mouse_held_callback
+ function="Zoom.plus" />
+ </button>
+ <slider_bar
+ height="50"
+ layout="topleft"
+ name="zoom_slider"
+ orientation="vertical"
+ tool_tip="Zoom camera toward focus"
+ top_pad="0"
+ min_val="0"
+ max_val="1"
+ width="18">
+ <commit_callback function="Slider.value_changed"/>
+ </slider_bar>
+ <button
+ follows="top|left"
+ height="18"
+ image_disabled="MinusItem_Disabled"
+ image_selected="MinusItem_Press"
+ image_unselected="MinusItem_Off"
+ layout="topleft"
+ name="zoom_minus_btn"
+ top_pad="0"
+ width="18">
+ <commit_callback
+ function="Zoom.minus" />
+ <mouse_held_callback
+ function="Zoom.minus" />
+ </button>
+ <joystick_track
+ follows="top|left"
+ height="78"
+ image_selected="Cam_Tracking_In"
+ image_unselected="Cam_Tracking_Out"
+ layout="topleft"
+ left="133"
+ name="cam_track_stick"
+ quadrant="left"
+ scale_image="false"
+ sound_flags="3"
+ tool_tip="Move camera up and down, left and right"
+ top="20"
+ width="78">
+ <commit_callback
+ function="Camera.track" />
+ <mouse_held_callback
+ function="Camera.track" />
+ </joystick_track>
+ </panel>
+ </panel>
+ <panel
+ border="false"
+ height="42"
+ layout="topleft"
+ left="2"
+ top_pad="0"
+ name="buttons"
+ width="226">
+ <button
+ height="23"
+ label=""
+ layout="topleft"
+ left="83"
+ is_toggle="true"
+ image_overlay="Cam_Avatar_Off"
+ image_selected="PushButton_Selected_Press"
+ name="presets_btn"
+ tab_stop="false"
+ tool_tip="Preset Views"
+ top="13"
+ width="25">
+ </button>
+ <button
+ height="23"
+ label=""
+ layout="topleft"
+ left_pad="1"
+ is_toggle="true"
+ image_overlay="PanOrbit_Off"
+ image_selected="PushButton_Selected_Press"
+ name="pan_btn"
+ tab_stop="false"
+ tool_tip="Orbit Zoom Pan"
+ width="25">
+ </button>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/floater_help_browser.xml b/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
new file mode 100644
index 0000000000..cc551f7d58
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ can_minimize="false"
+ height="360"
+ layout="topleft"
+ min_height="360"
+ left="645"
+ top="10"
+ min_width="345"
+ name="floater_help_browser"
+ save_rect="true"
+ single_instance="true"
+ title="HOW TO"
+ width="335">
+ <floater.string
+ name="loading_text">
+ Loading...
+ </floater.string>
+ <floater.string
+ name="done_text">
+ </floater.string>
+ <layout_stack
+ bottom="360"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="5"
+ orientation="vertical"
+ name="stack1"
+ top="20"
+ width="325">
+ <layout_panel
+ layout="topleft"
+ left_delta="0"
+ top_delta="0"
+ name="external_controls"
+ user_resize="false"
+ width="325">
+ <web_browser
+ trusted_content="true"
+ bottom="-5"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="0"
+ name="browser"
+ top="0"
+ height="300"
+ width="325" />
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/floater_media_browser.xml b/indra/newview/skins/minimal/xui/en/floater_media_browser.xml
new file mode 100644
index 0000000000..4862146c94
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/floater_media_browser.xml
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="440"
+ layout="topleft"
+ min_height="140"
+ min_width="467"
+ name="floater_about"
+ save_rect="true"
+ auto_tile="true"
+ title="MEDIA BROWSER"
+ width="820">
+ <floater.string
+ name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string
+ name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack
+ bottom="440"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="10"
+ name="stack1"
+ orientation="vertical"
+ top="20"
+ width="800">
+ <layout_panel
+ auto_resize="false"
+ default_tab_group="1"
+ height="20"
+ layout="topleft"
+ left="0"
+ min_height="20"
+ name="nav_controls"
+ top="400"
+ user_resize="false"
+ width="800">
+ <button
+ follows="left|top"
+ height="20"
+ label="Back"
+ layout="topleft"
+ left="0"
+ name="back"
+ top="0"
+ width="55">
+ <button.commit_callback
+ function="MediaBrowser.Back" />
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ label="Forward"
+ layout="topleft"
+ left_pad="3"
+ name="forward"
+ top_delta="0"
+ width="68">
+ <button.commit_callback
+ function="MediaBrowser.Forward" />
+ </button>
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Reload"
+ layout="topleft"
+ left_pad="2"
+ name="reload"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MediaBrowser.Refresh" />
+ </button>
+ <combo_box
+ allow_text_entry="true"
+ follows="left|top|right"
+ tab_group="1"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ max_chars="1024"
+ name="address"
+ combo_editor.select_on_focus="true"
+ top_delta="0"
+ width="540">
+ <combo_box.commit_callback
+ function="MediaBrowser.EnterAddress" />
+ </combo_box>
+ <button
+ enabled="false"
+ follows="right|top"
+ height="20"
+ label="Go"
+ layout="topleft"
+ left_pad="5"
+ name="go"
+ top_delta="0"
+ width="50">
+ <button.commit_callback
+ function="MediaBrowser.Go" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ min_height="20"
+ name="time_controls"
+ top_delta="0"
+ user_resize="false"
+ width="800">
+ <button
+ follows="left|top"
+ height="20"
+ label="rewind"
+ layout="topleft"
+ left="0"
+ name="rewind"
+ top="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ image_selected="button_anim_play_selected.tga"
+ image_unselected="button_anim_play.tga"
+ layout="topleft"
+ left_delta="55"
+ name="play"
+ top_delta="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ image_selected="button_anim_pause_selected.tga"
+ image_unselected="button_anim_pause.tga"
+ layout="topleft"
+ left_delta="0"
+ name="pause"
+ top_delta="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ label="stop"
+ layout="topleft"
+ left_pad="10"
+ name="stop"
+ top_delta="0"
+ width="55" />
+ <button
+ follows="left|top"
+ height="20"
+ label="forward"
+ layout="topleft"
+ left_pad="20"
+ name="seek"
+ top_delta="0"
+ width="55" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ min_height="20"
+ name="parcel_owner_controls"
+ top_delta="0"
+ user_resize="false"
+ width="540">
+ <button
+ enabled="false"
+ follows="left|top"
+ height="20"
+ label="Send Current Page to Parcel"
+ layout="topleft"
+ left="0"
+ name="assign"
+ top="0"
+ width="200">
+ <button.commit_callback
+ function="MediaBrowser.Assign" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ height="40"
+ layout="topleft"
+ left_delta="0"
+ name="external_controls"
+ top_delta="0"
+ user_resize="false"
+ width="540">
+ <web_browser
+ bottom="-30"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="browser"
+ top="0"
+ width="540" />
+ <button
+ follows="bottom|left"
+ height="20"
+ label="Open in My Web Browser"
+ layout="topleft"
+ left_delta="0"
+ name="open_browser"
+ top_pad="5"
+ width="185">
+ <button.commit_callback
+ function="MediaBrowser.OpenWebBrowser" />
+ </button>
+ <check_box
+ control_name="UseExternalBrowser"
+ follows="bottom|left"
+ height="20"
+ label="Always open in my web browser"
+ layout="topleft"
+ left_pad="5"
+ name="open_always"
+ top_delta="0"
+ width="200" />
+ <button
+ follows="bottom|right"
+ height="20"
+ label="Close"
+ layout="topleft"
+ left_pad="80"
+ name="close"
+ top_delta="0"
+ width="70">
+ <button.commit_callback
+ function="MediaBrowser.Close" />
+ </button>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/floater_nearby_chat.xml b/indra/newview/skins/minimal/xui/en/floater_nearby_chat.xml
new file mode 100644
index 0000000000..74ac885202
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/floater_nearby_chat.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<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"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_close="false"
+ can_dock="true"
+ bevel_style="in"
+ height="300"
+ min_width="235"
+ layout="topleft"
+ name="nearby_chat"
+ save_rect="true"
+ title="NEARBY CHAT"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+ width="320">
+ <check_box
+ bottom_delta="36"
+ control_name="TranslateChat"
+ enabled="true"
+ height="16"
+ label="Translate chat (powered by Google)"
+ layout="topleft"
+ left="5"
+ name="translate_chat_checkbox"
+ width="230" />
+ <chat_history
+ parse_urls="true"
+ bg_readonly_color="ChatHistoryBgColor"
+ bg_writeable_color="ChatHistoryBgColor"
+ follows="all"
+ left="5"
+ top_delta="17"
+ layout="topleft"
+ height="260"
+ name="chat_history"
+ parse_highlights="true"
+ text_color="ChatHistoryTextColor"
+ text_readonly_color="ChatHistoryTextColor"
+ right_widget_pad="5"
+ left_widget_pad="0"
+ width="315" />
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/floater_side_bar_tab.xml b/indra/newview/skins/minimal/xui/en/floater_side_bar_tab.xml
new file mode 100644
index 0000000000..83b1260620
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/floater_side_bar_tab.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<floater
+ can_close="true"
+ can_resize="true"
+ min_width="333"
+ min_height="440"
+ save_rect="true"
+ save_visibility="true"
+ >
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/floater_web_content.xml b/indra/newview/skins/minimal/xui/en/floater_web_content.xml
new file mode 100644
index 0000000000..50cb5b14ce
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/floater_web_content.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="775"
+ layout="topleft"
+ min_height="400"
+ min_width="500"
+ name="floater_web_content"
+ save_rect="true"
+ auto_tile="true"
+ title=""
+ initial_mime_type="text/html"
+ width="780">
+ <layout_stack
+ bottom="775"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="5"
+ name="stack1"
+ orientation="vertical"
+ top="20"
+ width="770">
+ <layout_panel
+ auto_resize="false"
+ default_tab_group="1"
+ height="22"
+ layout="topleft"
+ left="0"
+ min_height="20"
+ name="nav_controls"
+ top="400"
+ user_resize="false"
+ width="770">
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ tool_tip="Navigate back"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="1"
+ name="back"
+ top="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Back" />
+ </button>
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Navigate forward"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="27"
+ name="forward"
+ top_delta="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Forward" />
+ </button>
+ <button
+ image_overlay="Stop_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Stop navigation"
+ enabled="true"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="stop"
+ top_delta="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Stop" />
+ </button>
+ <button
+ image_overlay="Refresh_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Reload page"
+ follows="left|top"
+ height="22"
+ layout="topleft"
+ left="51"
+ name="reload"
+ top_delta="0"
+ width="22">
+ <button.commit_callback
+ function="WebContent.Reload" />
+ </button>
+ <combo_box
+ allow_text_entry="true"
+ follows="left|top|right"
+ tab_group="1"
+ height="22"
+ layout="topleft"
+ left_pad="4"
+ max_chars="1024"
+ name="address"
+ combo_editor.select_on_focus="true"
+ tool_tip="Enter URL here"
+ top_delta="0"
+ width="672">
+ <combo_box.commit_callback
+ function="WebContent.EnterAddress" />
+ </combo_box>
+ <icon
+ name="media_secure_lock_flag"
+ height="16"
+ follows="top|right"
+ image_name="Lock2"
+ layout="topleft"
+ left_delta="620"
+ top_delta="2"
+ visible="false"
+ tool_tip="Secured Browsing"
+ width="16" />
+ <button
+ image_overlay="ExternalBrowser_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ tool_tip="Open current URL in your desktop browser"
+ follows="right|top"
+ enabled="true"
+ height="22"
+ layout="topleft"
+ name="popexternal"
+ right="770"
+ top_delta="-2"
+ width="22">
+ <button.commit_callback
+ function="WebContent.PopExternal" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ height="40"
+ layout="topleft"
+ left_delta="0"
+ name="external_controls"
+ top_delta="0"
+ user_resize="false"
+ width="585">
+ <web_browser
+ bottom="-22"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="webbrowser"
+ top="0"/>
+ <text
+ type="string"
+ length="200"
+ follows="bottom|left"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ name="statusbartext"
+ parse_urls="false"
+ text_color="0.4 0.4 0.4 1"
+ top_pad="5"
+ width="495"/>
+ <progress_bar
+ color_bar="0.3 1.0 0.3 1"
+ follows="bottom|right"
+ height="16"
+ top_delta="-1"
+ left_pad="24"
+ layout="topleft"
+ name="statusbarprogress"
+ width="64"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/inspect_avatar.xml b/indra/newview/skins/minimal/xui/en/inspect_avatar.xml
new file mode 100644
index 0000000000..853d5f8735
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/inspect_avatar.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="25"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="164"
+ layout="topleft"
+ name="inspect_avatar"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="245">
+ <!-- Allowed fields include:
+ [BORN_ON] ("12/3/2008")
+ [SL_PROFILE] (Second Life profile),
+ [RW_PROFILE] (real world profile),
+ [ACCTTYPE] ("Resident"),
+ [PAYMENTINFO] ("Payment Info on File"),
+ [AGE] ("1 year 2 months")
+ -->
+ <string
+ name="Subtitle">
+[AGE]
+ </string>
+ <string
+ name="Details">
+[SL_PROFILE]
+ </string>
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="20"
+ left="8"
+ name="user_name_small"
+ top="7"
+ text_color="White"
+ use_ellipses="true"
+ word_wrap="true"
+ visible="false"
+ value="Grumpity ProductEngine with a long name"
+ width="185" />
+ <text
+ follows="top|left"
+ font="SansSerifBigLarge"
+ height="21"
+ left="8"
+ name="user_name"
+ top="10"
+ text_color="White"
+ use_ellipses="true"
+ value="Grumpity ProductEngine"
+ width="190" />
+ <text
+ follows="top|left"
+ height="16"
+ left="8"
+ name="user_slid"
+ font="SansSerifSmallBold"
+ text_color="EmphasisColor"
+ value="james.linden"
+ width="185"
+ use_ellipses="true" />
+ <text
+ follows="top|left"
+ height="16"
+ left="8"
+ name="user_subtitle"
+ font="SansSerifSmall"
+ text_color="White"
+ top_pad="0"
+ value="11 Months, 3 days old"
+ width="175"
+ use_ellipses="true" />
+ <text
+ follows="left|top|right"
+ height="35"
+ left="8"
+ name="user_details"
+ right="-10"
+ word_wrap="true"
+ top_pad="4"
+ use_ellipses="true"
+ width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot
+ </text>
+ <slider
+ follows="top|left"
+ height="23"
+ increment="0.01"
+ left="1"
+ max_val="0.95"
+ min_val="0.05"
+ name="volume_slider"
+ show_text="false"
+ tool_tip="Voice volume"
+ top_pad="0"
+ value="0.5"
+ width="200" />
+ <button
+ follows="top|left"
+ height="16"
+ image_disabled="Audio_Off"
+ image_disabled_selected="AudioMute_Off"
+ image_hover_selected="AudioMute_Over"
+ image_selected="AudioMute_Off"
+ image_unselected="Audio_Off"
+ is_toggle="true"
+ left_pad="0"
+ top_delta="4"
+ name="mute_btn"
+ width="16" />
+ <avatar_icon
+ follows="top|left"
+ height="38"
+ right="-10"
+ bevel_style="in"
+ border_style="line"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="10"
+ width="38" />
+<!-- Overlapping buttons for default actions
+ llinspectavatar.cpp makes visible the most likely default action
+-->
+ <button
+ follows="top|left"
+ height="20"
+ label="Add Friend"
+ left="8"
+ top="135"
+ name="add_friend_btn"
+ width="90" />
+ <button
+ follows="top|left"
+ height="20"
+ label="IM"
+ left_delta="0"
+ top_delta="0"
+ name="im_btn"
+ width="80"
+ commit_callback.function="InspectAvatar.IM"/>
+ <button
+ follows="top|left"
+ height="20"
+ label="Profile"
+ layout="topleft"
+ name="view_profile_btn"
+ left_delta="96"
+ top_delta="0"
+ tab_stop="false"
+ width="80" />
+ <!-- gear buttons here -->
+ <menu_button
+ follows="top|left"
+ height="20"
+ layout="topleft"
+ image_overlay="OptionsMenu_Off"
+ menu_filename="menu_inspect_avatar_gear.xml"
+ name="gear_btn"
+ right="-5"
+ top_delta="0"
+ width="35" />
+ <menu_button
+ follows="top|left"
+ height="20"
+ image_overlay="OptionsMenu_Off"
+ menu_filename="menu_inspect_self_gear.xml"
+ name="gear_self_btn"
+ right="-5"
+ top_delta="0"
+ width="35" />
+ <panel
+ follows="top|left"
+ top="164"
+ left="0"
+ height="60"
+ width="228"
+ visible="false"
+ background_visible="true"
+ name="moderator_panel"
+ background_opaque="true"
+ bg_opaque_color="MouseGray">
+ <button
+ name="disable_voice"
+ label="Disable Voice"
+ top="20"
+ width="95"
+ height="20"
+ left="10"
+ commit_callback.function="InspectAvatar.DisableVoice"/>
+ <button
+ name="enable_voice"
+ label="Enable Voice"
+ top="20"
+ width="95"
+ height="20"
+ left="10"
+ visible="false"
+ commit_callback.function="InspectAvatar.EnableVoice"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/inspect_object.xml b/indra/newview/skins/minimal/xui/en/inspect_object.xml
new file mode 100644
index 0000000000..f424069ec6
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/inspect_object.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater
+ legacy_header_height="25"
+ bevel_style="in"
+ bg_opaque_image="Inspector_Background"
+ can_close="false"
+ can_minimize="false"
+ height="150"
+ layout="topleft"
+ name="inspect_object"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="228">
+ <string name="Creator">By [CREATOR]</string>
+ <string name="CreatorAndOwner">
+By [CREATOR]
+Owner [OWNER]
+ </string>
+ <string name="Price">L$[AMOUNT]</string>
+ <string name="PriceFree">Free!</string>
+ <string name="Touch">Touch</string>
+ <string name="Sit">Sit</string>
+ <text
+ parse_urls="false"
+ follows="all"
+ font="SansSerifLarge"
+ height="30"
+ left="8"
+ name="object_name"
+ text_color="White"
+ top="6"
+ use_ellipses="true"
+ word_wrap="true"
+ width="220" />
+ <text
+ follows="all"
+ height="50"
+ left="8"
+ name="object_creator"
+ top_pad="6"
+ use_ellipses="true"
+ width="220">
+ by secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <text
+ follows="all"
+ font="SansSerifSmall"
+ font.style="BOLD"
+ height="14"
+ halign="right"
+ right="-5"
+ name="price_text"
+ text_color="white"
+ top="60"
+ font_shadow="none"
+ width="60">
+L$30,000
+ </text>
+ <text
+ clip_partial="true"
+ follows="all"
+ font="SansSerifSmall"
+ height="25"
+ left="8"
+ name="object_description"
+ top="76"
+ use_ellipses="true"
+ width="220"
+ word_wrap="true">
+ </text>
+ <!-- Overlapping buttons for all default actions. Show "Buy" if
+ for sale, "Sit" if can sit, etc. -->
+ <icon
+ name="secure_browsing"
+ image_name="Lock"
+ left="0"
+ visible="false"
+ width="18"
+ height="18"
+ top="103"
+ tool_tip="Secure Browsing"
+ follows="left|top" />
+ <text
+ follows="all"
+ font="SansSerifSmall"
+ height="13"
+ name="object_media_url"
+ width="207"
+ left_pad="2"
+ top_delta="0"
+ max_length = "50"
+ use_ellipses="true">
+ http://www.superdupertest.com
+</text>
+ <button
+ follows="top|left"
+ height="20"
+ label="Take Copy"
+ left_delta="0"
+ name="take_free_copy_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Touch"
+ left_delta="0"
+ name="touch_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Sit"
+ left_delta="0"
+ name="sit_btn"
+ top_delta="0"
+ width="80" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Open"
+ left_delta="0"
+ name="open_btn"
+ top_delta="0"
+ width="80" />
+
+ <!-- non-overlapping buttons here -->
+ <menu_button
+ follows="top|left"
+ height="20"
+ image_overlay="OptionsMenu_Off"
+ menu_filename="menu_inspect_object_gear.xml"
+ name="gear_btn"
+ right="-5"
+ top_delta="0"
+ width="35" />
+</floater>
diff --git a/indra/newview/skins/minimal/xui/en/main_view.xml b/indra/newview/skins/minimal/xui/en/main_view.xml
new file mode 100644
index 0000000000..45ba785c1f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/main_view.xml
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ height="768"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="main_view"
+ width="1024">
+ <panel top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="login_panel_holder"
+ width="1024"/>
+
+ <layout_stack border_size="0"
+ follows="all"
+ mouse_opaque="false"
+ height="768"
+ name="menu_stack"
+ orientation="vertical"
+ top="0">
+ <layout_panel auto_resize="false"
+ height="30"
+ mouse_opaque="false"
+ name="nav_bar_container"
+ tab_stop="false"
+ min_height="0"
+ width="1024"
+ user_resize="false"
+ visible="true">
+ </layout_panel>
+ <layout_panel auto_resize="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="hud"
+ width="1024">
+ <panel auto_resize="false"
+ follows="all"
+ height="500"
+ top="0"
+ layout="topleft"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="non_side_tray_view"
+ user_resize="false"
+ width="1024">
+
+ <layout_stack border_size="0"
+ bottom="500"
+ follows="all"
+ height="500"
+ left="0"
+ top="0"
+ mouse_opaque="false"
+ name="world_stack"
+ open_time_constant="0.03"
+ close_time_constant="0.03"
+ orientation="vertical">
+ <layout_panel auto_resize="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ tab_stop="false"
+ mouse_opaque="false"
+ user_resize="false"
+ name="hud container"
+ width="500">
+ <view top="0"
+ follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="floater_snap_region"
+ width="500"/>
+ <panel follows="left|top"
+ height="0"
+ left="0"
+ mouse_opaque="false"
+ name="topinfo_bar_container"
+ tab_stop="false"
+ top="0"
+ visible="false"
+ width="1024"/>
+ <panel bottom="500"
+ follows="left|right|bottom"
+ height="25"
+ left="0"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="stand_stop_flying_container"
+ visible="false"
+ width="500"/>
+ <panel follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="floater_view_holder"
+ tab_group="-1"
+ tab_stop="false"
+ top="0"
+ width="500">
+ <floater_view follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="Floater View"
+ tab_group="-1"
+ tab_stop="false"
+ top="0"
+ width="500"/>
+ </panel>
+ <panel bottom="500"
+ follows="all"
+ height="500"
+ left="0"
+ mouse_opaque="false"
+ name="world_view_rect"
+ top="0"
+ width="500"/>
+ </layout_panel>
+ <layout_panel auto_resize="false"
+ min_height="33"
+ height="33"
+ mouse_opaque="false"
+ name="bottom_tray_container"
+ visible="false"/>
+ <layout_panel auto_resize="false"
+ height="215"
+ mouse_opaque="false"
+ user_resize="false"
+ name="avatar_picker_and_destination_guide_container"
+ visible="false">
+ <panel top="0"
+ height="215"
+ left="0"
+ background_visible="true"
+ width="500"
+ follows="all">
+ <web_browser
+ top="0"
+ height="200"
+ follows="all"
+ name="destination_guide_contents"
+ trusted_content="true"
+ visible="false"/>
+ <web_browser
+ top="0"
+ height="200"
+ follows="all"
+ name="avatar_picker_contents"
+ visible="false"
+ trusted_content="true"/>
+ <button
+ name="close"
+ width="22"
+ height="23"
+ right="-10"
+ top="2"
+ follows="top|right"
+ chrome="true"
+ tab_stop="false"
+ image_unselected="bottomtray_close_off"
+ image_selected="bottomtray_close_press"
+ />
+ </panel>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ <debug_view follows="all"
+ left="0"
+ top="0"
+ mouse_opaque="false"
+ height="500"
+ name="DebugView"
+ width="1024"/>
+ </layout_panel>
+ </layout_stack>
+ <panel mouse_opaque="false"
+ follows="right|top"
+ name="status_bar_container"
+ tab_stop="false"
+ height="30"
+ left="-70"
+ top="0"
+ width="70"
+ visible="false"/>
+ <panel follows="top|bottom"
+ height="500"
+ mouse_opaque="false"
+ tab_stop="false"
+ name="hidden_side_tray"
+ visible="false"
+ width="333">
+ <panel
+ name="side_tray_container"
+ width="333"
+ height="500"/>
+ </panel>
+
+ <panel top="0"
+ follows="all"
+ mouse_opaque="false"
+ left="0"
+ name="snapshot_floater_view_holder"
+ width="1024"
+ height="798">
+ <snapshot_floater_view enabled="false"
+ follows="all"
+ height="768"
+ left="0"
+ mouse_opaque="false"
+ name="Snapshot Floater View"
+ tab_stop="false"
+ top="0"
+ visible="false"
+ width="1024"/>
+ </panel>
+ <panel top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="popup_holder"
+ class="popup_holder"
+ width="1024">
+ <icon follows="right|bottom"
+ image_name="Resize_Corner"
+ right="-1"
+ name="resize_corner"
+ width="11"
+ bottom="-1"
+ height="11" />
+ </panel>
+ <view top="0"
+ left="0"
+ width="1024"
+ height="768"
+ name="hint_holder"
+ mouse_opaque="false"
+ follows="all"/>
+ <panel top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="true"
+ name="progress_view"
+ filename="panel_progress.xml"
+ class="progress_view"
+ width="1024"
+ visible="false"/>
+ <menu_holder top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="Menu Holder"
+ width="1024"/>
+ <tooltip_view top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="tooltip view"
+ tab_group="-2"
+ width="1024"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/menu_add_wearable_gear.xml b/indra/newview/skins/minimal/xui/en/menu_add_wearable_gear.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_add_wearable_gear.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_attachment_other.xml b/indra/newview/skins/minimal/xui/en/menu_attachment_other.xml
new file mode 100644
index 0000000000..b55e677276
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_attachment_other.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: See also menu_avatar_other.xml -->
+<context_menu
+ layout="topleft"
+ name="Avatar Pie">
+ <menu_item_call
+ label="View Profile"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="hit object" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Add Friend"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableAddFriend" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ name="Send IM...">
+ <menu_item_call.on_click
+ function="Avatar.SendIM" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ enabled="false"
+ label="Block"
+ name="Avatar Mute">
+ <menu_item_call.on_click
+ function="Avatar.Mute" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ name="abuse">
+ <menu_item_call.on_click
+ function="Avatar.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ name="Freeze...">
+ <menu_item_call.on_click
+ function="Avatar.Freeze" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="Eject...">
+ <menu_item_call.on_click
+ function="Avatar.Eject" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Debug Textures"
+ name="Debug...">
+ <menu_item_call.on_click
+ function="Avatar.Debug" />
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="Zoom In">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ </menu_item_call>
+ <menu_item_separator />
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_attachment_self.xml b/indra/newview/skins/minimal/xui/en/menu_attachment_self.xml
new file mode 100644
index 0000000000..542a7dc7dc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_attachment_self.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Attachment Pie">
+ <menu_item_call
+ enabled="false"
+ label="Touch"
+ layout="topleft"
+ name="Attachment Object Touch">
+ <menu_item_call.on_click
+ function="Object.Touch" />
+ <menu_item_call.on_enable
+ function="Object.EnableTouch"
+ name="EnableTouch"/>
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Detach"
+ layout="topleft"
+ name="Detach">
+ <menu_item_call.on_click
+ function="Attachment.Detach" />
+ <menu_item_call.on_enable
+ function="Attachment.EnableDetach" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_avatar_icon.xml b/indra/newview/skins/minimal/xui/en/menu_avatar_icon.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_avatar_icon.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_avatar_other.xml b/indra/newview/skins/minimal/xui/en/menu_avatar_other.xml
new file mode 100644
index 0000000000..b76629f401
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_avatar_other.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu
+ layout="topleft"
+ name="Avatar Pie">
+ <menu_item_call
+ label="View Profile"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="hit object" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Add Friend"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableAddFriend" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ name="Send IM...">
+ <menu_item_call.on_click
+ function="Avatar.SendIM" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ enabled="false"
+ label="Block"
+ name="Avatar Mute">
+ <menu_item_call.on_click
+ function="Avatar.Mute" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ name="abuse">
+ <menu_item_call.on_click
+ function="Avatar.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ name="Freeze...">
+ <menu_item_call.on_click
+ function="Avatar.Freeze" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="Eject...">
+ <menu_item_call.on_click
+ function="Avatar.Eject" />
+ <menu_item_call.on_visible
+ function="Avatar.EnableFreezeEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Debug Textures"
+ name="Debug...">
+ <menu_item_call.on_click
+ function="Avatar.Debug" />
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="Zoom In">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_avatar_self.xml b/indra/newview/skins/minimal/xui/en/menu_avatar_self.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_avatar_self.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_bottomtray.xml b/indra/newview/skins/minimal/xui/en/menu_bottomtray.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_bottomtray.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_cof_attachment.xml b/indra/newview/skins/minimal/xui/en/menu_cof_attachment.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_cof_attachment.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_cof_body_part.xml b/indra/newview/skins/minimal/xui/en/menu_cof_body_part.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_cof_body_part.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_cof_clothing.xml b/indra/newview/skins/minimal/xui/en/menu_cof_clothing.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_cof_clothing.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_cof_gear.xml b/indra/newview/skins/minimal/xui/en/menu_cof_gear.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_cof_gear.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_edit.xml b/indra/newview/skins/minimal/xui/en/menu_edit.xml
new file mode 100644
index 0000000000..747eb3fc6a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_edit.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu create_jump_keys="true"
+ label="Edit"
+ name="Edit"
+ visible="false">
+ <menu_item_call
+ label="Undo"
+ name="Undo"
+ shortcut="control|Z">
+ <menu_item_call.on_click
+ function="Edit.Undo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableUndo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Redo"
+ name="Redo"
+ shortcut="control|Y">
+ <menu_item_call.on_click
+ function="Edit.Redo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableRedo" />
+ </menu_item_call>
+ <menu_item_separator/>
+ <menu_item_call
+ label="Cut"
+ name="Cut"
+ shortcut="control|X">
+ <menu_item_call.on_click
+ function="Edit.Cut" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ name="Copy"
+ shortcut="control|C">
+ <menu_item_call.on_click
+ function="Edit.Copy" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ name="Paste"
+ shortcut="control|V">
+ <menu_item_call.on_click
+ function="Edit.Paste" />
+ <menu_item_call.on_enable
+ function="Edit.EnablePaste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ name="Delete"
+ allow_key_repeat="true"
+ shortcut="Del">
+ <menu_item_call.on_click
+ function="Edit.Delete" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Duplicate"
+ name="Duplicate"
+ shortcut="control|D">
+ <menu_item_call.on_click
+ function="Edit.Duplicate" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDuplicate" />
+ </menu_item_call>
+ <menu_item_separator/>
+ <menu_item_call
+ label="Select All"
+ name="Select All"
+ shortcut="control|A">
+ <menu_item_call.on_click
+ function="Edit.SelectAll" />
+ <menu_item_call.on_enable
+ function="Edit.EnableSelectAll" />
+ </menu_item_call>
+ <menu_item_call
+ label="Deselect"
+ name="Deselect"
+ shortcut="control|E">
+ <menu_item_call.on_click
+ function="Edit.Deselect" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDeselect" />
+ </menu_item_call>
+</menu> \ No newline at end of file
diff --git a/indra/newview/skins/minimal/xui/en/menu_favorites.xml b/indra/newview/skins/minimal/xui/en/menu_favorites.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_favorites.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_gesture_gear.xml b/indra/newview/skins/minimal/xui/en/menu_gesture_gear.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_gesture_gear.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_group_plus.xml b/indra/newview/skins/minimal/xui/en/menu_group_plus.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_group_plus.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_hide_navbar.xml b/indra/newview/skins/minimal/xui/en/menu_hide_navbar.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_hide_navbar.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_im_well_button.xml b/indra/newview/skins/minimal/xui/en/menu_im_well_button.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_im_well_button.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_imchiclet_adhoc.xml b/indra/newview/skins/minimal/xui/en/menu_imchiclet_adhoc.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_imchiclet_adhoc.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_imchiclet_group.xml b/indra/newview/skins/minimal/xui/en/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_imchiclet_group.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_imchiclet_p2p.xml b/indra/newview/skins/minimal/xui/en/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_imchiclet_p2p.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/en/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..5a4a059781
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inspect_avatar_gear.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<toggleable_menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="View Profile"
+ enabled="true"
+ name="view_profile">
+ <menu_item_call.on_click
+ function="InspectAvatar.ViewProfile"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ name="add_friend">
+ <menu_item_call.on_click
+ function="InspectAvatar.AddFriend"/>
+ <menu_item_call.on_enable
+ function="InspectAvatar.Gear.Enable"/>
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ name="im">
+ <menu_item_call.on_click
+ function="InspectAvatar.IM"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport"
+ name="teleport">
+ <menu_item_call.on_click
+ function="InspectAvatar.Teleport"/>
+ <menu_item_call.on_enable
+ function="InspectAvatar.Gear.EnableTeleportOffer"/>
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Block"
+ name="block">
+ <menu_item_call.on_click
+ function="InspectAvatar.ToggleMute"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unblock"
+ name="unblock">
+ <menu_item_call.on_click
+ function="InspectAvatar.ToggleMute"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.EnableUnmute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ name="report">
+ <menu_item_call.on_click
+ function="InspectAvatar.Report"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Freeze"
+ name="freeze">
+ <menu_item_call.on_click
+ function="InspectAvatar.Freeze"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleFreeze"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Eject"
+ name="eject">
+ <menu_item_call.on_click
+ function="InspectAvatar.Eject"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleEject"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Kick"
+ name="kick">
+ <menu_item_call.on_click
+ function="InspectAvatar.Kick"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.EnableGod"/>
+ </menu_item_call>
+ <menu_item_call
+ label="CSR"
+ name="csr">
+ <menu_item_call.on_click
+ function="InspectAvatar.CSR" />
+ <menu_item_call.on_visible
+ function="InspectAvatar.EnableGod" />
+ </menu_item_call>
+ <menu_item_call
+ label="Debug Textures"
+ name="debug">
+ <menu_item_call.on_click
+ function="Avatar.Debug"/>
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Find On Map"
+ name="find_on_map">
+ <menu_item_call.on_click
+ function="InspectAvatar.FindOnMap"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleFindOnMap"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="zoom_in">
+ <menu_item_call.on_click
+ function="InspectAvatar.ZoomIn"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleZoomIn"/>
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/minimal/xui/en/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..8ec360a604
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inspect_object_gear.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<toggleable_menu
+ create_jump_keys="true"
+ layout="topleft"
+ mouse_opaque="false"
+ visible="false"
+ name="Gear Menu">
+ <menu_item_call
+ label="Touch"
+ layout="topleft"
+ enabled="true"
+ name="touch">
+ <menu_item_call.on_click
+ function="InspectObject.Touch"/>
+ <menu_item_call.on_visible
+ function="Object.EnableTouch" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sit"
+ layout="topleft"
+ name="sit">
+ <menu_item_call.on_click
+ function="InspectObject.Sit"/>
+ <menu_item_call.on_visible
+ function="Object.EnableSit"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Report"
+ layout="topleft"
+ name="report">
+ <menu_item_call.on_click
+ function="Object.ReportAbuse" />
+ </menu_item_call>
+ <menu_item_call
+ label="Block"
+ layout="topleft"
+ name="block">
+ <menu_item_call.on_click
+ function="Object.Mute" />
+ <menu_item_call.on_visible
+ function="Object.EnableMute" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="zoom_in">
+ <menu_item_call.on_click
+ function="InspectObject.ZoomIn" />
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/minimal/xui/en/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..ae8b640d26
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inspect_self_gear.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ layout="topleft"
+ name="Self Pie">
+ <menu_item_call
+ label="Sit Down"
+ layout="topleft"
+ name="Sit Down Here">
+ <menu_item_call.on_click
+ function="Self.SitDown"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Self.EnableSitDown" />
+ </menu_item_call>
+ <menu_item_call
+ label="Stand Up"
+ layout="topleft"
+ name="Stand Up">
+ <menu_item_call.on_click
+ function="Self.StandUp"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Self.EnableStandUp" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Friends"
+ layout="topleft"
+ name="Friends...">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="friends_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Profile"
+ layout="topleft"
+ name="Profile...">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="agent" />
+ </menu_item_call>
+ <menu_item_call
+ label="Debug Textures"
+ name="Debug...">
+ <menu_item_call.on_click
+ function="Avatar.Debug" />
+ <menu_item_call.on_visible
+ function="IsGodCustomerService"/>
+ </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inv_offer_chiclet.xml b/indra/newview/skins/minimal/xui/en/menu_inv_offer_chiclet.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inv_offer_chiclet.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inventory.xml b/indra/newview/skins/minimal/xui/en/menu_inventory.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inventory.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inventory_add.xml b/indra/newview/skins/minimal/xui/en/menu_inventory_add.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inventory_add.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/minimal/xui/en/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_inventory_gear_default.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_land.xml b/indra/newview/skins/minimal/xui/en/menu_land.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_land.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_landmark.xml b/indra/newview/skins/minimal/xui/en/menu_landmark.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_landmark.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_login.xml b/indra/newview/skins/minimal/xui/en/menu_login.xml
new file mode 100644
index 0000000000..62dbce3f56
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_login.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_bar/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_mini_map.xml b/indra/newview/skins/minimal/xui/en/menu_mini_map.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_mini_map.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_navbar.xml b/indra/newview/skins/minimal/xui/en/menu_navbar.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_navbar.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_nearby_chat.xml b/indra/newview/skins/minimal/xui/en/menu_nearby_chat.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_nearby_chat.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_notification_well_button.xml b/indra/newview/skins/minimal/xui/en/menu_notification_well_button.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_notification_well_button.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_object.xml b/indra/newview/skins/minimal/xui/en/menu_object.xml
new file mode 100644
index 0000000000..888ce42cf1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_object.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Object Pie">
+ <menu_item_call
+ enabled="false"
+ label="Sit Here"
+ name="Object Sit">
+ <menu_item_call.on_click
+ function="Object.SitOrStand" />
+ <menu_item_call.on_enable
+ function="Object.EnableSit" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Stand Up"
+ name="Object Stand Up">
+ <menu_item_call.on_click
+ function="Object.SitOrStand" />
+ <menu_item_call.on_enable
+ function="Object.EnableStandUp" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom In"
+ name="Zoom In">
+ <menu_item_call.on_click
+ function="Object.ZoomIn" />
+ </menu_item_call>
+ <menu_item_call
+ enabled="false"
+ label="Touch"
+ name="Object Touch">
+ <menu_item_call.on_click
+ function="Object.Touch" />
+ <menu_item_call.on_enable
+ function="Object.EnableTouch"
+ name="EnableTouch"
+ parameter="Touch" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_object_icon.xml b/indra/newview/skins/minimal/xui/en/menu_object_icon.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_object_icon.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_outfit_gear.xml b/indra/newview/skins/minimal/xui/en/menu_outfit_gear.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_outfit_gear.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_outfit_tab.xml b/indra/newview/skins/minimal/xui/en/menu_outfit_tab.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_outfit_tab.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_participant_list.xml b/indra/newview/skins/minimal/xui/en/menu_participant_list.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_participant_list.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/minimal/xui/en/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_friends_view_sort.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_groups.xml b/indra/newview/skins/minimal/xui/en/menu_people_groups.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_groups.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/minimal/xui/en/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_groups_view_sort.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/en/menu_people_nearby.xml
new file mode 100644
index 0000000000..3d64133f54
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_nearby.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Avatar Context Menu">
+ <menu_item_call
+ label="View Profile"
+ layout="topleft"
+ name="View Profile">
+ <menu_item_call.on_click
+ function="Avatar.Profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Friend"
+ layout="topleft"
+ name="Add Friend">
+ <menu_item_call.on_click
+ function="Avatar.AddFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_add" />
+ </menu_item_call>
+ <menu_item_call
+ label="Remove Friend"
+ layout="topleft"
+ name="Remove Friend">
+ <menu_item_call.on_click
+ function="Avatar.RemoveFriend" />
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_delete" />
+ </menu_item_call>
+ <menu_item_call
+ label="IM"
+ layout="topleft"
+ name="IM">
+ <menu_item_call.on_click
+ function="Avatar.IM" />
+ </menu_item_call>
+ <menu_item_check
+ label="Block/Unblock"
+ layout="topleft"
+ name="Block/Unblock">
+ <menu_item_check.on_click
+ function="Avatar.BlockUnblock" />
+ <menu_item_check.on_check
+ function="Avatar.CheckItem"
+ parameter="is_blocked" />
+ <menu_item_check.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_block" />
+ </menu_item_check>
+ <menu_item_call
+ label="Offer Teleport"
+ name="teleport">
+ <menu_item_call.on_click
+ function="Avatar.OfferTeleport"/>
+ <menu_item_call.on_enable
+ function="Avatar.EnableItem"
+ parameter="can_offer_teleport"/>
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/minimal/xui/en/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_nearby_multiselect.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/minimal/xui/en/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_nearby_view_sort.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/minimal/xui/en/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_people_recent_view_sort.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_picks.xml b/indra/newview/skins/minimal/xui/en/menu_picks.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_picks.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_picks_plus.xml b/indra/newview/skins/minimal/xui/en/menu_picks_plus.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_picks_plus.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_place.xml b/indra/newview/skins/minimal/xui/en/menu_place.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_place.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_place_add_button.xml b/indra/newview/skins/minimal/xui/en/menu_place_add_button.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_place_add_button.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/minimal/xui/en/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_places_gear_folder.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/minimal/xui/en/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_places_gear_landmark.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_profile_overflow.xml b/indra/newview/skins/minimal/xui/en/menu_profile_overflow.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_profile_overflow.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_save_outfit.xml b/indra/newview/skins/minimal/xui/en/menu_save_outfit.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_save_outfit.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_script_chiclet.xml b/indra/newview/skins/minimal/xui/en/menu_script_chiclet.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_script_chiclet.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_slurl.xml b/indra/newview/skins/minimal/xui/en/menu_slurl.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_slurl.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/minimal/xui/en/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_teleport_history_gear.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/minimal/xui/en/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_teleport_history_item.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_teleport_history_tab.xml b/indra/newview/skins/minimal/xui/en/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_teleport_history_tab.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_text_editor.xml b/indra/newview/skins/minimal/xui/en/menu_text_editor.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_text_editor.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_topinfobar.xml b/indra/newview/skins/minimal/xui/en/menu_topinfobar.xml
new file mode 100644
index 0000000000..9ebab9ef98
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_topinfobar.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_agent.xml b/indra/newview/skins/minimal/xui/en/menu_url_agent.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_agent.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_group.xml b/indra/newview/skins/minimal/xui/en/menu_url_group.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_group.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_http.xml b/indra/newview/skins/minimal/xui/en/menu_url_http.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_http.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_inventory.xml b/indra/newview/skins/minimal/xui/en/menu_url_inventory.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_inventory.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_map.xml b/indra/newview/skins/minimal/xui/en/menu_url_map.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_map.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_objectim.xml b/indra/newview/skins/minimal/xui/en/menu_url_objectim.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_objectim.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_parcel.xml b/indra/newview/skins/minimal/xui/en/menu_url_parcel.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_parcel.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_slapp.xml b/indra/newview/skins/minimal/xui/en/menu_url_slapp.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_slapp.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_slurl.xml b/indra/newview/skins/minimal/xui/en/menu_url_slurl.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_slurl.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_url_teleport.xml b/indra/newview/skins/minimal/xui/en/menu_url_teleport.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_url_teleport.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_viewer.xml b/indra/newview/skins/minimal/xui/en/menu_viewer.xml
new file mode 100644
index 0000000000..cd83ea4e99
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_viewer.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ name="Main Menu">
+ <menu
+ create_jump_keys="true"
+ label="Help"
+ name="Help"
+ tear_off="true">
+ <menu_item_call
+ label="[SECOND_LIFE] Help"
+ name="Second Life Help"
+ shortcut="F1">
+ <menu_item_call.on_click
+ function="ShowHelp"
+ parameter="f1_help" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Advanced"
+ name="Advanced"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Shortcuts"
+ name="Shortcuts"
+ tear_off="true"
+ visible="false">
+ <menu_item_check
+ label="Fly"
+ name="Fly"
+ shortcut="Home">
+ <menu_item_check.on_check
+ function="Agent.getFlying" />
+ <menu_item_check.on_click
+ function="Agent.toggleFlying" />
+ <menu_item_check.on_enable
+ function="Agent.enableFlying" />
+ </menu_item_check>
+ <menu_item_call
+ label="Close Window"
+ name="Close Window"
+ shortcut="control|W">
+ <menu_item_call.on_click
+ function="File.CloseWindow" />
+ <menu_item_call.on_enable
+ function="File.EnableCloseWindow" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Windows"
+ name="Close All Windows"
+ shortcut="control|shift|W">
+ <menu_item_call.on_click
+ function="File.CloseAllWindows" />
+ <menu_item_call.on_enable
+ function="File.EnableCloseAllWindows" />
+ </menu_item_call>
+
+ <menu_item_call
+ label="Reset View"
+ name="Reset View"
+ shortcut="Esc">
+ <menu_item_call.on_click
+ function="View.ResetView" />
+ </menu_item_call>
+ </menu> <!--Shortcuts-->
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/en/menu_wearable_list_item.xml b/indra/newview/skins/minimal/xui/en/menu_wearable_list_item.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_wearable_list_item.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_wearing_gear.xml b/indra/newview/skins/minimal/xui/en/menu_wearing_gear.xml
new file mode 100644
index 0000000000..28c4762eaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_wearing_gear.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/menu_wearing_tab.xml b/indra/newview/skins/minimal/xui/en/menu_wearing_tab.xml
new file mode 100644
index 0000000000..fb19c5eb2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/menu_wearing_tab.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu/>
diff --git a/indra/newview/skins/minimal/xui/en/notification_visibility.xml b/indra/newview/skins/minimal/xui/en/notification_visibility.xml
new file mode 100644
index 0000000000..616b544847
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/notification_visibility.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" ?>
+<notification_visibility>
+ <respond name="VoiceInviteP2P" response="Decline"/>
+ <respond name="VoiceInviteAdHoc" response="Decline"/>
+ <respond name="VoiceInviteGroup" response="Decline"/>
+
+ <!-- group and voice are disabled features -->
+ <hide tag="group"/>
+ <hide tag="voice"/>
+
+ <!-- no spammy scripts -->
+ <!-- <hide name="ScriptDialog"/> -->
+
+ <!-- hints pertaining to UI we don't show -->
+ <hide name="FirstBalanceIncrease"/>
+ <hide name="FirstInventory"/>
+ <hide name="HintSidePanel"/>
+ <hide name="HintMove"/>
+ <hide name="HintDisplayName"/>
+ <hide name="HintInventory"/>
+ <hide name="HintLindenDollar"/>
+
+ <!-- spam from servers, such as "Autopilot cancelled" -->
+ <hide name="SystemMessageTip"/>
+
+ <!-- show everything else -->
+ <show/>
+</notification_visibility>
+
diff --git a/indra/newview/skins/minimal/xui/en/notifications.xml b/indra/newview/skins/minimal/xui/en/notifications.xml
new file mode 100644
index 0000000000..84da9472cc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/notifications.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<notifications>
+ <notification
+ icon="notify.tga"
+ name="UserGiveItem"
+ type="offer">
+ [NAME_SLURL] is offering you [ITEM_SLURL]. Using this item requires you to switch to Advanced mode where you will find the item in your Inventory. To switch to Advanced mode, quit and restart this application and change the mode setting on the login screen.
+ <form name="form">
+ <button
+ index="4"
+ name="Show"
+ text="Keep Item"/>
+ <button
+ index="1"
+ name="Discard"
+ text="Reject Item"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block User"/>
+ </form>
+ </notification>
+ <notification
+ icon="notify.tga"
+ name="ObjectGiveItem"
+ type="offer">
+ An object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; owned by [NAME_SLURL] is offering you [ITEM_SLURL]. Using this item requires you to switch to Advanced mode where you will find the item in your Inventory. To switch to Advanced mode, quit and restart this application and change the mode setting on the login screen.
+ <form name="form">
+ <button
+ index="0"
+ name="Keep"
+ text="Keep Item"/>
+ <button
+ index="1"
+ name="Discard"
+ text="Reject Item"/>
+ <button
+ index="2"
+ name="Mute"
+ text="Block Object"/>
+ </form>
+ </notification>
+
+</notifications>
diff --git a/indra/newview/skins/minimal/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/minimal/xui/en/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..5730adab8a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_adhoc_control_panel.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="215"
+ name="panel_im_control_panel"
+ width="150">
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="215"
+ layout="topleft"
+ left="3"
+ name="vertical_stack"
+ orientation="vertical"
+ top="0"
+ width="147">
+ <layout_panel
+ auto_resize="true"
+ follows="top|left"
+ height="130"
+ layout="topleft"
+ left="0"
+ min_height="0"
+ mouse_opaque="false"
+ width="147"
+ top="0"
+ name="speakers_list_panel"
+ user_resize="false">
+ <avatar_list
+ color="DkGray2"
+ follows="all"
+ height="130"
+ ignore_online_status="true"
+ layout="topleft"
+ name="speakers_list"
+ opaque="false"
+ show_info_btn="true"
+ show_profile_btn="false"
+ show_speaking_indicator="false"
+ width="147" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml
new file mode 100644
index 0000000000..0145de8be9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_bottomtray.xml
@@ -0,0 +1,483 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
+ chrome="true"
+ follows="left|bottom|right"
+ height="33"
+ layout="topleft"
+ left="0"
+ name="bottom_tray"
+ focus_root="true"
+ top="28"
+ width="1310">
+ <string
+ name="DragIndicationImageName"
+ value="Accordion_ArrowOpened_Off" />
+ <string
+ name="SpeakBtnToolTip"
+ value="Turns microphone on/off" />
+ <string
+ name="VoiceControlBtnToolTip"
+ value="Shows/hides voice control panel" />
+ <layout_stack
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="28"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="toolbar_stack"
+ orientation="horizontal"
+ top="0"
+ width="1310">
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ min_width="2"
+ width="2" />
+ <layout_panel
+ auto_resize="false"
+ layout="topleft"
+ max_width="320"
+ min_width="214"
+ height="28"
+ mouse_opaque="false"
+ name="chat_bar_layout_panel"
+ user_resize="true"
+ width="308" >
+ <panel
+ name="chat_bar"
+ filename="panel_nearby_chat_bar.xml"
+ left="0"
+ height="28"
+ width="306"
+ top="0"
+ mouse_opaque="false"
+ follows="left|right"
+ />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="65"
+ mouse_opaque="false"
+ name="gesture_panel"
+ top_delta="0"
+ user_resize="false"
+ width="85">
+ <gesture_combo_list
+ follows="left|right"
+ height="23"
+ label="Gesture"
+ layout="topleft"
+ get_more="false"
+ view_all="false"
+ left="0"
+ name="Gesture"
+ tool_tip="Shows/hides gestures"
+ top="5"
+ width="82">
+ <combo_button
+ pad_right="10"
+ can_drag="false"
+ use_ellipses="true" />
+ <combo_list
+ page_lines="17" />
+ </gesture_combo_list>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="52"
+ mouse_opaque="false"
+ name="cam_panel"
+ user_resize="false"
+ width="83">
+ <bottomtray_button
+ can_drag="false"
+ follows="left|right"
+ height="23"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ is_toggle="true"
+ label="View"
+ layout="topleft"
+ left="0"
+ name="camera_btn"
+ tool_tip="Shows/hides camera controls"
+ top="5"
+ use_ellipses="true"
+ width="80">
+ <init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="camera" />
+ </bottomtray_button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_width="17"
+ name="splitter_panel"
+ user_resize="false"
+ width="17">
+ <icon
+ follows="left|bottom"
+ height="18"
+ width="2"
+ left="6"
+ image_name="Button_Separator"
+ name="separator"
+ top="7"/>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="83"
+ mouse_opaque="false"
+ name="avatar_and_destinations_panel"
+ user_resize="false"
+ width="103">
+ <bottomtray_button
+ can_drag="false"
+ follows="left|right"
+ height="23"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="Destinations"
+ layout="topleft"
+ left="0"
+ name="destination_btn"
+ tool_tip="Shows people window"
+ top="5"
+ is_toggle="true"
+ use_ellipses="true"
+ width="100">
+ <bottomtray_button.commit_callback
+ function="Destination.show" />
+ </bottomtray_button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="73"
+ mouse_opaque="false"
+ name="avatar_and_destinations_panel"
+ user_resize="false"
+ width="103">
+ <bottomtray_button
+ can_drag="false"
+ follows="left|right"
+ height="23"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="My Avatar"
+ layout="topleft"
+ left="0"
+ name="avatar_btn"
+ top="5"
+ is_toggle="true"
+ use_ellipses="true"
+ width="100">
+ <bottomtray_button.commit_callback
+ function="Avatar.show" />
+ </bottomtray_button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="left|right"
+ height="28"
+ layout="topleft"
+ min_width="17"
+ name="splitter_panel"
+ user_resize="false"
+ width="17">
+ <icon
+ follows="left|bottom"
+ height="18"
+ width="2"
+ left="6"
+ image_name="Button_Separator"
+ name="separator"
+ top="7"/>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="65"
+ mouse_opaque="false"
+ name="people_panel"
+ top_delta="0"
+ user_resize="false"
+ width="105">
+ <bottomtray_button
+ can_drag="false"
+ follows="left|right"
+ height="23"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="People"
+ layout="topleft"
+ left="0"
+ name="show_people_button"
+ tool_tip="Shows people window"
+ top="5"
+ is_toggle="true"
+ use_ellipses="true"
+ width="100">
+ <bottomtray_button.commit_callback
+ function="ShowSidetrayPanel"
+ parameter="panel_people" />
+ </bottomtray_button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="65"
+ mouse_opaque="false"
+ name="profile_panel"
+ top_delta="0"
+ user_resize="false"
+ width="105">
+ <bottomtray_button
+ can_drag="false"
+ follows="left|right"
+ height="23"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="Profile"
+ layout="topleft"
+ left="0"
+ name="show_profile_btn"
+ tool_tip="Shows profile window"
+ is_toggle="true"
+ top="5"
+ use_ellipses="true"
+ width="100">
+ <bottomtray_button.commit_callback
+ function="ToggleAgentProfile"
+ parameter="agent"/>
+ </bottomtray_button>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="65"
+ mouse_opaque="false"
+ name="howto_panel"
+ top_delta="0"
+ user_resize="false"
+ width="105">
+ <bottomtray_button
+ can_drag="false"
+ follows="left|right"
+ height="23"
+ image_pressed="PushButton_Press"
+ image_pressed_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
+ label="How To"
+ layout="topleft"
+ left="0"
+ name="show_help_btn"
+ tool_tip="Open Second Life How To topics"
+ is_toggle="true"
+ top="5"
+ use_ellipses="true"
+ width="100">
+ <bottomtray_button.commit_callback
+ function="ToggleHelp"
+ parameter="f1_help" />
+ </bottomtray_button>
+ </layout_panel>
+ <layout_panel
+ follows="left|right"
+ height="30"
+ layout="topleft"
+ min_width="95"
+ mouse_opaque="false"
+ name="chiclet_list_panel"
+ top="0"
+ user_resize="false"
+ width="189">
+ <!--*NOTE: min_width of the chiclet_panel (chiclet_list) must be the same
+as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly. EXT-991-->
+ <chiclet_panel
+ chiclet_padding="4"
+ follows="left|right"
+ height="24"
+ layout="topleft"
+ left="1"
+ min_width="95"
+ mouse_opaque="false"
+ name="chiclet_list"
+ top="7"
+ width="189">
+ <button
+ auto_resize="true"
+ follows="right"
+ height="29"
+ image_hover_selected="SegmentedBtn_Left_Over"
+ image_hover_unselected="SegmentedBtn_Left_Over"
+ image_overlay="Arrow_Small_Left"
+ image_pressed="SegmentedBtn_Left_Press"
+ image_pressed_selected="SegmentedBtn_Left_Press"
+ image_selected="SegmentedBtn_Left_Off"
+ image_unselected="SegmentedBtn_Left_Off"
+ layout="topleft"
+ name="chicklet_left_scroll_button"
+ tab_stop="false"
+ top="-28"
+ visible="false"
+ width="7" />
+ <button
+ auto_resize="true"
+ follows="right"
+ height="29"
+ image_hover_selected="SegmentedBtn_Right_Over"
+ image_hover_unselected="SegmentedBtn_Right_Over"
+ image_overlay="Arrow_Small_Right"
+ image_pressed="SegmentedBtn_Right_Press"
+ image_pressed_selected="SegmentedBtn_Right_Press"
+ image_selected="SegmentedBtn_Right_Off"
+ image_unselected="SegmentedBtn_Right_Off"
+ layout="topleft"
+ name="chicklet_right_scroll_button"
+ tab_stop="false"
+ top="-28"
+ visible="false"
+ width="7" />
+ </chiclet_panel>
+ </layout_panel>
+ <layout_panel auto_resize="false"
+ user_resize="false"
+ width="4"
+ min_width="4"/>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="37"
+ name="im_well_panel"
+ top="0"
+ user_resize="false"
+ width="37">
+ <chiclet_im_well
+ follows="right"
+ height="28"
+ layout="topleft"
+ left="0"
+ max_displayed_count="99"
+ name="im_well"
+ top="0"
+ width="35">
+ <!--
+Emulate 4 states of button by background images, see details in EXT-3147. The same should be for notification_well button
+xml attribute Description
+image_unselected "Unlit" - there are no new messages
+image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
+image_pressed "Lit" - there are new messages
+image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
+ -->
+ <button
+ auto_resize="true"
+ follows="right"
+ halign="center"
+ height="23"
+ image_overlay="Unread_IM"
+ image_overlay_alignment="center"
+ image_pressed="WellButton_Lit"
+ image_pressed_selected="WellButton_Lit_Selected"
+ image_selected="PushButton_Press"
+ label_color="Black"
+ left="0"
+ name="Unread IM messages"
+ tool_tip="Conversations"
+ width="34">
+ <init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="im_well_window" />
+ </button>
+ </chiclet_im_well>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ min_width="37"
+ name="notification_well_panel"
+ top="0"
+ user_resize="false"
+ width="37">
+ <chiclet_notification
+ follows="right"
+ height="23"
+ layout="topleft"
+ left="0"
+ max_displayed_count="99"
+ name="notification_well"
+ top="5"
+ width="35">
+ <button
+ auto_resize="true"
+ bottom_pad="3"
+ follows="right"
+ halign="center"
+ height="23"
+ image_overlay="Notices_Unread"
+ image_overlay_alignment="center"
+ image_pressed="WellButton_Lit"
+ image_pressed_selected="WellButton_Lit_Selected"
+ image_selected="PushButton_Press"
+ label_color="Black"
+ left="0"
+ name="Unread"
+ tool_tip="Notifications"
+ width="34">
+ <init_callback
+ function="Button.SetDockableFloaterToggle"
+ parameter="notification_well_window" />
+ </button>
+ </chiclet_notification>
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ user_resize="false"
+ min_width="4"
+ name="DUMMY2"
+ width="8" />
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/en/panel_group_control_panel.xml
new file mode 100644
index 0000000000..abddc59296
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_group_control_panel.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="238"
+ name="panel_im_control_panel"
+ width="150">
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="238"
+ layout="topleft"
+ left="5"
+ name="vertical_stack"
+ orientation="vertical"
+ top="0"
+ width="145">
+ <layout_panel
+ auto_resize="true"
+ follows="top|left"
+ height="100"
+ layout="topleft"
+ min_height="0"
+ mouse_opaque="false"
+ width="145"
+ top="0"
+ name="speakers_list_panel"
+ user_resize="false">
+ <avatar_list
+ color="DkGray2"
+ follows="all"
+ height="100"
+ ignore_online_status="true"
+ layout="topleft"
+ name="speakers_list"
+ opaque="false"
+ show_info_btn="true"
+ show_profile_btn="false"
+ show_speaking_indicator="false"
+ width="145" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="130"
+ name="end_call_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="23"
+ label="Leave Call"
+ name="end_call_btn"
+ use_ellipses="true" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="130"
+ name="voice_ctrls_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="all"
+ height="23"
+ label="Open Voice Controls"
+ name="voice_ctrls_btn"
+ use_ellipses="true" />
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
new file mode 100644
index 0000000000..53def54aca
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ height="300"
+ name="panel_im_control_panel"
+ width="150">
+ <avatar_icon
+ follows="left|top"
+ height="105"
+ left_delta="20"
+ name="avatar_icon"
+ top="-5"
+ width="114"/>
+ <layout_stack
+ mouse_opaque="false"
+ border_size="0"
+ clip="false"
+ follows="all"
+ height="183"
+ layout="topleft"
+ left="5"
+ name="button_stack"
+ orientation="vertical"
+ top_pad="5"
+ width="145">
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_login.xml b/indra/newview/skins/minimal/xui/en/panel_login.xml
new file mode 100644
index 0000000000..ef058e5567
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_login.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+follows="all"
+height="600"
+layout="topleft"
+left="0"
+name="panel_login"
+focus_root="true"
+top="600"
+ width="996">
+<panel.string
+ name="create_account_url">
+ http://join.secondlife.com/
+</panel.string>
+<string name="reg_in_client_url" translate="false">
+ http://secondlife.eniac15.lindenlab.com/reg-in-client/
+</string>
+<panel.string
+ name="forgot_password_url">
+ http://secondlife.com/account/request.php
+</panel.string>
+<!-- *NOTE: Custom resize logic for login_html in llpanellogin.cpp -->
+<web_browser
+ tab_stop="false"
+trusted_content="true"
+bg_opaque_color="Black"
+border_visible="false"
+bottom="600"
+follows="all"
+hide_loading="true"
+left="0"
+name="login_html"
+start_url=""
+top="0"
+height="600"
+ width="980" />
+<layout_stack
+follows="left|bottom|right"
+name="login_widgets"
+layout="topleft"
+orientation="horizontal"
+top="519"
+width="996"
+height="80">
+<layout_panel
+auto_resize="false"
+follows="left|bottom"
+name="login"
+layout="topleft"
+width="570"
+min_width="570"
+user_resize="false"
+height="80">
+<text
+follows="left|bottom"
+font="SansSerifSmall"
+height="16"
+name="username_text"
+top="20"
+left="20"
+width="150">
+Username:
+</text>
+ <combo_box
+ allow_text_entry="true"
+ follows="left|bottom"
+ height="22"
+ left_delta="0"
+ max_chars="128"
+ combo_editor.prevalidate_callback="ascii"
+ tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine"
+ top_pad="0"
+ name="username_combo"
+ width="178">
+ <combo_box.combo_button
+ visible ="false"/>
+ <combo_box.drop_down_button
+ visible ="false"/>
+ </combo_box>
+<text
+follows="left|bottom"
+font="SansSerifSmall"
+height="15"
+left_pad="-19"
+name="password_text"
+top="20"
+ width="150">
+ Password:
+</text>
+<line_editor
+follows="left|bottom"
+ height="22"
+left_delta="0"
+ max_length_bytes="16"
+name="password_edit"
+is_password="true"
+select_on_focus="true"
+ top_pad="0"
+ width="135" />
+ <check_box
+control_name="RememberPassword"
+follows="left|bottom"
+font="SansSerifSmall"
+height="16"
+label="Remember password"
+ top_pad="3"
+ name="remember_check"
+ width="135" />
+<button
+ follows="left|bottom"
+ height="23"
+ image_unselected="PushButton_On"
+ image_selected="PushButton_On_Selected"
+ label="Log In"
+ label_color="White"
+ layout="topleft"
+ left_pad="10"
+ name="connect_btn"
+ top="35"
+ width="90" />
+ <text
+ follows="left|bottom"
+ font="SansSerifSmall"
+ height="15"
+ left_pad="10"
+ name="mode_selection_text"
+top="20"
+ width="130">
+ Mode:
+ </text>
+<combo_box
+ follows="left|bottom"
+ height="23"
+ max_chars="128"
+ top_pad="0"
+ tool_tip="Select your mode. Choose Basic for fast, easy exploration and chat. Choose Advanced to access more features."
+ control_name="SessionSettingsFile"
+ name="mode_combo"
+ width="120">
+<combo_box.item
+ label="Basic"
+ name="Basic"
+ value="settings_minimal.xml" />
+<combo_box.item
+ label="Advanced"
+ name="Advanced"
+ value="" />
+</combo_box>
+</layout_panel>
+<layout_panel
+tab_stop="false"
+follows="right|bottom"
+name="links"
+width="205"
+min_width="205"
+user_resize="false"
+height="80">
+ <text
+follows="right|bottom"
+font="SansSerifSmall"
+text_color="EmphasisColor"
+halign="right"
+height="16"
+top="12"
+right="-10"
+name="create_new_account_text"
+ width="200">
+ Sign up
+ </text>
+<text
+follows="right|bottom"
+font="SansSerifSmall"
+text_color="EmphasisColor"
+halign="right"
+height="16"
+name="forgot_password_text"
+top_pad="12"
+right="-10"
+ width="200">
+ Forgot your username or password?
+</text>
+<text
+follows="right|bottom"
+font="SansSerifSmall"
+text_color="EmphasisColor"
+halign="right"
+height="16"
+name="login_help"
+top_pad="2"
+right="-10"
+ width="200">
+ Need help logging in? </text>
+<!-- <text
+ follows="right|bottom"
+ font="SansSerifSmall"
+ halign="right"
+ height="28"
+ top_pad="2"
+ name="channel_text"
+ width="180"
+ word_wrap="true">
+ [VERSION]
+ </text>-->
+ </layout_panel>
+</layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml
new file mode 100644
index 0000000000..6dc1a1c9b0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_navigation_bar.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="true"
+ bg_opaque_color="MouseGray"
+ follows="left|top|right"
+ height="26"
+ layout="topleft"
+ name="navigation_bar"
+ chrome="true"
+ width="600">
+ <icon
+ follows="all"
+ image_name="NavBar_BG_NoFav_Bevel"
+ mouse_opaque="false"
+ name="bg_icon_no_fav_bevel"
+ scale_image="true"
+ visible="true"
+ left="0"
+ top="0"
+ height="26"
+ width="600"/>
+ <panel
+ background_visible="false"
+ follows="left|top|right"
+ top="3"
+ height="26"
+ layout="topleft"
+ name="navigation_panel"
+ width="600">
+ <pull_button
+follows="left|top"
+direction="down"
+height="23"
+image_overlay="Arrow_Left_Off"
+image_bottom_pad="1"
+layout="topleft"
+left="10"
+name="back_btn"
+tool_tip="Go back to previous location"
+top="2"
+width="31" />
+ <pull_button
+ follows="left|top"
+ direction="down"
+ height="23"
+ image_overlay="Arrow_Right_Off"
+ image_bottom_pad="1"
+ layout="topleft"
+ left_pad="0"
+ name="forward_btn"
+ tool_tip="Go forward one location"
+ top_delta="0"
+ width="31" />
+ <location_input
+ follows="left|right|top"
+ halign="right"
+ height="23"
+ label="Location"
+ layout="topleft"
+ left_pad="7"
+ max_chars="254"
+ mouse_opaque="false"
+ name="location_combo"
+ top_delta="0"
+ width="440">
+ </location_input>
+ <icon follows="right"
+ height="20"
+ width="2"
+ left_pad="2"
+ image_name="Button_Separator"
+ name="separator"
+ top="2"/>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_people.xml b/indra/newview/skins/minimal/xui/en/panel_people.xml
new file mode 100644
index 0000000000..4a72653d76
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_people.xml
@@ -0,0 +1,550 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Side tray panel -->
+<panel
+ default_tab_group="1"
+ follows="all"
+ height="449"
+ label="People"
+ layout="topleft"
+ left="0"
+ min_height="350"
+ name="people_panel"
+ top="0"
+ width="333">
+ <string
+ name="no_recent_people"
+ value="No recent people. Looking for people to hang out with? Try the Destinations button below." />
+ <string
+ name="no_filtered_recent_people"
+ value="No recent people with that name." />
+ <string
+ name="no_one_near"
+ value="No one nearby. Looking for people to hang out with? Try the Destinations button below." />
+ <string
+ name="no_one_filtered_near"
+ value="No one nearby with that name." />
+ <string
+ name="no_friends_online"
+ value="No friends online" />
+ <string
+ name="no_friends"
+ value="No friends" />
+ <string
+ name="no_friends_msg">
+ Right-click on a Resident to add them as a friend.
+Looking for people to hang out with? Try the Destinations button below.
+ </string>
+ <string
+ name="no_filtered_friends_msg">
+ Didn't find what you're looking for? Try the Destinations button below..
+ </string>
+ <string
+ name="people_filter_label"
+ value="Filter People" />
+ <string
+ name="groups_filter_label"
+ value="Filter Groups" />
+ <!--
+ *WORKAROUND: for group_list.no_items_msg & group_list.no_filtered_items_msg attributes.
+ They are not defined as translatable in VLT. See EXT-5931
+ -->
+ <string
+ name="no_filtered_groups_msg"
+ value="Didn't find what you're looking for? Try [secondlife:///app/search/groups/[SEARCH_TERM] Search]." />
+ <string
+ name="no_groups_msg"
+ value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]." />
+ <string
+ name="MiniMapToolTipMsg"
+ value="[REGION](Double-click to open Map, shift-drag to pan)"/>
+ <string
+ name="AltMiniMapToolTipMsg"
+ value="[REGION](Double-click to teleport, shift-drag to pan)"/>
+ <filter_editor
+ follows="left|top|right"
+ height="23"
+ layout="topleft"
+ left="10"
+ label="Filter"
+ max_length="300"
+ name="filter_input"
+ text_color="Black"
+ text_pad_left="10"
+ top="3"
+ width="303" />
+ <tab_container
+ follows="all"
+ height="383"
+ layout="topleft"
+ left="5"
+ name="tabs"
+ tab_group="1"
+ tab_min_width="70"
+ tab_height="30"
+ tab_position="top"
+ top_pad="10"
+ halign="center"
+ width="317">
+ <panel
+ background_opaque="true"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
+ follows="all"
+ height="383"
+ label="NEARBY"
+ layout="topleft"
+ left="0"
+ help_topic="people_nearby_tab"
+ name="nearby_panel"
+ top="0"
+ width="313">
+ <net_map
+ bg_color="NetMapBackgroundColor"
+ follows="top|left|right"
+ layout="topleft"
+ left="3"
+ mouse_opaque="false"
+ name="Net Map"
+ width="307"
+ height="140"
+ top="0"/>
+ <avatar_list
+ allow_select="true"
+ follows="top|left|bottom|right"
+ height="216"
+ ignore_online_status="true"
+ layout="topleft"
+ left="3"
+ multi_select="true"
+ name="avatar_list"
+ top="145"
+ width="307" />
+ <panel
+ background_visible="true"
+ follows="left|right|bottom"
+ height="27"
+ label="bottom_panel"
+ layout="topleft"
+ left="3"
+ name="bottom_panel"
+ top_pad="0"
+ width="313">
+ <icon
+ follows="bottom|left|right"
+ height="25"
+ image_name="Toolbar_Right_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_icon"
+ width="241"
+ />
+ </panel>
+ </panel>
+ <panel
+ background_opaque="true"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
+ follows="all"
+ height="383"
+ label="MY FRIENDS"
+ layout="topleft"
+ left="0"
+ help_topic="people_friends_tab"
+ name="friends_panel"
+ top="0"
+ width="313">
+ <accordion
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ bg_opaque_color="DkGray2"
+ follows="all"
+ height="356"
+ layout="topleft"
+ left="3"
+ name="friends_accordion"
+ top="0"
+ width="307">
+ <accordion_tab
+ layout="topleft"
+ height="172"
+ min_height="150"
+ name="tab_online"
+ title="Online">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ height="172"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="avatars_online"
+ show_permissions_granted="true"
+ top="0"
+ width="307" />
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ height="173"
+ name="tab_all"
+ title="All">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ height="173"
+ layout="topleft"
+ left="0"
+ multi_select="true"
+ name="avatars_all"
+ show_permissions_granted="true"
+ top="0"
+ width="307" />
+ </accordion_tab>
+ </accordion>
+ <panel
+ background_visible="true"
+ follows="left|right|bottom"
+ height="27"
+ label="bottom_panel"
+ layout="topleft"
+ left="3"
+ name="bottom_panel"
+ top_pad="0"
+ width="313">
+
+ <layout_stack
+ animate="false"
+ border_size="0"
+ follows="left|right|bottom"
+ height="25"
+ layout="topleft"
+ orientation="horizontal"
+ top_pad="1"
+ left="0"
+ name="bottom_panel"
+ width="305">
+ <layout_panel
+ auto_resize="true"
+ height="25"
+ layout="topleft"
+ name="dummy_panel"
+ user_resize="false"
+ width="212">
+ <icon
+ follows="bottom|left|right"
+ height="25"
+ image_name="Toolbar_Middle_Off"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="dummy_icon"
+ width="211" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ height="25"
+ layout="topleft"
+ name="trash_btn_panel"
+ user_resize="false"
+ width="31">
+ <dnd_button
+ follows="bottom|left"
+ height="25"
+ image_hover_unselected="Toolbar_Right_Over"
+ image_overlay="TrashItem_Off"
+ image_selected="Toolbar_Right_Selected"
+ image_unselected="Toolbar_Right_Off"
+ left="0"
+ layout="topleft"
+ name="del_btn"
+ tool_tip="Remove selected person from your Friends list"
+ top="0"
+ width="31"/>
+ </layout_panel>
+ </layout_stack><!--
+
+ <button
+ follows="bottom|left"
+ tool_tip="Options"
+ height="25"
+ image_hover_unselected="Toolbar_Left_Over"
+ image_overlay="OptionsMenu_Off"
+ image_selected="Toolbar_Left_Selected"
+ image_unselected="Toolbar_Left_Off"
+ layout="topleft"
+ left="0"
+ name="friends_viewsort_btn"
+ top="1"
+ width="31" />
+ <button
+ follows="bottom|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="AddItem_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="add_btn"
+ tool_tip="Offer friendship to a Resident"
+ width="31" />
+ <icon
+ follows="bottom|left|right"
+ height="25"
+ image_name="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_icon"
+ width="209"
+ />
+ <button
+ follows="bottom|left"
+ height="25"
+ image_hover_unselected="Toolbar_Right_Over"
+ image_overlay="TrashItem_Off"
+ image_selected="Toolbar_Right_Selected"
+ image_unselected="Toolbar_Right_Off"
+ layout="topleft"
+ left_pad="1"
+ name="del_btn"
+ tool_tip="Remove selected person from your Friends list"
+ width="31" />
+ --></panel>
+ <text
+ follows="all"
+ height="450"
+ left="13"
+ name="no_friends_help_text"
+ top="10"
+ width="293"
+ wrap="true" />
+ </panel>
+ <panel
+ background_opaque="true"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
+ follows="all"
+ height="383"
+ label="RECENT"
+ layout="topleft"
+ left="0"
+ help_topic="people_recent_tab"
+ name="recent_panel"
+ top="0"
+ width="313">
+ <avatar_list
+ allow_select="true"
+ follows="all"
+ height="356"
+ layout="topleft"
+ left="3"
+ multi_select="true"
+ name="avatar_list"
+ show_last_interaction_time="true"
+ top="0"
+ width="307" />
+ <panel
+ background_visible="true"
+ follows="left|right|bottom"
+ height="27"
+ label="bottom_panel"
+ layout="topleft"
+ left="0"
+ name="bottom_panel"
+ top_pad="0"
+ width="313">
+ <button
+ follows="bottom|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="AddItem_Off"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="add_friend_btn"
+ tool_tip="Add selected Resident to your friends List"
+ width="31">
+ <commit_callback
+ function="People.addFriend" />
+ </button>
+ <icon
+ follows="bottom|left|right"
+ height="25"
+ image_name="Toolbar_Right_Off"
+ layout="topleft"
+ left_pad="1"
+ name="dummy_icon"
+ width="241"
+ />
+ </panel>
+ </panel>
+ </tab_container>
+ <panel
+ follows="bottom|left|right"
+ height="23"
+ layout="topleft"
+ left="8"
+ top_pad="4"
+ name="button_bar"
+ width="313">
+
+<!--********************************Profile; IM; Call, Share, Teleport********************************-->
+ <layout_stack
+ follows="bottom|left|right"
+ height="23"
+ layout="topleft"
+ name="bottom_bar_ls"
+ left="0"
+ orientation="horizontal"
+ top_pad="0"
+ width="313">
+
+ <layout_panel
+ follows="bottom|left|right"
+ height="23"
+ layout="bottomleft"
+ left="0"
+ name="view_profile_btn_lp"
+ user_resize="false"
+ auto_resize="true"
+ width="68">
+ <button
+ follows="bottom|left|right"
+ height="23"
+ label="Profile"
+ layout="topleft"
+ left="1"
+ name="view_profile_btn"
+ tool_tip="Show picture, groups, and other Residents information"
+ top="0"
+ width="67" />
+ </layout_panel>
+
+ <layout_panel
+ follows="bottom|left|right"
+ height="23"
+ layout="bottomleft"
+ left_pad="3"
+ name="chat_btn_lp"
+ user_resize="false"
+ auto_resize="true"
+ width="41">
+ <button
+ follows="bottom|left|right"
+ left="1"
+ height="23"
+ label="IM"
+ layout="topleft"
+ name="im_btn"
+ tool_tip="Open instant message session"
+ top="0"
+ width="40" />
+ </layout_panel>
+
+ <layout_panel
+ follows="bottom|left|right"
+ height="23"
+ layout="bottomleft"
+ left_pad="3"
+ name="chat_btn_lp"
+ user_resize="false"
+ auto_resize="true"
+ width="77">
+ <button
+ follows="bottom|left|right"
+ left="1"
+ height="23"
+ label="Teleport"
+ layout="topleft"
+ name="teleport_btn"
+ tool_tip="Offer teleport"
+ top="0"
+ width="76" />
+ </layout_panel>
+ </layout_stack>
+
+<!--********************************Group Profile; Group Chat; Group Call buttons************************-->
+ <layout_stack
+ follows="bottom|left|right"
+ height="23"
+ layout="topleft"
+ mouse_opaque="false"
+ name="bottom_bar_ls1"
+ left="0"
+ orientation="horizontal"
+ top="0"
+ width="313">
+ <layout_panel
+ follows="bottom|left|right"
+ height="23"
+ layout="bottomleft"
+ left="0"
+ mouse_opaque="false"
+ name="group_info_btn_lp"
+ user_resize="false"
+ auto_resize="true"
+ width="108">
+ <button
+ follows="bottom|left|right"
+ left="1"
+ height="23"
+ label="Group Profile"
+ layout="topleft"
+ mouse_opaque="false"
+ name="group_info_btn"
+ tool_tip="Show group information"
+ top="0"
+ width="107" />
+ </layout_panel>
+
+ <layout_panel
+ follows="bottom|left|right"
+ height="23"
+ layout="bottomleft"
+ left_pad="3"
+ mouse_opaque="false"
+ name="chat_btn_lp"
+ user_resize="false"
+ auto_resize="true"
+ width="101">
+ <button
+ follows="bottom|left|right"
+ left="1"
+ height="23"
+ label="Group Chat"
+ layout="topleft"
+ mouse_opaque="false"
+ name="chat_btn"
+ tool_tip="Open chat session"
+ top="0"
+ width="100" />
+ </layout_panel>
+
+ <layout_panel
+ follows="bottom|left|right"
+ height="23"
+ layout="bottomleft"
+ left_pad="3"
+ mouse_opaque="false"
+ name="group_call_btn_lp"
+ user_resize="false"
+ auto_resize="true"
+ width="96">
+ <button
+ follows="bottom|left|right"
+ left="1"
+ height="23"
+ label="Group Call"
+ layout="topleft"
+ mouse_opaque="false"
+ name="group_call_btn"
+ tool_tip="Call this group"
+ top="0"
+ width="95" />
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_side_tray_tab_caption.xml b/indra/newview/skins/minimal/xui/en/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..9f2f41ba31
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_side_tray_tab_caption.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bottom="0"
+ follows="left|top|right"
+ height="5"
+ width="333"
+ layout="topleft"
+ left="0"
+ name="sidetray_tab_panel">
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_status_bar.xml b/indra/newview/skins/minimal/xui/en/panel_status_bar.xml
new file mode 100644
index 0000000000..6ccd0e938d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_status_bar.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="true"
+ bg_opaque_color="MouseGray"
+ chrome="true"
+ follows="top|right"
+ height="30"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="status"
+ top="19"
+ tab_stop="false"
+ width="70">
+ <panel.string
+ name="packet_loss_tooltip">
+ Packet Loss
+ </panel.string>
+ <panel.string
+ name="bandwidth_tooltip">
+ Bandwidth
+ </panel.string>
+ <panel.string
+ name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string
+ name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string
+ name="buycurrencylabel">
+ L$ [AMT]
+ </panel.string>
+ <button
+ follows="right|top"
+ height="16"
+ image_selected="Play_Off"
+ image_unselected="Pause_Off"
+ image_pressed="Pause_Press"
+ image_pressed_selected="Play_Press"
+ is_toggle="true"
+ left="15"
+ top="7"
+ name="media_toggle_btn"
+ tool_tip="Start/Stop All Media (Music, Video, Web pages)"
+ width="16" >
+ </button>
+ <button
+ follows="right|top"
+ height="16"
+ image_selected="AudioMute_Off"
+ image_pressed="Audio_Press"
+ image_unselected="Audio_Off"
+ is_toggle="true"
+ left_pad="5"
+ top="8"
+ name="volume_btn"
+ tool_tip="Global Volume Control"
+ width="16" />
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/minimal/xui/en/panel_volume_pulldown.xml
new file mode 100644
index 0000000000..36ad39abe8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/panel_volume_pulldown.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="true"
+ bg_opaque_image="Volume_Background"
+ bg_alpha_image="Volume_Background"
+ border_visible="false"
+ border="false"
+ chrome="true"
+ follows="bottom"
+ height="150"
+ layout="topleft"
+ name="volumepulldown_floater"
+ width="32">
+ <slider
+ control_name="AudioLevelMaster"
+ follows="left|top"
+ left="0"
+ top="1"
+ orientation="vertical"
+ height="140"
+ increment="0.05"
+ initial_value="0.5"
+ layout="topleft"
+ name="mastervolume"
+ show_text="false"
+ slider_label.halign="right"
+ top_pad="2"
+ volume="true">
+ <slider.commit_callback
+ function="Vol.setControlFalse"
+ parameter="MuteAudio" />
+ </slider>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/en/widgets/location_input.xml b/indra/newview/skins/minimal/xui/en/widgets/location_input.xml
new file mode 100644
index 0000000000..fe06a2d816
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/en/widgets/location_input.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!--
+*TODO: Replace hardcoded buttons width/height with getting this info from the button images.
+ Currently that doesn't work because LLUIImage::getWidth/getHeight() return 1 for the images.
+-->
+<location_input font="SansSerifSmall"
+ maturity_help_topic="maturity_rating"
+ add_landmark_hpad="0"
+ icon_hpad="2"
+ allow_text_entry="true"
+ list_position="below"
+ show_text_as_tentative="false"
+ max_chars="20"
+ follows="left|top"
+ allow_new_values="true"
+ >
+ <!-- *NOTE: Tooltips are in strings.xml so they can be localized.
+ See LocationCtrlAddLandmarkTooltip etc. -->
+ <info_button
+ name="Place Information"
+ width="0"
+ height="0"
+ visible="false"
+ left="6"
+ top="20"
+ follows="left|top"
+ hover_glow_amount="0.15" />
+ <add_landmark_button name="Add Landmark"
+ hover_glow_amount="0.15"
+ width="0"
+ height="0"
+ visible="false"
+ follows="right|top"
+ scale_image="false"
+ top="19"
+ left="-3" />
+ <maturity_button
+ name="maturity_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="20"
+ follows="left|top"
+ />
+ <for_sale_button
+ name="for_sale_btn"
+ width="0"
+ height="0"
+ visible="false"
+ follows="right|top"
+ scale_image="false"
+ top="21"
+ />
+ <voice_icon
+ enabled="true"
+ name="voice_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="21"
+ follows="right|top"
+ />
+ <fly_icon
+ name="fly_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="21"
+ follows="right|top"
+ />
+ <push_icon
+ name="push_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="21"
+ follows="right|top"
+ />
+ <build_icon
+ name="build_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="21"
+ follows="right|top"
+ />
+ <scripts_icon
+ name="scripts_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="21"
+ follows="right|top"
+ />
+ <damage_icon
+ name="damage_icon"
+ width="0"
+ height="0"
+ visible="false"
+ top="19"
+ left="2"
+ follows="right|top"
+ />
+ <!-- Default text color is invisible on top of nav bar background -->
+ <damage_text
+ name="damage_text"
+ width="0"
+ height="0"
+ max_length="0"
+ top="17"
+ follows="right|top"
+ halign="right"
+ font="SansSerifSmall"
+ text_color="TextFgColor"
+ />
+ <combo_button
+ name="Location History"
+ label=""
+ pad_right="0"/>
+ <combo_list
+ bg_writeable_color="MenuDefaultBgColor"
+ page_lines="10"
+ scroll_bar_bg_visible="true" />
+ <combo_editor name="Combo Text Entry"
+ text_pad_left="4"
+ select_on_focus="false"
+ font="SansSerifSmall"
+ bevel_style="none"
+ border_style="line"
+ border.border_thickness="0" />
+</location_input>
diff --git a/indra/newview/skins/minimal/xui/es/floater_camera.xml b/indra/newview/skins/minimal/xui/es/floater_camera.xml
new file mode 100644
index 0000000000..ccf3d4bf91
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/floater_camera.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
+ Girar la cámara alrededor de lo enfocado
+ </floater.string>
+ <floater.string name="zoom_tooltip">
+ Hacer zoom con la cámara en lo enfocado
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Mover la cámara arriba y abajo, izquierda y derecha
+ </floater.string>
+ <floater.string name="camera_modes_title">
+ Modos de cámara
+ </floater.string>
+ <floater.string name="pan_mode_title">
+ Orbital - Zoom - Panóramica
+ </floater.string>
+ <floater.string name="presets_mode_title">
+ Vistas predefinidas
+ </floater.string>
+ <floater.string name="free_mode_title">
+ Centrar el objeto
+ </floater.string>
+ <panel name="controls">
+ <panel name="preset_views_list">
+ <panel_camera_item name="front_view">
+ <panel_camera_item.text name="front_view_text">
+ De frente
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="group_view">
+ <panel_camera_item.text name="side_view_text">
+ Vista lateral
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="rear_view">
+ <panel_camera_item.text name="rear_view_text">
+ Desde detrás
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="camera_modes_list">
+ <panel_camera_item name="object_view">
+ <panel_camera_item.text name="object_view_text">
+ Vista de objeto
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="mouselook_view">
+ <panel_camera_item.text name="mouselook_view_text">
+ Vista subjetiva
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="zoom" tool_tip="Hacer zoom con la cámara en lo enfocado">
+ <joystick_rotate name="cam_rotate_stick" tool_tip="La cámara gira alrededor del punto de vista"/>
+ <slider_bar name="zoom_slider" tool_tip="Hacer zoom en lo enfocado"/>
+ <joystick_track name="cam_track_stick" tool_tip="Mueve la cámara arriba y abajo, a izquierda y derecha"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="presets_btn" tool_tip="Vistas predefinidas"/>
+ <button label="" name="pan_btn" tool_tip="Orbital - Zoom - Panóramica"/>
+ <button label="" name="avatarview_btn" tool_tip="Modos de cámara"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/floater_help_browser.xml b/indra/newview/skins/minimal/xui/es/floater_help_browser.xml
new file mode 100644
index 0000000000..67590ebfbb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/floater_help_browser.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="INDICACIONES">
+ <floater.string name="loading_text">
+ Cargando...
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls"/>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/floater_media_browser.xml b/indra/newview/skins/minimal/xui/es/floater_media_browser.xml
new file mode 100644
index 0000000000..a7086c2d6d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/floater_media_browser.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="EXPLORADOR DE MEDIA">
+ <floater.string name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button label="Atrás" name="back"/>
+ <button label="Adelante" name="forward"/>
+ <button label="Recargar" name="reload"/>
+ <button label="Ir" name="go"/>
+ </layout_panel>
+ <layout_panel name="time_controls">
+ <button label="rebobinar" name="rewind"/>
+ <button label="parar" name="stop"/>
+ <button label="avanzar" name="seek"/>
+ </layout_panel>
+ <layout_panel name="parcel_owner_controls">
+ <button label="Enviar a la parcela la página actual" name="assign"/>
+ </layout_panel>
+ <layout_panel name="external_controls">
+ <button label="Abrir en mi propio navegador" name="open_browser"/>
+ <check_box label="Abrir siempre en mi propio navegador" name="open_always"/>
+ <button label="Cerrar" name="close"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/floater_nearby_chat.xml b/indra/newview/skins/minimal/xui/es/floater_nearby_chat.xml
new file mode 100644
index 0000000000..1fee9ab056
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/floater_nearby_chat.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="CHAT">
+ <check_box label="Traducir chat (mediante Google)" name="translate_chat_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/floater_web_content.xml b/indra/newview/skins/minimal/xui/es/floater_web_content.xml
new file mode 100644
index 0000000000..b012809679
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/floater_web_content.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_web_content" title="">
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button name="back" tool_tip="Navegar hacia atrás"/>
+ <button name="forward" tool_tip="Navegar hacia adelante"/>
+ <button name="stop" tool_tip="Parar navegación"/>
+ <button name="reload" tool_tip="Recargar página"/>
+ <combo_box name="address" tool_tip="Escribe la URL aquí"/>
+ <icon name="media_secure_lock_flag" tool_tip="Navegación segura"/>
+ <button name="popexternal" tool_tip="Abrir la URL actual en tu explorador de escritorio"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/inspect_avatar.xml b/indra/newview/skins/minimal/xui/es/inspect_avatar.xml
new file mode 100644
index 0000000000..1d70fa6a90
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/inspect_avatar.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [AGE]
+ </string>
+ <string name="Details">
+ [SL_PROFILE]
+ </string>
+ <text name="user_details">
+ Ésta es mi descripción de Second Life que, por cierto, me encanta. Pero, por lo que sea, me he enrollado más de la cuenta y la descripción es larguísima.
+ </text>
+ <slider name="volume_slider" tool_tip="Volumen de la voz" value="0.5"/>
+ <button label="Añadir como amigo" name="add_friend_btn"/>
+ <button label="MI" name="im_btn"/>
+ <button label="Perfil" name="view_profile_btn"/>
+ <panel name="moderator_panel">
+ <button label="Desactivar la voz" name="disable_voice"/>
+ <button label="Activar la voz" name="enable_voice"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/inspect_object.xml b/indra/newview/skins/minimal/xui/es/inspect_object.xml
new file mode 100644
index 0000000000..d608b4a0f7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/inspect_object.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ Por [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ Por [CREATOR]
+Propietario [OWNER]
+ </string>
+ <string name="Price">
+ [AMOUNT] L$
+ </string>
+ <string name="PriceFree">
+ ¡Gratis!
+ </string>
+ <string name="Touch">
+ Tocar
+ </string>
+ <string name="Sit">
+ Sentarme
+ </string>
+ <text name="object_name" value="Test Object Name That Is actually two lines and Really Long"/>
+ <text name="price_text">
+ 30.000 L$
+ </text>
+ <text name="object_description">
+ This is a really long description for an object being as how it is at least 80 characters in length and so but maybe more like 120 at this point. Who knows, really?
+ </text>
+ <button label="Comprar" name="buy_btn"/>
+ <button label="Pagar" name="pay_btn"/>
+ <button label="Coger una copia" name="take_free_copy_btn"/>
+ <button label="Tocar" name="touch_btn"/>
+ <button label="Sentarme" name="sit_btn"/>
+ <button label="Abrir" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="Navegación segura"/>
+ <button label="Más" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/es/menu_add_wearable_gear.xml b/indra/newview/skins/minimal/xui/es/menu_add_wearable_gear.xml
new file mode 100644
index 0000000000..f2367c72a3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_add_wearable_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Add Wearable Gear Menu">
+ <menu_item_check label="Ordenar por los más recientes" name="sort_by_most_recent"/>
+ <menu_item_check label="Ordenar alfabéticamente" name="sort_by_name"/>
+ <menu_item_check label="Ordenar por tipo" name="sort_by_type"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_attachment_other.xml b/indra/newview/skins/minimal/xui/es/menu_attachment_other.xml
new file mode 100644
index 0000000000..00bdb74881
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_attachment_other.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_avatar_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Ver el perfil" name="Profile..."/>
+ <menu_item_call label="Añadir como amigo" name="Add Friend"/>
+ <menu_item_call label="MI" name="Send IM..."/>
+ <menu_item_call label="Llamada" name="Call"/>
+ <menu_item_call label="Invitar al grupo" name="Invite..."/>
+ <menu_item_call label="Ignorar" name="Avatar Mute"/>
+ <menu_item_call label="Denunciar" name="abuse"/>
+ <menu_item_call label="Congelar" name="Freeze..."/>
+ <menu_item_call label="Expulsar" name="Eject..."/>
+ <menu_item_call label="Depurar las texturas" name="Debug..."/>
+ <menu_item_call label="Acercar el zoom" name="Zoom In"/>
+ <menu_item_call label="Pagar" name="Pay..."/>
+ <menu_item_call label="Perfil del objeto" name="Object Inspect"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_attachment_self.xml b/indra/newview/skins/minimal/xui/es/menu_attachment_self.xml
new file mode 100644
index 0000000000..ab76c92d65
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_attachment_self.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Attachment Pie">
+ <menu_item_call label="Tocar" name="Attachment Object Touch"/>
+ <menu_item_call label="Editar" name="Edit..."/>
+ <menu_item_call label="Quitar" name="Detach"/>
+ <menu_item_call label="Sentarte" name="Sit Down Here"/>
+ <menu_item_call label="Levantarme" name="Stand Up"/>
+ <menu_item_call label="Cambiar vestuario" name="Change Outfit"/>
+ <menu_item_call label="Editar mi vestuario" name="Edit Outfit"/>
+ <menu_item_call label="Editar mi anatomía" name="Edit My Shape"/>
+ <menu_item_call label="Mis amigos" name="Friends..."/>
+ <menu_item_call label="Mis grupos" name="Groups..."/>
+ <menu_item_call label="Mi perfil" name="Profile..."/>
+ <menu_item_call label="Depurar las texturas" name="Debug..."/>
+ <menu_item_call label="Soltar" name="Drop"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_avatar_icon.xml b/indra/newview/skins/minimal/xui/es/menu_avatar_icon.xml
new file mode 100644
index 0000000000..fe7331a108
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="Ver el perfil" name="Show Profile"/>
+ <menu_item_call label="Enviar un MI..." name="Send IM"/>
+ <menu_item_call label="Añadir como amigo..." name="Add Friend"/>
+ <menu_item_call label="Quitar de los amigos..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_avatar_other.xml b/indra/newview/skins/minimal/xui/es/menu_avatar_other.xml
new file mode 100644
index 0000000000..7df2d7c4e0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_avatar_other.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Ver el perfil" name="Profile..."/>
+ <menu_item_call label="Añadir como amigo" name="Add Friend"/>
+ <menu_item_call label="MI" name="Send IM..."/>
+ <menu_item_call label="Llamada" name="Call"/>
+ <menu_item_call label="Invitar al grupo" name="Invite..."/>
+ <menu_item_call label="Ignorar" name="Avatar Mute"/>
+ <menu_item_call label="Denunciar" name="abuse"/>
+ <menu_item_call label="Congelar" name="Freeze..."/>
+ <menu_item_call label="Expulsar" name="Eject..."/>
+ <menu_item_call label="Depurar las texturas" name="Debug..."/>
+ <menu_item_call label="Acercar el zoom" name="Zoom In"/>
+ <menu_item_call label="Pagar" name="Pay..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_avatar_self.xml b/indra/newview/skins/minimal/xui/es/menu_avatar_self.xml
new file mode 100644
index 0000000000..50f8384b0f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_avatar_self.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Self Pie">
+ <menu_item_call label="Sentarte" name="Sit Down Here"/>
+ <menu_item_call label="Levantarme" name="Stand Up"/>
+ <context_menu label="Quitarme" name="Take Off &gt;">
+ <context_menu label="Ropas" name="Clothes &gt;">
+ <menu_item_call label="Camisa" name="Shirt"/>
+ <menu_item_call label="Pantalón" name="Pants"/>
+ <menu_item_call label="Falda" name="Skirt"/>
+ <menu_item_call label="Zapatos" name="Shoes"/>
+ <menu_item_call label="Calcetines" name="Socks"/>
+ <menu_item_call label="Chaqueta" name="Jacket"/>
+ <menu_item_call label="Guantes" name="Gloves"/>
+ <menu_item_call label="Camiseta" name="Self Undershirt"/>
+ <menu_item_call label="Ropa interior" name="Self Underpants"/>
+ <menu_item_call label="Tatuaje" name="Self Tattoo"/>
+ <menu_item_call label="Alfa" name="Self Alpha"/>
+ <menu_item_call label="Toda la ropa" name="All Clothes"/>
+ </context_menu>
+ <context_menu label="HUD" name="Object Detach HUD"/>
+ <context_menu label="Quitar" name="Object Detach"/>
+ <menu_item_call label="Quitarse todo" name="Detach All"/>
+ </context_menu>
+ <menu_item_call label="Cambiar vestuario" name="Chenge Outfit"/>
+ <menu_item_call label="Editar mi vestuario" name="Edit Outfit"/>
+ <menu_item_call label="Editar mi anatomía" name="Edit My Shape"/>
+ <menu_item_call label="Mis amigos" name="Friends..."/>
+ <menu_item_call label="Mis grupos" name="Groups..."/>
+ <menu_item_call label="Mi perfil" name="Profile..."/>
+ <menu_item_call label="Depurar las texturas" name="Debug..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_bottomtray.xml b/indra/newview/skins/minimal/xui/es/menu_bottomtray.xml
new file mode 100644
index 0000000000..62683f3076
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_bottomtray.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="Botón Gestos" name="ShowGestureButton"/>
+ <menu_item_check label="Botón Moverse" name="ShowMoveButton"/>
+ <menu_item_check label="Botón Vista" name="ShowCameraButton"/>
+ <menu_item_check label="Botón Foto" name="ShowSnapshotButton"/>
+ <menu_item_check label="Botón Barra lateral" name="ShowSidebarButton"/>
+ <menu_item_check label="Botón Construir" name="ShowBuildButton"/>
+ <menu_item_check label="Botón Buscar" name="ShowSearchButton"/>
+ <menu_item_check label="Botón Mapa" name="ShowWorldMapButton"/>
+ <menu_item_check label="Botón Minimapa" name="ShowMiniMapButton"/>
+ <menu_item_call label="Cortar" name="NearbyChatBar_Cut"/>
+ <menu_item_call label="Copiar" name="NearbyChatBar_Copy"/>
+ <menu_item_call label="Pegar" name="NearbyChatBar_Paste"/>
+ <menu_item_call label="Borrar" name="NearbyChatBar_Delete"/>
+ <menu_item_call label="Seleccionar todo" name="NearbyChatBar_Select_All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_cof_attachment.xml b/indra/newview/skins/minimal/xui/es/menu_cof_attachment.xml
new file mode 100644
index 0000000000..7541530601
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_cof_attachment.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Attachment">
+ <menu_item_call label="Quitar" name="detach"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_cof_body_part.xml b/indra/newview/skins/minimal/xui/es/menu_cof_body_part.xml
new file mode 100644
index 0000000000..56b95bdc3b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_cof_body_part.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Body">
+ <menu_item_call label="Reemplazar" name="replace"/>
+ <menu_item_call label="Editar" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_cof_clothing.xml b/indra/newview/skins/minimal/xui/es/menu_cof_clothing.xml
new file mode 100644
index 0000000000..3c0c588284
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_cof_clothing.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Clothing">
+ <menu_item_call label="Quitarme" name="take_off"/>
+ <menu_item_call label="Editar" name="edit"/>
+ <menu_item_call label="Reemplazar" name="replace"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_cof_gear.xml b/indra/newview/skins/minimal/xui/es/menu_cof_gear.xml
new file mode 100644
index 0000000000..ff8ad0977a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_cof_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear COF">
+ <menu label="Ropas nuevas" name="COF.Gear.New_Clothes"/>
+ <menu label="Nuevas partes del cuerpo" name="COF.Geear.New_Body_Parts"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_edit.xml b/indra/newview/skins/minimal/xui/es/menu_edit.xml
new file mode 100644
index 0000000000..96fc9d8881
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_edit.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu label="Editar" name="Edit">
+ <menu_item_call label="Deshacer" name="Undo"/>
+ <menu_item_call label="Rehacer" name="Redo"/>
+ <menu_item_call label="Cortar" name="Cut"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Pegar" name="Paste"/>
+ <menu_item_call label="Borrar" name="Delete"/>
+ <menu_item_call label="Duplicar" name="Duplicate"/>
+ <menu_item_call label="Seleccionar todo" name="Select All"/>
+ <menu_item_call label="Deseleccionar" name="Deselect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_favorites.xml b/indra/newview/skins/minimal/xui/es/menu_favorites.xml
new file mode 100644
index 0000000000..c8a7858ddb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Teleportarse" name="Teleport To Landmark"/>
+ <menu_item_call label="Ver/Editar el hito" name="Landmark Open"/>
+ <menu_item_call label="Copiar la SLurl" name="Copy slurl"/>
+ <menu_item_call label="Mostrar en el mapa" name="Show On Map"/>
+ <menu_item_call label="Copiar" name="Landmark Copy"/>
+ <menu_item_call label="Pegar" name="Landmark Paste"/>
+ <menu_item_call label="Borrar" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_gesture_gear.xml b/indra/newview/skins/minimal/xui/es/menu_gesture_gear.xml
new file mode 100644
index 0000000000..24706eb2c8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="Añadir a / Quitar de los favoritos" name="activate"/>
+ <menu_item_call label="Copiar" name="copy_gesture"/>
+ <menu_item_call label="Pegar" name="paste"/>
+ <menu_item_call label="Copiar la UUID" name="copy_uuid"/>
+ <menu_item_call label="Añadir al vestuario actual" name="save_to_outfit"/>
+ <menu_item_call label="Editar" name="edit_gesture"/>
+ <menu_item_call label="Inspeccionar" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_group_plus.xml b/indra/newview/skins/minimal/xui/es/menu_group_plus.xml
new file mode 100644
index 0000000000..6b26ba42c4
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Entrar al grupo..." name="item_join"/>
+ <menu_item_call label="Grupo nuevo..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_hide_navbar.xml b/indra/newview/skins/minimal/xui/es/menu_hide_navbar.xml
new file mode 100644
index 0000000000..22a1873234
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_hide_navbar.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="Mostrar la barra de navegación" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="Mostrar la barra de favoritos" name="ShowNavbarFavoritesPanel"/>
+ <menu_item_check label="Mostrar mini-barra de ubicación" name="ShowMiniLocationPanel"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_im_well_button.xml b/indra/newview/skins/minimal/xui/es/menu_im_well_button.xml
new file mode 100644
index 0000000000..c8f6c217cc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_im_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="IM Well Button Context Menu">
+ <menu_item_call label="Cerrar todo" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_imchiclet_adhoc.xml b/indra/newview/skins/minimal/xui/es/menu_imchiclet_adhoc.xml
new file mode 100644
index 0000000000..e11e9bdc58
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_imchiclet_adhoc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet AdHoc Menu">
+ <menu_item_call label="Acabar la sesión" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_imchiclet_group.xml b/indra/newview/skins/minimal/xui/es/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..a5e60ea40b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="Información del grupo" name="Show Profile"/>
+ <menu_item_call label="Mostrar la sesión" name="Chat"/>
+ <menu_item_call label="Acabar la sesión" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_imchiclet_p2p.xml b/indra/newview/skins/minimal/xui/es/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..492801026c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="Ver el perfil" name="Show Profile"/>
+ <menu_item_call label="Añadir como amigo" name="Add Friend"/>
+ <menu_item_call label="Mostrar la sesión" name="Send IM"/>
+ <menu_item_call label="Acabar la sesión" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/es/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..ebe33cea11
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<toggleable_menu name="Gear Menu">
+ <menu_item_call label="Ver el perfil" name="view_profile"/>
+ <menu_item_call label="Añadir como amigo" name="add_friend"/>
+ <menu_item_call label="MI" name="im"/>
+ <menu_item_call label="Teleportarse" name="teleport"/>
+ <menu_item_call label="Ignorar" name="block"/>
+ <menu_item_call label="Designorar" name="unblock"/>
+ <menu_item_call label="Denunciar" name="report"/>
+ <menu_item_call label="Congelar" name="freeze"/>
+ <menu_item_call label="Expulsar" name="eject"/>
+ <menu_item_call label="Expulsar" name="kick"/>
+ <menu_item_call label="CSR" name="csr"/>
+ <menu_item_call label="Depurar las texturas" name="debug"/>
+ <menu_item_call label="Encontrar en el mapa" name="find_on_map"/>
+ <menu_item_call label="Acercar el zoom" name="zoom_in"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inspect_object_gear.xml b/indra/newview/skins/minimal/xui/es/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..bcdc25894f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inspect_object_gear.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Tocar" name="touch"/>
+ <menu_item_call label="Sentarse" name="sit"/>
+ <menu_item_call label="Pagar" name="pay"/>
+ <menu_item_call label="Comprar" name="buy"/>
+ <menu_item_call label="Tomar" name="take"/>
+ <menu_item_call label="Coger una copia" name="take_copy"/>
+ <menu_item_call label="Abrir" name="open"/>
+ <menu_item_call label="Editar" name="edit"/>
+ <menu_item_call label="Ponerse" name="wear"/>
+ <menu_item_call label="Añadir" name="add"/>
+ <menu_item_call label="Denunciar" name="report"/>
+ <menu_item_call label="Ignorar" name="block"/>
+ <menu_item_call label="Acercar el zoom" name="zoom_in"/>
+ <menu_item_call label="Quitar" name="remove"/>
+ <menu_item_call label="Más información" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inspect_self_gear.xml b/indra/newview/skins/minimal/xui/es/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..1a49efb9d0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="Self Pie">
+ <menu_item_call label="Sentarme" name="Sit Down Here"/>
+ <menu_item_call label="Levantarme" name="Stand Up"/>
+ <menu_item_call label="Mis amigos" name="Friends..."/>
+ <menu_item_call label="Mi perfil" name="Profile..."/>
+ <menu_item_call label="Depurar texturas" name="Debug..."/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inv_offer_chiclet.xml b/indra/newview/skins/minimal/xui/es/menu_inv_offer_chiclet.xml
new file mode 100644
index 0000000000..20d99afde1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inv_offer_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="InvOfferChiclet Menu">
+ <menu_item_call label="Cerrar" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inventory.xml b/indra/newview/skins/minimal/xui/es/menu_inventory.xml
new file mode 100644
index 0000000000..94ee162bbc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inventory.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Compartir" name="Share"/>
+ <menu_item_call label="Comprar" name="Task Buy"/>
+ <menu_item_call label="Abrir" name="Task Open"/>
+ <menu_item_call label="Ejecutar" name="Task Play"/>
+ <menu_item_call label="Propiedades" name="Task Properties"/>
+ <menu_item_call label="Renombrar" name="Task Rename"/>
+ <menu_item_call label="Borrar" name="Task Remove"/>
+ <menu_item_call label="Vaciar la papelera" name="Empty Trash"/>
+ <menu_item_call label="Vaciar Objetos Perdidos" name="Empty Lost And Found"/>
+ <menu_item_call label="Carpeta nueva" name="New Folder"/>
+ <menu_item_call label="Script nuevo" name="New Script"/>
+ <menu_item_call label="Nota nueva" name="New Note"/>
+ <menu_item_call label="Gesto nuevo" name="New Gesture"/>
+ <menu label="Ropas nuevas" name="New Clothes">
+ <menu_item_call label="Camisa nueva" name="New Shirt"/>
+ <menu_item_call label="Pantalones nuevos" name="New Pants"/>
+ <menu_item_call label="Zapatos nuevos" name="New Shoes"/>
+ <menu_item_call label="Calcetines nuevos" name="New Socks"/>
+ <menu_item_call label="Chaqueta nueva" name="New Jacket"/>
+ <menu_item_call label="Falda nueva" name="New Skirt"/>
+ <menu_item_call label="Guantes nuevos" name="New Gloves"/>
+ <menu_item_call label="Camiseta nueva" name="New Undershirt"/>
+ <menu_item_call label="Ropa interior nueva" name="New Underpants"/>
+ <menu_item_call label="Nueva capa Alpha" name="New Alpha Mask"/>
+ <menu_item_call label="Tatuaje nuevo" name="New Tattoo"/>
+ </menu>
+ <menu label="Nuevas partes del cuerpo" name="New Body Parts">
+ <menu_item_call label="Forma nueva" name="New Shape"/>
+ <menu_item_call label="Piel nueva" name="New Skin"/>
+ <menu_item_call label="Pelo nuevo" name="New Hair"/>
+ <menu_item_call label="Ojos nuevos" name="New Eyes"/>
+ </menu>
+ <menu label="Change Type" name="Change Type">
+ <menu_item_call label="Por defecto" name="Default"/>
+ <menu_item_call label="Guantes" name="Gloves"/>
+ <menu_item_call label="Chaqueta" name="Jacket"/>
+ <menu_item_call label="Pantalón" name="Pants"/>
+ <menu_item_call label="Forma" name="Shape"/>
+ <menu_item_call label="Zapatos" name="Shoes"/>
+ <menu_item_call label="Camisa" name="Shirt"/>
+ <menu_item_call label="Falda" name="Skirt"/>
+ <menu_item_call label="Ropa interior" name="Underpants"/>
+ <menu_item_call label="Camiseta" name="Undershirt"/>
+ </menu>
+ <menu_item_call label="Teleportar" name="Landmark Open"/>
+ <menu_item_call label="Abrir" name="Animation Open"/>
+ <menu_item_call label="Abrir" name="Sound Open"/>
+ <menu_item_call label="Reemplazar el vestuario" name="Replace Outfit"/>
+ <menu_item_call label="Añadir al vestuario" name="Add To Outfit"/>
+ <menu_item_call label="Quitar del vestuario actual" name="Remove From Outfit"/>
+ <menu_item_call label="Encontrar el original" name="Find Original"/>
+ <menu_item_call label="Eliminar el ítem" name="Purge Item"/>
+ <menu_item_call label="Restaurar el ítem" name="Restore Item"/>
+ <menu_item_call label="Abrir" name="Open"/>
+ <menu_item_call label="Abrir original" name="Open Original"/>
+ <menu_item_call label="Propiedades" name="Properties"/>
+ <menu_item_call label="Renombrar" name="Rename"/>
+ <menu_item_call label="Copiar la UUID" name="Copy Asset UUID"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Pegar" name="Paste"/>
+ <menu_item_call label="Pegar como enlace" name="Paste As Link"/>
+ <menu_item_call label="Borrar" name="Remove Link"/>
+ <menu_item_call label="Borrar" name="Delete"/>
+ <menu_item_call label="Borrar carpeta del sistema" name="Delete System Folder"/>
+ <menu_item_call label="Empezar multiconferencia" name="Conference Chat Folder"/>
+ <menu_item_call label="Escuchar" name="Sound Play"/>
+ <menu_item_call label="Acerca del hito" name="About Landmark"/>
+ <menu_item_call label="Escuchar en el mundo" name="Animation Play"/>
+ <menu_item_call label="Ejecutarla para usted" name="Animation Audition"/>
+ <menu_item_call label="Enviar un mensaje instantáneo" name="Send Instant Message"/>
+ <menu_item_call label="Ofrecer teleporte..." name="Offer Teleport..."/>
+ <menu_item_call label="Empezar multiconferencia" name="Conference Chat"/>
+ <menu_item_call label="Activar" name="Activate"/>
+ <menu_item_call label="Desactivar" name="Deactivate"/>
+ <menu_item_call label="Guardar como" name="Save As"/>
+ <menu_item_call label="Quitarse" name="Detach From Yourself"/>
+ <menu_item_call label="Ponerme" name="Wearable And Object Wear"/>
+ <menu label="Anexar a" name="Attach To"/>
+ <menu label="Anexar como HUD" name="Attach To HUD"/>
+ <menu_item_call label="Editar" name="Wearable Edit"/>
+ <menu_item_call label="Añadir" name="Wearable Add"/>
+ <menu_item_call label="Quitarse" name="Take Off"/>
+ <menu_item_call label="--sin opciones--" name="--no options--"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inventory_add.xml b/indra/newview/skins/minimal/xui/es/menu_inventory_add.xml
new file mode 100644
index 0000000000..ba106e8335
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inventory_add.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Subir" name="upload">
+ <menu_item_call label="Imagen ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Sonido ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animación ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Masivo ([COST] L$ por archivo)..." name="Bulk Upload"/>
+ <menu_item_call label="Configurar los permisos por defecto de subida" name="perm prefs"/>
+ </menu>
+ <menu_item_call label="Carpeta nueva" name="New Folder"/>
+ <menu_item_call label="Script nuevo" name="New Script"/>
+ <menu_item_call label="Nota nueva" name="New Note"/>
+ <menu_item_call label="Gesto nuevo" name="New Gesture"/>
+ <menu label="Ropas nuevas" name="New Clothes">
+ <menu_item_call label="Camisa nueva" name="New Shirt"/>
+ <menu_item_call label="Pantalón nuevo" name="New Pants"/>
+ <menu_item_call label="Zapatos nuevos" name="New Shoes"/>
+ <menu_item_call label="Calcetines nuevos" name="New Socks"/>
+ <menu_item_call label="Chaqueta nueva" name="New Jacket"/>
+ <menu_item_call label="Falda nueva" name="New Skirt"/>
+ <menu_item_call label="Guantes nuevos" name="New Gloves"/>
+ <menu_item_call label="Camiseta nueva" name="New Undershirt"/>
+ <menu_item_call label="Ropa interior nueva" name="New Underpants"/>
+ <menu_item_call label="Nueva Alfa" name="New Alpha"/>
+ <menu_item_call label="Tatuaje nuevo" name="New Tattoo"/>
+ </menu>
+ <menu label="Nuevas partes del cuerpo" name="New Body Parts">
+ <menu_item_call label="Forma nueva" name="New Shape"/>
+ <menu_item_call label="Piel nueva" name="New Skin"/>
+ <menu_item_call label="Pelo nuevo" name="New Hair"/>
+ <menu_item_call label="Ojos nuevos" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_inventory_gear_default.xml b/indra/newview/skins/minimal/xui/es/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..8e498fefba
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_inventory_gear_default.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_gear_default">
+ <menu_item_call label="Nueva ventana del inventario" name="new_window"/>
+ <menu_item_check label="Ordenar alfabéticamente" name="sort_by_name"/>
+ <menu_item_check label="Ordenar por los más recientes" name="sort_by_recent"/>
+ <menu_item_check label="Las carpetas del sistema, arriba" name="sort_system_folders_to_top"/>
+ <menu_item_call label="Ver los filtros" name="show_filters"/>
+ <menu_item_call label="Restablecer los filtros" name="reset_filters"/>
+ <menu_item_call label="Cerrar todas las carpetas" name="close_folders"/>
+ <menu_item_call label="Vaciar Objetos Perdidos" name="empty_lostnfound"/>
+ <menu_item_call label="Guardar la textura como" name="Save Texture As"/>
+ <menu_item_call label="Compartir" name="Share"/>
+ <menu_item_call label="Encontrar el original" name="Find Original"/>
+ <menu_item_call label="Encontrar todos los enlazados" name="Find All Links"/>
+ <menu_item_call label="Vaciar la Papelera" name="empty_trash"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_land.xml b/indra/newview/skins/minimal/xui/es/menu_land.xml
new file mode 100644
index 0000000000..b0f15be1b6
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_land.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Land Pie">
+ <menu_item_call label="Acerca del terreno" name="Place Information..."/>
+ <menu_item_call label="Sentarme aquí" name="Sit Here"/>
+ <menu_item_call label="Comprar este terreno" name="Land Buy"/>
+ <menu_item_call label="Comprar un pase" name="Land Buy Pass"/>
+ <menu_item_call label="Construir" name="Create"/>
+ <menu_item_call label="Modificar el terreno" name="Edit Terrain"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_landmark.xml b/indra/newview/skins/minimal/xui/es/menu_landmark.xml
new file mode 100644
index 0000000000..f69b1539b8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="Copiar la SLurl" name="copy"/>
+ <menu_item_call label="Borrar" name="delete"/>
+ <menu_item_call label="Crear un Destacado" name="pick"/>
+ <menu_item_call label="Añadir a la barra de favoritos" name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_login.xml b/indra/newview/skins/minimal/xui/es/menu_login.xml
new file mode 100644
index 0000000000..c27d624732
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_login.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Login Menu">
+ <menu label="Yo" name="File">
+ <menu_item_call label="Preferencias" name="Preferences..."/>
+ <menu_item_call label="Salir de [APP_NAME]" name="Quit"/>
+ </menu>
+ <menu label="Ayuda" name="Help">
+ <menu_item_call label="Ayuda de [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="Acerca de [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu_item_check label="Mostrar el menú &apos;Debug&apos;" name="Show Debug Menu"/>
+ <menu label="Depurar" name="Debug">
+ <menu_item_call label="Mostrar las configuraciones del depurador" name="Debug Settings"/>
+ <menu_item_call label="Configuraciones del Visor/Color" name="UI/Color Settings"/>
+ <menu label="Pruebas de la interfaz" name="UI Tests"/>
+ <menu_item_call label="Definir el tamaño de la ventana..." name="Set Window Size..."/>
+ <menu_item_call label="Mostrar los &apos;TOS&apos;" name="TOS"/>
+ <menu_item_call label="Mostrar mensaje crítico" name="Critical"/>
+ <menu_item_call label="Prueba de navegadores de medios" name="Web Browser Test"/>
+ <menu_item_call label="Prueba de ventanas de contenidos web" name="Web Content Floater Test"/>
+ <menu_item_check label="Mostrar el selector de Grid" name="Show Grid Picker"/>
+ <menu_item_call label="Mostrar la consola de notificaciones" name="Show Notifications Console"/>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/es/menu_mini_map.xml b/indra/newview/skins/minimal/xui/es/menu_mini_map.xml
new file mode 100644
index 0000000000..07d1b08572
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_mini_map.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Zoom cerca" name="Zoom Close"/>
+ <menu_item_call label="Zoom medio" name="Zoom Medium"/>
+ <menu_item_call label="Zoom lejos" name="Zoom Far"/>
+ <menu_item_call label="Zoom por defecto" name="Zoom Default"/>
+ <menu_item_check label="Girar el mapa" name="Rotate Map"/>
+ <menu_item_check label="Centrar automáticamente" name="Auto Center"/>
+ <menu_item_call label="Parar la búsqueda" name="Stop Tracking"/>
+ <menu_item_call label="Mapa del mundo" name="World Map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_navbar.xml b/indra/newview/skins/minimal/xui/es/menu_navbar.xml
new file mode 100644
index 0000000000..63e5468020
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="Mostrar las coordenadas" name="Show Coordinates"/>
+ <menu_item_check label="Mostrar las propiedades de la parcela" name="Show Parcel Properties"/>
+ <menu_item_call label="Hito" name="Landmark"/>
+ <menu_item_call label="Cortar" name="Cut"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Pegar" name="Paste"/>
+ <menu_item_call label="Borrar" name="Delete"/>
+ <menu_item_call label="Seleccionar todo" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_nearby_chat.xml b/indra/newview/skins/minimal/xui/es/menu_nearby_chat.xml
new file mode 100644
index 0000000000..94b281b6c7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="Mostrar la gente que está cerca..." name="nearby_people"/>
+ <menu_item_check label="Ver el texto ignorado" name="muted_text"/>
+ <menu_item_check label="Mostrar los iconos del amigo" name="show_buddy_icons"/>
+ <menu_item_check label="Mostrar los nombres" name="show_names"/>
+ <menu_item_check label="Mostrar los iconos y los nombres" name="show_icons_and_names"/>
+ <menu_item_call label="Tamaño de la fuente" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_notification_well_button.xml b/indra/newview/skins/minimal/xui/es/menu_notification_well_button.xml
new file mode 100644
index 0000000000..0562d35be7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_notification_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Notification Well Button Context Menu">
+ <menu_item_call label="Cerrar todo" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_object.xml b/indra/newview/skins/minimal/xui/es/menu_object.xml
new file mode 100644
index 0000000000..06121e0c09
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_object.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Object Pie">
+ <menu_item_call label="Tocar" name="Object Touch">
+ <menu_item_call.on_enable name="EnableTouch" parameter="Tocar"/>
+ </menu_item_call>
+ <menu_item_call label="Editar" name="Edit..."/>
+ <menu_item_call label="Construir" name="Build"/>
+ <menu_item_call label="Abrir" name="Open"/>
+ <menu_item_call label="Sentarme aquí" name="Object Sit"/>
+ <menu_item_call label="Levantarme" name="Object Stand Up"/>
+ <menu_item_call label="Perfil del objeto" name="Object Inspect"/>
+ <menu_item_call label="Acercar el zoom" name="Zoom In"/>
+ <context_menu label="Ponerme" name="Put On">
+ <menu_item_call label="Ponerme" name="Wear"/>
+ <menu_item_call label="Añadir" name="Add"/>
+ <context_menu label="Anexar" name="Object Attach"/>
+ <context_menu label="Anexar el HUD" name="Object Attach HUD"/>
+ </context_menu>
+ <context_menu label="Quitar" name="Remove">
+ <menu_item_call label="Denunciar una infracción" name="Report Abuse..."/>
+ <menu_item_call label="Ignorar" name="Object Mute"/>
+ <menu_item_call label="Devolver" name="Return..."/>
+ <menu_item_call label="Eliminar" name="Delete"/>
+ </context_menu>
+ <menu_item_call label="Tomar" name="Pie Object Take"/>
+ <menu_item_call label="Coger una copia" name="Take Copy"/>
+ <menu_item_call label="Pagar" name="Pay..."/>
+ <menu_item_call label="Comprar" name="Buy..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_object_icon.xml b/indra/newview/skins/minimal/xui/es/menu_object_icon.xml
new file mode 100644
index 0000000000..7e4578b950
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="Perfil del objeto..." name="Object Profile"/>
+ <menu_item_call label="Ignorar..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_outfit_gear.xml b/indra/newview/skins/minimal/xui/es/menu_outfit_gear.xml
new file mode 100644
index 0000000000..3b11bceecf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_outfit_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Outfit">
+ <menu_item_call label="Ponerme - Reemplazar el vestuario actual" name="wear"/>
+ <menu_item_call label="Ponerme - Añadir al vestuario actual" name="wear_add"/>
+ <menu_item_call label="Quitarme - Quitar del vestuario actual" name="take_off"/>
+ <menu label="Ropas nuevas" name="New Clothes">
+ <menu_item_call label="Camisa nueva" name="New Shirt"/>
+ <menu_item_call label="Pantalón nuevo" name="New Pants"/>
+ <menu_item_call label="Zapatos nuevos" name="New Shoes"/>
+ <menu_item_call label="Calcetines nuevos" name="New Socks"/>
+ <menu_item_call label="Chaqueta nueva" name="New Jacket"/>
+ <menu_item_call label="Falda nueva" name="New Skirt"/>
+ <menu_item_call label="Guantes nuevos" name="New Gloves"/>
+ <menu_item_call label="Camiseta nueva" name="New Undershirt"/>
+ <menu_item_call label="Ropa interior nueva" name="New Underpants"/>
+ <menu_item_call label="Nueva Alfa" name="New Alpha"/>
+ <menu_item_call label="Tatuaje nuevo" name="New Tattoo"/>
+ </menu>
+ <menu label="Nuevas partes del cuerpo" name="New Body Parts">
+ <menu_item_call label="Anatomía nueva" name="New Shape"/>
+ <menu_item_call label="Piel nueva" name="New Skin"/>
+ <menu_item_call label="Pelo nuevo" name="New Hair"/>
+ <menu_item_call label="Ojos nuevos" name="New Eyes"/>
+ </menu>
+ <menu_item_call label="Renombrar el vestuario" name="rename"/>
+ <menu_item_call label="Borrar el vestuario" name="delete_outfit"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_outfit_tab.xml b/indra/newview/skins/minimal/xui/es/menu_outfit_tab.xml
new file mode 100644
index 0000000000..4136082a62
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_outfit_tab.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit">
+ <menu_item_call label="Ponerme - Reemplazar el vestuario actual" name="wear_replace"/>
+ <menu_item_call label="Ponerme - Añadir al vestuario actual" name="wear_add"/>
+ <menu_item_call label="Quitarme - Quitar del vestuario actual" name="take_off"/>
+ <menu_item_call label="Editar el vestuario" name="edit"/>
+ <menu_item_call label="Renombrar el vestuario" name="rename"/>
+ <menu_item_call label="Borrar el vestuario" name="delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_participant_list.xml b/indra/newview/skins/minimal/xui/es/menu_participant_list.xml
new file mode 100644
index 0000000000..f6eedd1170
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_participant_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="Ordenar alfabéticamente" name="SortByName"/>
+ <menu_item_check label="Ordenar según las intervenciones recientes" name="SortByRecentSpeakers"/>
+ <menu_item_call label="Ver el perfil" name="View Profile"/>
+ <menu_item_call label="Añadir como amigo" name="Add Friend"/>
+ <menu_item_call label="MI" name="IM"/>
+ <menu_item_call label="Llamar" name="Call"/>
+ <menu_item_call label="Compartir" name="Share"/>
+ <menu_item_call label="Pagar" name="Pay"/>
+ <menu_item_check label="Ver los iconos de la gente" name="View Icons"/>
+ <menu_item_check label="Ignorar la voz" name="Block/Unblock"/>
+ <menu_item_check label="Ignorar el texto" name="MuteText"/>
+ <context_menu label="Opciones del moderador" name="Moderator Options">
+ <menu_item_check label="Permitir el chat de texto" name="AllowTextChat"/>
+ <menu_item_call label="Ignorar a este participante" name="ModerateVoiceMuteSelected"/>
+ <menu_item_call label="Quitar el silencio a este participante" name="ModerateVoiceUnMuteSelected"/>
+ <menu_item_call label="Silenciar a todos" name="ModerateVoiceMute"/>
+ <menu_item_call label="Quitar el silencio a todos" name="ModerateVoiceUnmute"/>
+ </context_menu>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_friends_view_sort.xml b/indra/newview/skins/minimal/xui/es/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..3899ad9e96
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_friends_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Ordenar alfabéticamente" name="sort_name"/>
+ <menu_item_check label="Ordenar por estatus" name="sort_status"/>
+ <menu_item_check label="Ver los iconos de la gente" name="view_icons"/>
+ <menu_item_check label="Ver permisos concedidos" name="view_permissions"/>
+ <menu_item_call label="Ver la lista de Residentes y Objetos ignorados" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_groups.xml b/indra/newview/skins/minimal/xui/es/menu_people_groups.xml
new file mode 100644
index 0000000000..51bd2c7208
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_groups.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Ver la información" name="View Info"/>
+ <menu_item_call label="Chat" name="Chat"/>
+ <menu_item_call label="Llamar" name="Call"/>
+ <menu_item_call label="Activar" name="Activate"/>
+ <menu_item_call label="Dejar" name="Leave"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_groups_view_sort.xml b/indra/newview/skins/minimal/xui/es/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..1bd3efb611
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Mostrar los iconos de grupo" name="Display Group Icons"/>
+ <menu_item_call label="Dejar el grupo seleccionado" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/es/menu_people_nearby.xml
new file mode 100644
index 0000000000..dc1486d879
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_nearby.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="Ver el perfil" name="View Profile"/>
+ <menu_item_call label="Añadir como amigo" name="Add Friend"/>
+ <menu_item_call label="Quitarle como amigo" name="Remove Friend"/>
+ <menu_item_call label="MI" name="IM"/>
+ <menu_item_call label="Llamar" name="Call"/>
+ <menu_item_call label="Mapa" name="Map"/>
+ <menu_item_call label="Compartir" name="Share"/>
+ <menu_item_call label="Pagar" name="Pay"/>
+ <menu_item_check label="Ignorar / No ignorar" name="Block/Unblock"/>
+ <menu_item_call label="Ofrecer teleporte" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_nearby_multiselect.xml b/indra/newview/skins/minimal/xui/es/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..227c5ebe58
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_nearby_multiselect.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="Añadir como amigos" name="Add Friends"/>
+ <menu_item_call label="Quitar amigos" name="Remove Friend"/>
+ <menu_item_call label="MI" name="IM"/>
+ <menu_item_call label="Llamar" name="Call"/>
+ <menu_item_call label="Compartir" name="Share"/>
+ <menu_item_call label="Pagar" name="Pay"/>
+ <menu_item_call label="Ofrecer teleporte" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_nearby_view_sort.xml b/indra/newview/skins/minimal/xui/es/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..f0fe383c0c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Ordenar según las intervenciones recientes" name="sort_by_recent_speakers"/>
+ <menu_item_check label="Ordenar alfabéticamente" name="sort_name"/>
+ <menu_item_check label="Ordenar según distancia" name="sort_distance"/>
+ <menu_item_check label="Ver los iconos de la gente" name="view_icons"/>
+ <menu_item_call label="Ver la lista de Residentes y Objetos ignorados" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_people_recent_view_sort.xml b/indra/newview/skins/minimal/xui/es/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..e4aaa89110
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Ordenar por los más recientes" name="sort_most"/>
+ <menu_item_check label="Ordenar alfabéticamente" name="sort_name"/>
+ <menu_item_check label="Ver los iconos de la gente" name="view_icons"/>
+ <menu_item_call label="Ver la lista de Residentes y Objetos ignorados" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_picks.xml b/indra/newview/skins/minimal/xui/es/menu_picks.xml
new file mode 100644
index 0000000000..9da68d7c9b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Información" name="pick_info"/>
+ <menu_item_call label="Editar" name="pick_edit"/>
+ <menu_item_call label="Teleportar" name="pick_teleport"/>
+ <menu_item_call label="Mapa" name="pick_map"/>
+ <menu_item_call label="Eliminar" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_picks_plus.xml b/indra/newview/skins/minimal/xui/es/menu_picks_plus.xml
new file mode 100644
index 0000000000..cc59bf1d29
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="Destacado nuevo" name="create_pick"/>
+ <menu_item_call label="Clasificado nuevo" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_place.xml b/indra/newview/skins/minimal/xui/es/menu_place.xml
new file mode 100644
index 0000000000..675f0699e9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="Crear un hito" name="landmark"/>
+ <menu_item_call label="Crear un destacado" name="pick"/>
+ <menu_item_call label="Comprar un pase" name="pass"/>
+ <menu_item_call label="Editar" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_place_add_button.xml b/indra/newview/skins/minimal/xui/es/menu_place_add_button.xml
new file mode 100644
index 0000000000..4b2f908a06
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Añadir una carpeta" name="add_folder"/>
+ <menu_item_call label="Añadir este hito" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_places_gear_folder.xml b/indra/newview/skins/minimal/xui/es/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..bf46eb58e3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Añadir este hito" name="add_landmark"/>
+ <menu_item_call label="Añadir una carpeta" name="add_folder"/>
+ <menu_item_call label="Cortar" name="cut"/>
+ <menu_item_call label="Copiar" name="copy_folder"/>
+ <menu_item_call label="Pegar" name="paste"/>
+ <menu_item_call label="Renombrar" name="rename"/>
+ <menu_item_call label="Borrar" name="delete"/>
+ <menu_item_call label="Abrir" name="expand"/>
+ <menu_item_call label="Cerrar" name="collapse"/>
+ <menu_item_call label="Abrir todas las carpetas" name="expand_all"/>
+ <menu_item_call label="Cerrar todas las carpetas" name="collapse_all"/>
+ <menu_item_check label="Ordenar por fecha" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_places_gear_landmark.xml b/indra/newview/skins/minimal/xui/es/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..eac85de846
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Teleportar" name="teleport"/>
+ <menu_item_call label="Más información" name="more_info"/>
+ <menu_item_call label="Mostrar en el mapa" name="show_on_map"/>
+ <menu_item_call label="Añadir un hito" name="add_landmark"/>
+ <menu_item_call label="Añadir una carpeta" name="add_folder"/>
+ <menu_item_call label="Cortar" name="cut"/>
+ <menu_item_call label="Copiar el hito" name="copy_landmark"/>
+ <menu_item_call label="Copiar la SLurl" name="copy_slurl"/>
+ <menu_item_call label="Pegar" name="paste"/>
+ <menu_item_call label="Renombrar" name="rename"/>
+ <menu_item_call label="Eliminar" name="delete"/>
+ <menu_item_call label="Abrir todas las carpetas" name="expand_all"/>
+ <menu_item_call label="Cerrar todas las carpetas" name="collapse_all"/>
+ <menu_item_check label="Ordenar por fecha" name="sort_by_date"/>
+ <menu_item_call label="Crear un Destacado" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_profile_overflow.xml b/indra/newview/skins/minimal/xui/es/menu_profile_overflow.xml
new file mode 100644
index 0000000000..5ee8c50949
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_profile_overflow.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="Mapa" name="show_on_map"/>
+ <menu_item_call label="Pagar" name="pay"/>
+ <menu_item_call label="Compartir" name="share"/>
+ <menu_item_call label="Ignorar" name="block"/>
+ <menu_item_call label="Designorar" name="unblock"/>
+ <menu_item_call label="Expulsar" name="kick"/>
+ <menu_item_call label="Congelar" name="freeze"/>
+ <menu_item_call label="Descongelar" name="unfreeze"/>
+ <menu_item_call label="CSR" name="csr"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_save_outfit.xml b/indra/newview/skins/minimal/xui/es/menu_save_outfit.xml
new file mode 100644
index 0000000000..a04ec75b60
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_save_outfit.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_outfit_menu">
+ <menu_item_call label="Guardar" name="save_outfit"/>
+ <menu_item_call label="Guardar como" name="save_as_new_outfit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_script_chiclet.xml b/indra/newview/skins/minimal/xui/es/menu_script_chiclet.xml
new file mode 100644
index 0000000000..f517baf566
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_script_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="ScriptChiclet Menu">
+ <menu_item_call label="Cerrar" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_slurl.xml b/indra/newview/skins/minimal/xui/es/menu_slurl.xml
new file mode 100644
index 0000000000..ca19acec6e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_slurl.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Acerca de la URL" name="about_url"/>
+ <menu_item_call label="Teleportar a la URL" name="teleport_to_url"/>
+ <menu_item_call label="Mapa" name="show_on_map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_teleport_history_gear.xml b/indra/newview/skins/minimal/xui/es/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..b708f3bc20
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="Abrir todas las carpetas" name="Expand all folders"/>
+ <menu_item_call label="Cerrar todas las carpetas" name="Collapse all folders"/>
+ <menu_item_call label="Limpiar el historial de teleportes" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_teleport_history_item.xml b/indra/newview/skins/minimal/xui/es/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..ed33c55aca
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Teleportarse" name="Teleport"/>
+ <menu_item_call label="Más información" name="More Information"/>
+ <menu_item_call label="Copiar al portapapeles" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_teleport_history_tab.xml b/indra/newview/skins/minimal/xui/es/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..17e90422a5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Abrir" name="TabOpen"/>
+ <menu_item_call label="Cerrar" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_text_editor.xml b/indra/newview/skins/minimal/xui/es/menu_text_editor.xml
new file mode 100644
index 0000000000..095e461734
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="Cortar" name="Cut"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Pegar" name="Paste"/>
+ <menu_item_call label="Borrar" name="Delete"/>
+ <menu_item_call label="Seleccionar todo" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_topinfobar.xml b/indra/newview/skins/minimal/xui/es/menu_topinfobar.xml
new file mode 100644
index 0000000000..2125fd51b2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_topinfobar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_topinfobar">
+ <menu_item_check label="Mostrar las coordenadas" name="Show Coordinates"/>
+ <menu_item_check label="Mostrar las propiedades de la parcela" name="Show Parcel Properties"/>
+ <menu_item_call label="Hito" name="Landmark"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_agent.xml b/indra/newview/skins/minimal/xui/es/menu_url_agent.xml
new file mode 100644
index 0000000000..a089c8f68e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar el perfil del Residente" name="show_agent"/>
+ <menu_item_call label="Copiar el nombre al portapapeles" name="url_copy_label"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_group.xml b/indra/newview/skins/minimal/xui/es/menu_url_group.xml
new file mode 100644
index 0000000000..79374b9739
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar la información del grupo" name="show_group"/>
+ <menu_item_call label="Copiar el grupo al portapapeles" name="url_copy_label"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_http.xml b/indra/newview/skins/minimal/xui/es/menu_url_http.xml
new file mode 100644
index 0000000000..585c059ff3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Abrir la página web" name="url_open"/>
+ <menu_item_call label="Abrir en el navegador incorporado" name="url_open_internal"/>
+ <menu_item_call label="Abrir en mi navegador" name="url_open_external"/>
+ <menu_item_call label="Copiar la URL al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_inventory.xml b/indra/newview/skins/minimal/xui/es/menu_url_inventory.xml
new file mode 100644
index 0000000000..13a8711c76
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar ítem del inventario" name="show_item"/>
+ <menu_item_call label="Copiar el nombre al portapapeles" name="url_copy_label"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_map.xml b/indra/newview/skins/minimal/xui/es/menu_url_map.xml
new file mode 100644
index 0000000000..f96a0c7170
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar en el mapa" name="show_on_map"/>
+ <menu_item_call label="Teleportarse a la localización" name="teleport_to_location"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_objectim.xml b/indra/newview/skins/minimal/xui/es/menu_url_objectim.xml
new file mode 100644
index 0000000000..8791a290af
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar la información del objeto" name="show_object"/>
+ <menu_item_call label="Mostrar en el mapa" name="show_on_map"/>
+ <menu_item_call label="Teleportarse a la posición del objeto" name="teleport_to_object"/>
+ <menu_item_call label="Copiar el nombre del objeto al portapapeles" name="url_copy_label"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_parcel.xml b/indra/newview/skins/minimal/xui/es/menu_url_parcel.xml
new file mode 100644
index 0000000000..9e789ef8ee
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar la información de la parcela" name="show_parcel"/>
+ <menu_item_call label="Mostrar en el mapa" name="show_on_map"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_slapp.xml b/indra/newview/skins/minimal/xui/es/menu_url_slapp.xml
new file mode 100644
index 0000000000..7147dcd3cf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Ejecutar este comando" name="run_slapp"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_slurl.xml b/indra/newview/skins/minimal/xui/es/menu_url_slurl.xml
new file mode 100644
index 0000000000..4ab47c2f61
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar la información del lugar" name="show_place"/>
+ <menu_item_call label="Mostrar en el mapa" name="show_on_map"/>
+ <menu_item_call label="Teleportarse a este lugar" name="teleport_to_location"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_url_teleport.xml b/indra/newview/skins/minimal/xui/es/menu_url_teleport.xml
new file mode 100644
index 0000000000..8f86a91be3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Teleportarse a este lugar" name="teleport"/>
+ <menu_item_call label="Mostrar en el mapa" name="show_on_map"/>
+ <menu_item_call label="Copiar la SLurl al portapapeles" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_viewer.xml b/indra/newview/skins/minimal/xui/es/menu_viewer.xml
new file mode 100644
index 0000000000..776ccfe21b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_viewer.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Main Menu">
+ <menu label="Ayuda" name="Help">
+ <menu_item_call label="Ayuda de [SECOND_LIFE]" name="Second Life Help"/>
+ </menu>
+ <menu label="Avanzado" name="Advanced">
+ <menu label="Atajos de teclado" name="Shortcuts">
+ <menu_item_check label="Volar" name="Fly"/>
+ <menu_item_call label="Cerrar la ventana" name="Close Window"/>
+ <menu_item_call label="Cerrar todas las ventanas" name="Close All Windows"/>
+ <menu_item_call label="Volver a la vista por defecto" name="Reset View"/>
+ </menu>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/es/menu_wearable_list_item.xml b/indra/newview/skins/minimal/xui/es/menu_wearable_list_item.xml
new file mode 100644
index 0000000000..4bffa689e7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_wearable_list_item.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit Wearable Context Menu">
+ <menu_item_call label="Reemplazar" name="wear_replace"/>
+ <menu_item_call label="Ponerme" name="wear_wear"/>
+ <menu_item_call label="Añadir" name="wear_add"/>
+ <menu_item_call label="Quitarme / Quitar" name="take_off_or_detach"/>
+ <menu_item_call label="Quitar" name="detach"/>
+ <context_menu label="Anexar a" name="wearable_attach_to"/>
+ <context_menu label="Anexar al HUD" name="wearable_attach_to_hud"/>
+ <menu_item_call label="Quitarme" name="take_off"/>
+ <menu_item_call label="Editar" name="edit"/>
+ <menu_item_call label="Perfil del elemento" name="object_profile"/>
+ <menu_item_call label="Mostrar original" name="show_original"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_wearing_gear.xml b/indra/newview/skins/minimal/xui/es/menu_wearing_gear.xml
new file mode 100644
index 0000000000..9d9ce75e53
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_wearing_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Wearing">
+ <menu_item_call label="Editar el vestuario" name="edit"/>
+ <menu_item_call label="Quitarme" name="takeoff"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/es/menu_wearing_tab.xml b/indra/newview/skins/minimal/xui/es/menu_wearing_tab.xml
new file mode 100644
index 0000000000..64fd7ce4cf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/menu_wearing_tab.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Wearing">
+ <menu_item_call label="Quitarme" name="take_off"/>
+ <menu_item_call label="Quitar" name="detach"/>
+ <menu_item_call label="Editar el vestuario" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/es/notifications.xml b/indra/newview/skins/minimal/xui/es/notifications.xml
new file mode 100644
index 0000000000..b08ebb5f76
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/notifications.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<notifications>
+ <notification name="UserGiveItem">
+ [NAME_SLURL] te ofrece un/a [ITEM_SLURL]. Para utilizar este ítem, cambia al modo Avanzado y búscalo en el inventario. Para cambiar al modo Avanzado, sal de la aplicación, reiníciala y cambia el ajuste de modo en la pantalla de inicio de sesión.
+ <form name="form">
+ <button name="Show" text="Conservar ítem"/>
+ <button name="Discard" text="Rechazar ítem"/>
+ <button name="Mute" text="Bloquear usuario"/>
+ </form>
+ </notification>
+ <notification name="ObjectGiveItem">
+ Un objeto de nombre &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt;, propiedad de [NAME_SLURL], te ofrece un/a [ITEM_SLURL]. Para utilizar este ítem, cambia al modo Avanzado y búscalo en el inventario. Para cambiar al modo Avanzado, sal de la aplicación, reiníciala y cambia el ajuste de modo en la pantalla de inicio de sesión.
+ <form name="form">
+ <button name="Keep" text="Conservar ítem"/>
+ <button name="Discard" text="Rechazar ítem"/>
+ <button name="Mute" text="Bloquear objeto"/>
+ </form>
+ </notification>
+</notifications>
diff --git a/indra/newview/skins/minimal/xui/es/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/es/panel_bottomtray.xml
new file mode 100644
index 0000000000..f782d66ae7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_bottomtray.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="DragIndicationImageName" value="Accordion_ArrowOpened_Off"/>
+ <string name="SpeakBtnToolTip" value="Activa/Desactiva el micrófono"/>
+ <string name="VoiceControlBtnToolTip" value="Muestra/Oculta el panel del control de voz"/>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_list label="Gestos" name="Gesture" tool_tip="Muestra/Oculta los gestos"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <bottomtray_button label="Visión" name="camera_btn" tool_tip="Muestra/Oculta los controles de la cámara"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Destinos" name="destination_btn" tool_tip="Muestra la ventana de gente"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Mi avatar" name="avatar_btn"/>
+ </layout_panel>
+ <layout_panel name="people_panel">
+ <bottomtray_button label="Gente" name="show_people_button" tool_tip="Muestra la ventana de gente"/>
+ </layout_panel>
+ <layout_panel name="profile_panel">
+ <bottomtray_button label="Perfil" name="show_profile_btn" tool_tip="Muestra la ventana del perfil"/>
+ </layout_panel>
+ <layout_panel name="howto_panel">
+ <bottomtray_button label="Indicaciones" name="show_help_btn" tool_tip="Abrir los temas sobre indicaciones de Second Life"/>
+ </layout_panel>
+ <layout_panel name="im_well_panel">
+ <chiclet_im_well name="im_well">
+ <button name="Unread IM messages" tool_tip="Conversaciones"/>
+ </chiclet_im_well>
+ </layout_panel>
+ <layout_panel name="notification_well_panel">
+ <chiclet_notification name="notification_well">
+ <button name="Unread" tool_tip="Notificaciones"/>
+ </chiclet_notification>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/es/panel_group_control_panel.xml
new file mode 100644
index 0000000000..e77156b0d4
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_group_control_panel.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="vertical_stack">
+ <layout_panel name="end_call_btn_panel">
+ <button label="Colgar" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Abrir los controles de la voz" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/es/panel_im_control_panel.xml
new file mode 100644
index 0000000000..7d4db6a630
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_im_control_panel.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="button_stack">
+ <layout_panel name="view_profile_btn_panel">
+ <button label="Perfil" name="view_profile_btn"/>
+ </layout_panel>
+ <layout_panel name="add_friend_btn_panel">
+ <button label="Añadir como amigo" name="add_friend_btn"/>
+ </layout_panel>
+ <layout_panel name="teleport_btn_panel">
+ <button label="Teleportarme" name="teleport_btn" tool_tip="Ofrecer teleporte a esta persona"/>
+ </layout_panel>
+ <layout_panel name="share_btn_panel">
+ <button label="Compartir" name="share_btn"/>
+ </layout_panel>
+ <layout_panel name="pay_btn_panel">
+ <button label="Pagar" name="pay_btn"/>
+ </layout_panel>
+ <layout_panel name="call_btn_panel">
+ <button label="Llamar" name="call_btn"/>
+ </layout_panel>
+ <layout_panel name="end_call_btn_panel">
+ <button label="Colgar" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Controles de la voz" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_login.xml b/indra/newview/skins/minimal/xui/es/panel_login.xml
new file mode 100644
index 0000000000..689a71e277
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_login.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_login">
+ <panel.string name="create_account_url">
+ http://join.secondlife.com/index.php?lang=es-ES
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=es
+ </panel.string>
+ <layout_stack name="login_widgets">
+ <layout_panel name="login">
+ <text name="username_text">
+ Nombre de usuario:
+ </text>
+ <combo_box name="username_combo" tool_tip="El nombre de usuario que elegiste al registrarte, como bobsmith12 o Steller Sunshine"/>
+ <text name="password_text">
+ Contraseña:
+ </text>
+ <check_box label="Recordar la contraseña" name="remember_check"/>
+ <button label="Iniciar sesión" name="connect_btn"/>
+ <text name="mode_selection_text">
+ Modo:
+ </text>
+ <combo_box name="mode_combo" tool_tip="Selecciona el modo. Elige Básico para una exploración rápida y fácil y para chatear. Elige Avanzado para tener acceso a más funciones.">
+ <combo_box.item label="Básico" name="Basic"/>
+ <combo_box.item label="Avanzado" name="Advanced"/>
+ </combo_box>
+ </layout_panel>
+ <layout_panel name="links">
+ <text name="create_new_account_text">
+ Registrarme
+ </text>
+ <text name="forgot_password_text">
+ ¿Olvidaste el nombre de usuario o la contraseña?
+ </text>
+ <text name="login_help">
+ ¿Necesitas ayuda para conectarte?
+ </text>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/es/panel_navigation_bar.xml
new file mode 100644
index 0000000000..e8e95c3bac
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_navigation_bar.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <pull_button name="back_btn" tool_tip="Volver a lo localización anterior"/>
+ <pull_button name="forward_btn" tool_tip="Ir una localización adelante"/>
+ <button name="home_btn" tool_tip="Teleportar a mi Base"/>
+ <location_input label="Localización" name="location_combo"/>
+ <search_combo_box label="Buscar" name="search_combo_box" tool_tip="Buscar">
+ <combo_editor label="Buscar en [SECOND_LIFE]" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+ <favorites_bar name="favorite" tool_tip="¡Accede rápidamente a tus lugares favoritos de Second Life arrastrando hitos hasta aquí!">
+ <label name="favorites_bar_label" tool_tip="¡Accede rápidamente a tus lugares favoritos de Second Life arrastrando hitos hasta aquí!">
+ Barra de Favoritos
+ </label>
+ <chevron_button name="&gt;&gt;" tool_tip="Ver más de Mis favoritos"/>
+ </favorites_bar>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_people.xml b/indra/newview/skins/minimal/xui/es/panel_people.xml
new file mode 100644
index 0000000000..7d3157ef45
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_people.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="Gente" name="people_panel">
+ <string name="no_recent_people" value="No hay gente reciente. ¿Estás buscando gente con la que juntarte? Prueba con el botón Destinos que aparece a continuación."/>
+ <string name="no_filtered_recent_people" value="No hay gente reciente con ese nombre."/>
+ <string name="no_one_near" value="No hay nadie cerca. ¿Estás buscando gente con la que juntarte? Prueba con el botón Destinos que aparece a continuación."/>
+ <string name="no_one_filtered_near" value="No hay nadie cerca con ese nombre."/>
+ <string name="no_friends_online" value="No hay amigos conectados"/>
+ <string name="no_friends" value="No hay amigos"/>
+ <string name="no_friends_msg">
+ Haz clic con el botón derecho del ratón en un residente para agregarlo como amigo.
+¿Estás buscando gente con la que juntarte? Prueba con el botón Destinos que aparece a continuación.
+ </string>
+ <string name="no_filtered_friends_msg">
+ ¿No encuentras lo que buscas? Prueba con el botón Destinos que aparece a continuación.
+ </string>
+ <string name="people_filter_label" value="Filtrar a la gente"/>
+ <string name="groups_filter_label" value="Filtrar a los grupos"/>
+ <string name="no_filtered_groups_msg" value="¿No encuentras lo que buscas? Prueba con [secondlife:///app/search/groups/[SEARCH_TERM] Buscar]."/>
+ <string name="no_groups_msg" value="¿Buscas grupos en que participar? Prueba la [secondlife:///app/search/groups Búsqueda]."/>
+ <string name="MiniMapToolTipMsg" value="[REGIÓN](Haz doble clic para abrir el mapa y pulsa la tecla Mayús y arrastra para obtener una vista panorámica)"/>
+ <string name="AltMiniMapToolTipMsg" value="[REGIÓN](Haz doble clic para teleportarte y pulsa la tecla Mayús y arrastra para obtener una vista panorámica)"/>
+ <filter_editor label="Filtrar" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="CERCANA" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel"/>
+ </panel>
+ <panel label="MIS AMIGOS" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="Conectado"/>
+ <accordion_tab name="tab_all" title="Todos"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <layout_stack name="bottom_panel">
+ <layout_panel name="trash_btn_panel">
+ <dnd_button name="del_btn" tool_tip="Quitar a la persona seleccionada de tu lista de amigos"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ </panel>
+ <panel label="RECIENTE" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="add_friend_btn" tool_tip="Añadir al Residente seleccionado a la lista de tus amigos"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <layout_stack name="bottom_bar_ls">
+ <layout_panel name="view_profile_btn_lp">
+ <button label="Perfil" name="view_profile_btn" tool_tip="Mostrar imágenes, grupos y otra información del Residente"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="MI" name="im_btn" tool_tip="Abrir una sesión de mensajes instantáneos"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Teleporte" name="teleport_btn" tool_tip="Ofrecer teleporte"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack name="bottom_bar_ls1">
+ <layout_panel name="group_info_btn_lp">
+ <button label="Perfil del grupo" name="group_info_btn" tool_tip="Ver la información del grupo"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Chat de grupo" name="chat_btn" tool_tip="Abrir el chat"/>
+ </layout_panel>
+ <layout_panel name="group_call_btn_lp">
+ <button label="Llamar al grupo" name="group_call_btn" tool_tip="Llama a este grupo"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_side_tray_tab_caption.xml b/indra/newview/skins/minimal/xui/es/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..775e343dc9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_side_tray_tab_caption.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="Panel lateral"/>
+ <button name="undock" tool_tip="Soltar"/>
+ <button name="dock" tool_tip="Fijar"/>
+ <button name="show_help" tool_tip="Ver ayuda"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/es/panel_status_bar.xml b/indra/newview/skins/minimal/xui/es/panel_status_bar.xml
new file mode 100644
index 0000000000..ab76d3f994
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/es/panel_status_bar.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="status">
+ <panel.string name="StatBarDaysOfWeek">
+ Domingo:Lunes:Martes:Miércoles:Jueves:Viernes:Sábado
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
+ Enero:Febrero:Marzo:Abril:Mayo:Junio:Julio:Agosto:Septiembre:Octubre:Noviembre:Diciembre
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
+ Pérdida de paquetes
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
+ Ancho de banda
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ [AMT] L$
+ </panel.string>
+ <panel name="balance_bg">
+ <text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="20 L$"/>
+ <button label="COMPRAR L$" name="buyL" tool_tip="Pulsa para comprar más L$"/>
+ </panel>
+ <text name="TimeText" tool_tip="Hora actual (Pacífico)">
+ 24:00 AM PST
+ </text>
+ <button name="media_toggle_btn" tool_tip="Iniciar/Parar todos los media (música, vídeo, páginas web)"/>
+ <button name="volume_btn" tool_tip="Control general del volumen"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/floater_camera.xml b/indra/newview/skins/minimal/xui/fr/floater_camera.xml
new file mode 100644
index 0000000000..1d62a89ff2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/floater_camera.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
+ Faire tourner la caméra autour du point central
+ </floater.string>
+ <floater.string name="zoom_tooltip">
+ Zoomer en direction du point central
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Déplacer la caméra vers le haut et le bas, la gauche et la droite
+ </floater.string>
+ <floater.string name="camera_modes_title">
+ Modes
+ </floater.string>
+ <floater.string name="pan_mode_title">
+ Rotation - Zoom - Panoramique
+ </floater.string>
+ <floater.string name="presets_mode_title">
+ Préréglages
+ </floater.string>
+ <floater.string name="free_mode_title">
+ Voir l&apos;objet
+ </floater.string>
+ <panel name="controls">
+ <panel name="preset_views_list">
+ <panel_camera_item name="front_view">
+ <panel_camera_item.text name="front_view_text">
+ Vue frontale
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="group_view">
+ <panel_camera_item.text name="side_view_text">
+ Vue latérale
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="rear_view">
+ <panel_camera_item.text name="rear_view_text">
+ Vue arrière
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="camera_modes_list">
+ <panel_camera_item name="object_view">
+ <panel_camera_item.text name="object_view_text">
+ Vue de l&apos;objet
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="mouselook_view">
+ <panel_camera_item.text name="mouselook_view_text">
+ Vue subjective
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="zoom" tool_tip="Zoomer en direction du point central">
+ <joystick_rotate name="cam_rotate_stick" tool_tip="Faire tourner la caméra autour du point central"/>
+ <slider_bar name="zoom_slider" tool_tip="Zoomer en direction du point central"/>
+ <joystick_track name="cam_track_stick" tool_tip="Déplacer la caméra vers le haut et le bas, la gauche et la droite"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="presets_btn" tool_tip="Préréglages"/>
+ <button label="" name="pan_btn" tool_tip="Rotation - Zoom - Panoramique"/>
+ <button label="" name="avatarview_btn" tool_tip="Modes"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/floater_help_browser.xml b/indra/newview/skins/minimal/xui/fr/floater_help_browser.xml
new file mode 100644
index 0000000000..09d763b809
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/floater_help_browser.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="AIDE RAPIDE">
+ <floater.string name="loading_text">
+ Chargement…
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls"/>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/floater_media_browser.xml b/indra/newview/skins/minimal/xui/fr/floater_media_browser.xml
new file mode 100644
index 0000000000..ba171c6363
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/floater_media_browser.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="NAVIGATEUR DE MÉDIAS">
+ <floater.string name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button label="Préc." name="back"/>
+ <button label="Suiv." name="forward"/>
+ <button label="Recharger" name="reload"/>
+ <button label="OK" name="go"/>
+ </layout_panel>
+ <layout_panel name="time_controls">
+ <button label="retour" name="rewind"/>
+ <button label="stop" name="stop"/>
+ <button label="avance" name="seek"/>
+ </layout_panel>
+ <layout_panel name="parcel_owner_controls">
+ <button label="Envoyer la page actuelle à la parcelle" name="assign"/>
+ </layout_panel>
+ <layout_panel name="external_controls">
+ <button label="Ouvrir dans mon navigateur Web" name="open_browser"/>
+ <check_box label="Toujours ouvrir dans mon navigateur Web" name="open_always"/>
+ <button label="Fermer" name="close"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/floater_nearby_chat.xml b/indra/newview/skins/minimal/xui/fr/floater_nearby_chat.xml
new file mode 100644
index 0000000000..9b1b21c434
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/floater_nearby_chat.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="CHAT PRÈS DE MOI">
+ <check_box label="Traduction du chat (fournie par Google)" name="translate_chat_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/floater_web_content.xml b/indra/newview/skins/minimal/xui/fr/floater_web_content.xml
new file mode 100644
index 0000000000..71f44b6ec3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/floater_web_content.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_web_content" title="">
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button name="back" tool_tip="Précédente"/>
+ <button name="forward" tool_tip="Suivante"/>
+ <button name="stop" tool_tip="Arrêter"/>
+ <button name="reload" tool_tip="Recharger la page"/>
+ <combo_box name="address" tool_tip="Saisir une URL ici"/>
+ <icon name="media_secure_lock_flag" tool_tip="Navigation sécurisée"/>
+ <button name="popexternal" tool_tip="Ouvrir l&apos;URL actuelle dans votre navigateur de bureau"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/inspect_avatar.xml b/indra/newview/skins/minimal/xui/fr/inspect_avatar.xml
new file mode 100644
index 0000000000..553646f8e9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/inspect_avatar.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [AGE]
+ </string>
+ <string name="Details">
+ [SL_PROFILE]
+ </string>
+ <text name="user_subtitle" value="11 mois, 3 jours"/>
+ <text name="user_details">
+ This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot
+ </text>
+ <slider name="volume_slider" tool_tip="Volume de la voix" value="0.5"/>
+ <button label="Devenir amis" name="add_friend_btn"/>
+ <button label="IM" name="im_btn"/>
+ <button label="Profil" name="view_profile_btn"/>
+ <panel name="moderator_panel">
+ <button label="Désactiver le chat vocal" name="disable_voice"/>
+ <button label="Activer le chat vocal" name="enable_voice"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/inspect_object.xml b/indra/newview/skins/minimal/xui/fr/inspect_object.xml
new file mode 100644
index 0000000000..b66af7a2bf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/inspect_object.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ Par [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ De [CREATOR]
+Propriétaire [OWNER]
+ </string>
+ <string name="Price">
+ [AMOUNT] L$
+ </string>
+ <string name="PriceFree">
+ Gratuit !
+ </string>
+ <string name="Touch">
+ Toucher
+ </string>
+ <string name="Sit">
+ M&apos;asseoir
+ </string>
+ <text name="object_name" value="Test Object Name That Is actually two lines and Really Long"/>
+ <text name="object_creator">
+ par secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
+ </text>
+ <text name="price_text">
+ 30 000 L$
+ </text>
+ <text name="object_description">
+ This is a really long description for an object being as how it is at least 80 characters in length and so but maybe more like 120 at this point. Who knows, really?
+ </text>
+ <text name="object_media_url">
+ http://www.superdupertest.com
+ </text>
+ <button label="Acheter" name="buy_btn"/>
+ <button label="Payer" name="pay_btn"/>
+ <button label="Prendre une copie" name="take_free_copy_btn"/>
+ <button label="Toucher" name="touch_btn"/>
+ <button label="M&apos;asseoir" name="sit_btn"/>
+ <button label="Ouvert" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="Navigation sécurisée"/>
+ <button label="Plus" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_add_wearable_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_add_wearable_gear.xml
new file mode 100644
index 0000000000..7e7993175e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_add_wearable_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Add Wearable Gear Menu">
+ <menu_item_check label="Trier en commençant par le plus récent" name="sort_by_most_recent"/>
+ <menu_item_check label="Trier par nom" name="sort_by_name"/>
+ <menu_item_check label="Trier par type" name="sort_by_type"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_attachment_other.xml b/indra/newview/skins/minimal/xui/fr/menu_attachment_other.xml
new file mode 100644
index 0000000000..f48513eb2b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_attachment_other.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_avatar_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Voir le profil" name="Profile..."/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="IM" name="Send IM..."/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Inviter dans le groupe" name="Invite..."/>
+ <menu_item_call label="Ignorer" name="Avatar Mute"/>
+ <menu_item_call label="Signaler" name="abuse"/>
+ <menu_item_call label="Figer" name="Freeze..."/>
+ <menu_item_call label="Expulser" name="Eject..."/>
+ <menu_item_call label="Déboguer les textures" name="Debug..."/>
+ <menu_item_call label="Zoomer en avant" name="Zoom In"/>
+ <menu_item_call label="Payer" name="Pay..."/>
+ <menu_item_call label="Profil de l&apos;objet" name="Object Inspect"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_attachment_self.xml b/indra/newview/skins/minimal/xui/fr/menu_attachment_self.xml
new file mode 100644
index 0000000000..78198fb5a8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_attachment_self.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Attachment Pie">
+ <menu_item_call label="Toucher" name="Attachment Object Touch"/>
+ <menu_item_call label="Modifier" name="Edit..."/>
+ <menu_item_call label="Détacher" name="Detach"/>
+ <menu_item_call label="M&apos;asseoir" name="Sit Down Here"/>
+ <menu_item_call label="Me lever" name="Stand Up"/>
+ <menu_item_call label="Changer de tenue" name="Change Outfit"/>
+ <menu_item_call label="Modifier ma tenue" name="Edit Outfit"/>
+ <menu_item_call label="Modifier ma silhouette" name="Edit My Shape"/>
+ <menu_item_call label="Mes amis" name="Friends..."/>
+ <menu_item_call label="Mes groupes" name="Groups..."/>
+ <menu_item_call label="Mon profil" name="Profile..."/>
+ <menu_item_call label="Déboguer les textures" name="Debug..."/>
+ <menu_item_call label="Lâcher" name="Drop"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_avatar_icon.xml b/indra/newview/skins/minimal/xui/fr/menu_avatar_icon.xml
new file mode 100644
index 0000000000..3bac25c79b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="Voir le profil" name="Show Profile"/>
+ <menu_item_call label="Envoyer IM..." name="Send IM"/>
+ <menu_item_call label="Devenir amis..." name="Add Friend"/>
+ <menu_item_call label="Supprimer cet ami..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_avatar_other.xml b/indra/newview/skins/minimal/xui/fr/menu_avatar_other.xml
new file mode 100644
index 0000000000..08d1a20361
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_avatar_other.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Voir le profil" name="Profile..."/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="IM" name="Send IM..."/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Inviter dans le groupe" name="Invite..."/>
+ <menu_item_call label="Ignorer" name="Avatar Mute"/>
+ <menu_item_call label="Signaler" name="abuse"/>
+ <menu_item_call label="Figer" name="Freeze..."/>
+ <menu_item_call label="Expulser" name="Eject..."/>
+ <menu_item_call label="Déboguer les textures" name="Debug..."/>
+ <menu_item_call label="Zoomer en avant" name="Zoom In"/>
+ <menu_item_call label="Payer" name="Pay..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_avatar_self.xml b/indra/newview/skins/minimal/xui/fr/menu_avatar_self.xml
new file mode 100644
index 0000000000..c7ee2e9f88
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_avatar_self.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Self Pie">
+ <menu_item_call label="M&apos;asseoir" name="Sit Down Here"/>
+ <menu_item_call label="Me lever" name="Stand Up"/>
+ <context_menu label="Enlever" name="Take Off &gt;">
+ <context_menu label="Habits" name="Clothes &gt;">
+ <menu_item_call label="Chemise" name="Shirt"/>
+ <menu_item_call label="Pantalon" name="Pants"/>
+ <menu_item_call label="Jupe" name="Skirt"/>
+ <menu_item_call label="Chaussures" name="Shoes"/>
+ <menu_item_call label="Chaussettes" name="Socks"/>
+ <menu_item_call label="Veste" name="Jacket"/>
+ <menu_item_call label="Gants" name="Gloves"/>
+ <menu_item_call label="Débardeur" name="Self Undershirt"/>
+ <menu_item_call label="Caleçon" name="Self Underpants"/>
+ <menu_item_call label="Tatouage" name="Self Tattoo"/>
+ <menu_item_call label="Alpha" name="Self Alpha"/>
+ <menu_item_call label="Tous les habits" name="All Clothes"/>
+ </context_menu>
+ <context_menu label="HUD" name="Object Detach HUD"/>
+ <context_menu label="Détacher" name="Object Detach"/>
+ <menu_item_call label="Tout détacher" name="Detach All"/>
+ </context_menu>
+ <menu_item_call label="Changer de tenue" name="Chenge Outfit"/>
+ <menu_item_call label="Modifier ma tenue" name="Edit Outfit"/>
+ <menu_item_call label="Modifier ma silhouette" name="Edit My Shape"/>
+ <menu_item_call label="Mes amis" name="Friends..."/>
+ <menu_item_call label="Mes groupes" name="Groups..."/>
+ <menu_item_call label="Mon profil" name="Profile..."/>
+ <menu_item_call label="Déboguer les textures" name="Debug..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_bottomtray.xml b/indra/newview/skins/minimal/xui/fr/menu_bottomtray.xml
new file mode 100644
index 0000000000..bfdc89c5bb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_bottomtray.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="Bouton Geste" name="ShowGestureButton"/>
+ <menu_item_check label="Bouton Bouger" name="ShowMoveButton"/>
+ <menu_item_check label="Bouton Affichage" name="ShowCameraButton"/>
+ <menu_item_check label="Bouton Photo" name="ShowSnapshotButton"/>
+ <menu_item_check label="Bouton Panneau latéral" name="ShowSidebarButton"/>
+ <menu_item_check label="Bouton Construire" name="ShowBuildButton"/>
+ <menu_item_check label="Bouton Rechercher" name="ShowSearchButton"/>
+ <menu_item_check label="Bouton Carte" name="ShowWorldMapButton"/>
+ <menu_item_check label="Bouton Mini-carte" name="ShowMiniMapButton"/>
+ <menu_item_call label="Couper" name="NearbyChatBar_Cut"/>
+ <menu_item_call label="Copier" name="NearbyChatBar_Copy"/>
+ <menu_item_call label="Coller" name="NearbyChatBar_Paste"/>
+ <menu_item_call label="Supprimer" name="NearbyChatBar_Delete"/>
+ <menu_item_call label="Tout sélectionner" name="NearbyChatBar_Select_All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_cof_attachment.xml b/indra/newview/skins/minimal/xui/fr/menu_cof_attachment.xml
new file mode 100644
index 0000000000..a4ead48b6b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_cof_attachment.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Attachment">
+ <menu_item_call label="Détacher" name="detach"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_cof_body_part.xml b/indra/newview/skins/minimal/xui/fr/menu_cof_body_part.xml
new file mode 100644
index 0000000000..4b6907fcc6
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_cof_body_part.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Body">
+ <menu_item_call label="Remplacer" name="replace"/>
+ <menu_item_call label="Modifier" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_cof_clothing.xml b/indra/newview/skins/minimal/xui/fr/menu_cof_clothing.xml
new file mode 100644
index 0000000000..03cc569704
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_cof_clothing.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Clothing">
+ <menu_item_call label="Enlever" name="take_off"/>
+ <menu_item_call label="Modifier" name="edit"/>
+ <menu_item_call label="Remplacer" name="replace"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_cof_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_cof_gear.xml
new file mode 100644
index 0000000000..8276d57025
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_cof_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear COF">
+ <menu label="Nouveaux habits" name="COF.Gear.New_Clothes"/>
+ <menu label="Nouvelles parties du corps" name="COF.Geear.New_Body_Parts"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_edit.xml b/indra/newview/skins/minimal/xui/fr/menu_edit.xml
new file mode 100644
index 0000000000..56669f31e1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_edit.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu label="Modifier" name="Edit">
+ <menu_item_call label="Annuler" name="Undo"/>
+ <menu_item_call label="Refaire" name="Redo"/>
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Dupliquer" name="Duplicate"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+ <menu_item_call label="Désélectionner" name="Deselect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_favorites.xml b/indra/newview/skins/minimal/xui/fr/menu_favorites.xml
new file mode 100644
index 0000000000..5f1545fde7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Téléporter" name="Teleport To Landmark"/>
+ <menu_item_call label="Voir/Modifier le repère" name="Landmark Open"/>
+ <menu_item_call label="Copier la SLurl" name="Copy slurl"/>
+ <menu_item_call label="Voir sur la carte" name="Show On Map"/>
+ <menu_item_call label="Copier" name="Landmark Copy"/>
+ <menu_item_call label="Coller" name="Landmark Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_gesture_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_gesture_gear.xml
new file mode 100644
index 0000000000..062dd0f005
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="Ajouter/Supprimer des favoris" name="activate"/>
+ <menu_item_call label="Copier" name="copy_gesture"/>
+ <menu_item_call label="Coller" name="paste"/>
+ <menu_item_call label="Copier l&apos;UUID" name="copy_uuid"/>
+ <menu_item_call label="Enregistrer dans la tenue actuelle" name="save_to_outfit"/>
+ <menu_item_call label="Modifier" name="edit_gesture"/>
+ <menu_item_call label="Inspecter" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_group_plus.xml b/indra/newview/skins/minimal/xui/fr/menu_group_plus.xml
new file mode 100644
index 0000000000..0db5afedc7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Rejoindre des groupes..." name="item_join"/>
+ <menu_item_call label="Nouveau groupe..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_hide_navbar.xml b/indra/newview/skins/minimal/xui/fr/menu_hide_navbar.xml
new file mode 100644
index 0000000000..20af901ddc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_hide_navbar.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="Afficher la barre de navigation" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="Afficher la barre des favoris" name="ShowNavbarFavoritesPanel"/>
+ <menu_item_check label="Afficher la mini-barre d&apos;emplacement" name="ShowMiniLocationPanel"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_im_well_button.xml b/indra/newview/skins/minimal/xui/fr/menu_im_well_button.xml
new file mode 100644
index 0000000000..8ef1529e6b
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_im_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="IM Well Button Context Menu">
+ <menu_item_call label="Tout fermer" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_imchiclet_adhoc.xml b/indra/newview/skins/minimal/xui/fr/menu_imchiclet_adhoc.xml
new file mode 100644
index 0000000000..4d9a103058
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_imchiclet_adhoc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet AdHoc Menu">
+ <menu_item_call label="Mettre fin à la session" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_imchiclet_group.xml b/indra/newview/skins/minimal/xui/fr/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..59f97d8b48
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="Profil du groupe" name="Show Profile"/>
+ <menu_item_call label="Afficher la session" name="Chat"/>
+ <menu_item_call label="Mettre fin à la session" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_imchiclet_p2p.xml b/indra/newview/skins/minimal/xui/fr/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..ecc8cee413
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="Voir le profil" name="Show Profile"/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="Afficher la session" name="Send IM"/>
+ <menu_item_call label="Mettre fin à la session" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..231a175ee5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<toggleable_menu name="Gear Menu">
+ <menu_item_call label="Voir le profil" name="view_profile"/>
+ <menu_item_call label="Devenir amis" name="add_friend"/>
+ <menu_item_call label="IM" name="im"/>
+ <menu_item_call label="Téléporter" name="teleport"/>
+ <menu_item_call label="Ignorer" name="block"/>
+ <menu_item_call label="Ne plus ignorer" name="unblock"/>
+ <menu_item_call label="Signaler" name="report"/>
+ <menu_item_call label="Figer" name="freeze"/>
+ <menu_item_call label="Expulser" name="eject"/>
+ <menu_item_call label="Éjecter" name="kick"/>
+ <menu_item_call label="Représentant de l&apos;Assistance client" name="csr"/>
+ <menu_item_call label="Déboguer les textures" name="debug"/>
+ <menu_item_call label="Situer sur la carte" name="find_on_map"/>
+ <menu_item_call label="Zoomer en avant" name="zoom_in"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inspect_object_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..074bb54cdc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inspect_object_gear.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Toucher" name="touch"/>
+ <menu_item_call label="M&apos;asseoir" name="sit"/>
+ <menu_item_call label="Payer" name="pay"/>
+ <menu_item_call label="Acheter" name="buy"/>
+ <menu_item_call label="Prendre" name="take"/>
+ <menu_item_call label="Prendre une copie" name="take_copy"/>
+ <menu_item_call label="Ouvrir" name="open"/>
+ <menu_item_call label="Modifier" name="edit"/>
+ <menu_item_call label="Porter" name="wear"/>
+ <menu_item_call label="Ajouter" name="add"/>
+ <menu_item_call label="Signaler" name="report"/>
+ <menu_item_call label="Ignorer" name="block"/>
+ <menu_item_call label="Zoomer en avant" name="zoom_in"/>
+ <menu_item_call label="Supprimer" name="remove"/>
+ <menu_item_call label="En savoir plus" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inspect_self_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..fd48aa4f7d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="Self Pie">
+ <menu_item_call label="M&apos;asseoir" name="Sit Down Here"/>
+ <menu_item_call label="Me lever" name="Stand Up"/>
+ <menu_item_call label="Mes amis" name="Friends..."/>
+ <menu_item_call label="Mon profil" name="Profile..."/>
+ <menu_item_call label="Déboguer les textures" name="Debug..."/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inv_offer_chiclet.xml b/indra/newview/skins/minimal/xui/fr/menu_inv_offer_chiclet.xml
new file mode 100644
index 0000000000..a9b2883cca
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inv_offer_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="InvOfferChiclet Menu">
+ <menu_item_call label="Fermer" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inventory.xml b/indra/newview/skins/minimal/xui/fr/menu_inventory.xml
new file mode 100644
index 0000000000..a2279cf0ac
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inventory.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Acheter" name="Task Buy"/>
+ <menu_item_call label="Ouvrir" name="Task Open"/>
+ <menu_item_call label="Jouer" name="Task Play"/>
+ <menu_item_call label="Propriétés" name="Task Properties"/>
+ <menu_item_call label="Renommer" name="Task Rename"/>
+ <menu_item_call label="Supprimer" name="Task Remove"/>
+ <menu_item_call label="Vider la corbeille" name="Empty Trash"/>
+ <menu_item_call label="Vider les objets trouvés" name="Empty Lost And Found"/>
+ <menu_item_call label="Nouveau dossier" name="New Folder"/>
+ <menu_item_call label="Nouveau script" name="New Script"/>
+ <menu_item_call label="Nouvelle note" name="New Note"/>
+ <menu_item_call label="Nouveau geste" name="New Gesture"/>
+ <menu label="Nouveaux habits" name="New Clothes">
+ <menu_item_call label="Nouvelle chemise" name="New Shirt"/>
+ <menu_item_call label="Nouveau pantalon" name="New Pants"/>
+ <menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
+ <menu_item_call label="Nouvelles chaussettes" name="New Socks"/>
+ <menu_item_call label="Nouvelle veste" name="New Jacket"/>
+ <menu_item_call label="Nouvelle jupe" name="New Skirt"/>
+ <menu_item_call label="Nouveaux gants" name="New Gloves"/>
+ <menu_item_call label="Nouveau débardeur" name="New Undershirt"/>
+ <menu_item_call label="Nouveau caleçon" name="New Underpants"/>
+ <menu_item_call label="Nouveau masque alpha" name="New Alpha Mask"/>
+ <menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+ </menu>
+ <menu label="Nouvelles parties du corps" name="New Body Parts">
+ <menu_item_call label="Nouvelle silhouette" name="New Shape"/>
+ <menu_item_call label="Nouvelle peau" name="New Skin"/>
+ <menu_item_call label="Nouveaux cheveux" name="New Hair"/>
+ <menu_item_call label="Nouveaux yeux" name="New Eyes"/>
+ </menu>
+ <menu label="Changer de type" name="Change Type">
+ <menu_item_call label="Défaut" name="Default"/>
+ <menu_item_call label="Gants" name="Gloves"/>
+ <menu_item_call label="Veste" name="Jacket"/>
+ <menu_item_call label="Pantalon" name="Pants"/>
+ <menu_item_call label="Silhouette" name="Shape"/>
+ <menu_item_call label="Chaussures" name="Shoes"/>
+ <menu_item_call label="Chemise" name="Shirt"/>
+ <menu_item_call label="Jupe" name="Skirt"/>
+ <menu_item_call label="Caleçon" name="Underpants"/>
+ <menu_item_call label="Débardeur" name="Undershirt"/>
+ </menu>
+ <menu_item_call label="Téléporter" name="Landmark Open"/>
+ <menu_item_call label="Ouvrir" name="Animation Open"/>
+ <menu_item_call label="Ouvrir" name="Sound Open"/>
+ <menu_item_call label="Remplacer la tenue actuelle" name="Replace Outfit"/>
+ <menu_item_call label="Ajouter à la tenue actuelle" name="Add To Outfit"/>
+ <menu_item_call label="Enlever de la tenue actuelle" name="Remove From Outfit"/>
+ <menu_item_call label="Trouver l&apos;original" name="Find Original"/>
+ <menu_item_call label="Purger l&apos;objet" name="Purge Item"/>
+ <menu_item_call label="Restaurer l&apos;objet" name="Restore Item"/>
+ <menu_item_call label="Ouvrir" name="Open"/>
+ <menu_item_call label="Ouvrir l&apos;original" name="Open Original"/>
+ <menu_item_call label="Propriétés" name="Properties"/>
+ <menu_item_call label="Renommer" name="Rename"/>
+ <menu_item_call label="Copier l&apos;UUID (identifiant universel unique)" name="Copy Asset UUID"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Coller comme lien" name="Paste As Link"/>
+ <menu_item_call label="Supprimer" name="Remove Link"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Supprimer le dossier système" name="Delete System Folder"/>
+ <menu_item_call label="Démarrer le chat conférence" name="Conference Chat Folder"/>
+ <menu_item_call label="Jouer" name="Sound Play"/>
+ <menu_item_call label="À propos du repère" name="About Landmark"/>
+ <menu_item_call label="Jouer dans Second Life" name="Animation Play"/>
+ <menu_item_call label="Jouer localement" name="Animation Audition"/>
+ <menu_item_call label="Envoyer un message instantané" name="Send Instant Message"/>
+ <menu_item_call label="Offrir de téléporter..." name="Offer Teleport..."/>
+ <menu_item_call label="Démarrer le chat conférence" name="Conference Chat"/>
+ <menu_item_call label="Activer" name="Activate"/>
+ <menu_item_call label="Désactiver" name="Deactivate"/>
+ <menu_item_call label="Enregistrer sous" name="Save As"/>
+ <menu_item_call label="Détacher de vous" name="Detach From Yourself"/>
+ <menu_item_call label="Porter" name="Wearable And Object Wear"/>
+ <menu label="Attacher à" name="Attach To"/>
+ <menu label="Attacher au HUD " name="Attach To HUD"/>
+ <menu_item_call label="Modifier" name="Wearable Edit"/>
+ <menu_item_call label="Ajouter" name="Wearable Add"/>
+ <menu_item_call label="Enlever" name="Take Off"/>
+ <menu_item_call label="--aucune option--" name="--no options--"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inventory_add.xml b/indra/newview/skins/minimal/xui/fr/menu_inventory_add.xml
new file mode 100644
index 0000000000..fe096b4a7e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inventory_add.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Importer" name="upload">
+ <menu_item_call label="Image ([COST] L$)..." name="Upload Image"/>
+ <menu_item_call label="Son ([COST] L$)..." name="Upload Sound"/>
+ <menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
+ <menu_item_call label="Lot ([COST] L$ par fichier)..." name="Bulk Upload"/>
+ <menu_item_call label="Définir les droits de chargement par défaut" name="perm prefs"/>
+ </menu>
+ <menu_item_call label="Nouveau dossier" name="New Folder"/>
+ <menu_item_call label="Nouveau script" name="New Script"/>
+ <menu_item_call label="Nouvelle note" name="New Note"/>
+ <menu_item_call label="Nouveau geste" name="New Gesture"/>
+ <menu label="Nouveaux habits" name="New Clothes">
+ <menu_item_call label="Nouvelle chemise" name="New Shirt"/>
+ <menu_item_call label="Nouveau pantalon" name="New Pants"/>
+ <menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
+ <menu_item_call label="Nouvelles chaussettes" name="New Socks"/>
+ <menu_item_call label="Nouvelle veste" name="New Jacket"/>
+ <menu_item_call label="Nouvelle jupe" name="New Skirt"/>
+ <menu_item_call label="Nouveaux gants" name="New Gloves"/>
+ <menu_item_call label="Nouveau débardeur" name="New Undershirt"/>
+ <menu_item_call label="Nouveau caleçon" name="New Underpants"/>
+ <menu_item_call label="Nouvel alpha" name="New Alpha"/>
+ <menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+ </menu>
+ <menu label="Nouvelles parties du corps" name="New Body Parts">
+ <menu_item_call label="Nouvelle silhouette" name="New Shape"/>
+ <menu_item_call label="Nouvelle peau" name="New Skin"/>
+ <menu_item_call label="Nouveaux cheveux" name="New Hair"/>
+ <menu_item_call label="Nouveaux yeux" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_inventory_gear_default.xml b/indra/newview/skins/minimal/xui/fr/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..f28918ae14
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_inventory_gear_default.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_gear_default">
+ <menu_item_call label="Nouvelle fenêtre d&apos;inventaire" name="new_window"/>
+ <menu_item_check label="Trier par nom" name="sort_by_name"/>
+ <menu_item_check label="Trier en commençant par le plus récent" name="sort_by_recent"/>
+ <menu_item_check label="Dossiers système en premier" name="sort_system_folders_to_top"/>
+ <menu_item_call label="Afficher les filtres" name="show_filters"/>
+ <menu_item_call label="Réinitialiser les filtres" name="reset_filters"/>
+ <menu_item_call label="Fermer tous les dossiers" name="close_folders"/>
+ <menu_item_call label="Vider les objets trouvés" name="empty_lostnfound"/>
+ <menu_item_call label="Enregistrer la texture sous" name="Save Texture As"/>
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Trouver l&apos;original" name="Find Original"/>
+ <menu_item_call label="Trouver tous les liens" name="Find All Links"/>
+ <menu_item_call label="Vider la corbeille" name="empty_trash"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_land.xml b/indra/newview/skins/minimal/xui/fr/menu_land.xml
new file mode 100644
index 0000000000..b84daee3ae
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_land.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Land Pie">
+ <menu_item_call label="À propos du terrain" name="Place Information..."/>
+ <menu_item_call label="M&apos;asseoir ici" name="Sit Here"/>
+ <menu_item_call label="Acheter ce terrain" name="Land Buy"/>
+ <menu_item_call label="Acheter un pass" name="Land Buy Pass"/>
+ <menu_item_call label="Construire" name="Create"/>
+ <menu_item_call label="Modifier le terrain" name="Edit Terrain"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_landmark.xml b/indra/newview/skins/minimal/xui/fr/menu_landmark.xml
new file mode 100644
index 0000000000..73eaa4af7e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="Copier la SLurl" name="copy"/>
+ <menu_item_call label="Supprimer" name="delete"/>
+ <menu_item_call label="Créer un favori" name="pick"/>
+ <menu_item_call label="Ajouter à la barre des favoris" name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_login.xml b/indra/newview/skins/minimal/xui/fr/menu_login.xml
new file mode 100644
index 0000000000..400c77e51a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_login.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Login Menu">
+ <menu label="Moi" name="File">
+ <menu_item_call label="Préférences" name="Preferences..."/>
+ <menu_item_call label="Quitter [APP_NAME]" name="Quit"/>
+ </menu>
+ <menu label="Aide" name="Help">
+ <menu_item_call label="Aide de [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="À propos de [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu_item_check label="Afficher le menu de débogage" name="Show Debug Menu"/>
+ <menu label="Débogage" name="Debug">
+ <menu_item_call label="Afficher les paramètres de débogage" name="Debug Settings"/>
+ <menu_item_call label="Paramètres de couleurs/interface" name="UI/Color Settings"/>
+ <menu_item_call label="Outil d&apos;aperçu XUI" name="UI Preview Tool"/>
+ <menu label="Tests de l&apos;interface" name="UI Tests"/>
+ <menu_item_call label="Définir la taille de la fenêtre..." name="Set Window Size..."/>
+ <menu_item_call label="Afficher les conditions d&apos;utilisation" name="TOS"/>
+ <menu_item_call label="Afficher le message critique" name="Critical"/>
+ <menu_item_call label="Test du navigateur de médias" name="Web Browser Test"/>
+ <menu_item_call label="Test de la fenêtre flottante du contenu Web" name="Web Content Floater Test"/>
+ <menu_item_check label="Afficher le sélecteur de grille" name="Show Grid Picker"/>
+ <menu_item_call label="Afficher la console des notifications" name="Show Notifications Console"/>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_mini_map.xml b/indra/newview/skins/minimal/xui/fr/menu_mini_map.xml
new file mode 100644
index 0000000000..b9d0a70383
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_mini_map.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Zoom rapproché" name="Zoom Close"/>
+ <menu_item_call label="Zoom moyen" name="Zoom Medium"/>
+ <menu_item_call label="Zoom éloigné" name="Zoom Far"/>
+ <menu_item_call label="Zoom par défaut" name="Zoom Default"/>
+ <menu_item_check label="Faire pivoter la carte" name="Rotate Map"/>
+ <menu_item_check label="Centrage auto" name="Auto Center"/>
+ <menu_item_call label="Arrêter de suivre" name="Stop Tracking"/>
+ <menu_item_call label="Carte du monde" name="World Map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_navbar.xml b/indra/newview/skins/minimal/xui/fr/menu_navbar.xml
new file mode 100644
index 0000000000..08d810b653
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="Voir les coordonnées" name="Show Coordinates"/>
+ <menu_item_check label="Afficher les propriétés de la parcelle" name="Show Parcel Properties"/>
+ <menu_item_call label="Repère" name="Landmark"/>
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_nearby_chat.xml b/indra/newview/skins/minimal/xui/fr/menu_nearby_chat.xml
new file mode 100644
index 0000000000..99e22aeff7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="Afficher les personnes près de vous..." name="nearby_people"/>
+ <menu_item_check label="Afficher le texte ignoré" name="muted_text"/>
+ <menu_item_check label="Afficher les icônes des Buddy" name="show_buddy_icons"/>
+ <menu_item_check label="Afficher les noms" name="show_names"/>
+ <menu_item_check label="Afficher les icônes et les noms" name="show_icons_and_names"/>
+ <menu_item_call label="Taille de la police" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_notification_well_button.xml b/indra/newview/skins/minimal/xui/fr/menu_notification_well_button.xml
new file mode 100644
index 0000000000..323bfdbf16
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_notification_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Notification Well Button Context Menu">
+ <menu_item_call label="Tout fermer" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_object.xml b/indra/newview/skins/minimal/xui/fr/menu_object.xml
new file mode 100644
index 0000000000..a50a9df4b1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_object.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Object Pie">
+ <menu_item_call label="Toucher" name="Object Touch">
+ <menu_item_call.on_enable name="EnableTouch" parameter="Toucher"/>
+ </menu_item_call>
+ <menu_item_call label="Modifier" name="Edit..."/>
+ <menu_item_call label="Construire" name="Build"/>
+ <menu_item_call label="Ouvrir" name="Open"/>
+ <menu_item_call label="M&apos;asseoir ici" name="Object Sit"/>
+ <menu_item_call label="Me lever" name="Object Stand Up"/>
+ <menu_item_call label="Profil de l&apos;objet" name="Object Inspect"/>
+ <menu_item_call label="Zoomer en avant" name="Zoom In"/>
+ <context_menu label="Porter" name="Put On">
+ <menu_item_call label="Porter" name="Wear"/>
+ <menu_item_call label="Ajouter" name="Add"/>
+ <context_menu label="Attacher" name="Object Attach"/>
+ <context_menu label="Attacher HUD" name="Object Attach HUD"/>
+ </context_menu>
+ <context_menu label="Supprimer" name="Remove">
+ <menu_item_call label="Signaler une infraction" name="Report Abuse..."/>
+ <menu_item_call label="Ignorer" name="Object Mute"/>
+ <menu_item_call label="Retour" name="Return..."/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ </context_menu>
+ <menu_item_call label="Prendre" name="Pie Object Take"/>
+ <menu_item_call label="Prendre une copie" name="Take Copy"/>
+ <menu_item_call label="Payer" name="Pay..."/>
+ <menu_item_call label="Acheter" name="Buy..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_object_icon.xml b/indra/newview/skins/minimal/xui/fr/menu_object_icon.xml
new file mode 100644
index 0000000000..69f8e88a0d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="Profil de l&apos;objet..." name="Object Profile"/>
+ <menu_item_call label="Ignorer..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_outfit_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_outfit_gear.xml
new file mode 100644
index 0000000000..5db7f176b5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_outfit_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Outfit">
+ <menu_item_call label="Porter - Remplacer la tenue actuelle" name="wear"/>
+ <menu_item_call label="Porter - Ajouter à la tenue actuelle" name="wear_add"/>
+ <menu_item_call label="Enlever - Supprimer de la tenue actuelle" name="take_off"/>
+ <menu label="Nouveaux habits" name="New Clothes">
+ <menu_item_call label="Nouvelle chemise" name="New Shirt"/>
+ <menu_item_call label="Nouveau pantalon" name="New Pants"/>
+ <menu_item_call label="Nouvelles chaussures" name="New Shoes"/>
+ <menu_item_call label="Nouvelles chaussettes" name="New Socks"/>
+ <menu_item_call label="Nouvelle veste" name="New Jacket"/>
+ <menu_item_call label="Nouvelle jupe" name="New Skirt"/>
+ <menu_item_call label="Nouveaux gants" name="New Gloves"/>
+ <menu_item_call label="Nouveau débardeur" name="New Undershirt"/>
+ <menu_item_call label="Nouveau caleçon" name="New Underpants"/>
+ <menu_item_call label="Nouvel alpha" name="New Alpha"/>
+ <menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+ </menu>
+ <menu label="Nouvelles parties du corps" name="New Body Parts">
+ <menu_item_call label="Nouvelle silhouette" name="New Shape"/>
+ <menu_item_call label="Nouvelle peau" name="New Skin"/>
+ <menu_item_call label="Nouveaux cheveux" name="New Hair"/>
+ <menu_item_call label="Nouveaux yeux" name="New Eyes"/>
+ </menu>
+ <menu_item_call label="Renommer la tenue" name="rename"/>
+ <menu_item_call label="Supprimer la tenue" name="delete_outfit"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_outfit_tab.xml b/indra/newview/skins/minimal/xui/fr/menu_outfit_tab.xml
new file mode 100644
index 0000000000..2a7f618e07
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_outfit_tab.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit">
+ <menu_item_call label="Porter - Remplacer la tenue actuelle" name="wear_replace"/>
+ <menu_item_call label="Porter - Ajouter à la tenue actuelle" name="wear_add"/>
+ <menu_item_call label="Enlever - Supprimer de la tenue actuelle" name="take_off"/>
+ <menu_item_call label="Modifier la tenue" name="edit"/>
+ <menu_item_call label="Renommer la tenue" name="rename"/>
+ <menu_item_call label="Supprimer la tenue" name="delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_participant_list.xml b/indra/newview/skins/minimal/xui/fr/menu_participant_list.xml
new file mode 100644
index 0000000000..f91a30f6bb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_participant_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="Trier par nom" name="SortByName"/>
+ <menu_item_check label="Trier par intervenants récents" name="SortByRecentSpeakers"/>
+ <menu_item_call label="Voir le profil" name="View Profile"/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Payer" name="Pay"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="View Icons"/>
+ <menu_item_check label="Bloquer le chat vocal" name="Block/Unblock"/>
+ <menu_item_check label="Ignorer le texte" name="MuteText"/>
+ <context_menu label="Options du modérateur" name="Moderator Options">
+ <menu_item_check label="Autoriser les chats écrits" name="AllowTextChat"/>
+ <menu_item_call label="Ignorer ce participant" name="ModerateVoiceMuteSelected"/>
+ <menu_item_call label="Ne plus ignorer ce participant" name="ModerateVoiceUnMuteSelected"/>
+ <menu_item_call label="Ignorer les autres" name="ModerateVoiceMute"/>
+ <menu_item_call label="Ne plus ignorer les autres" name="ModerateVoiceUnmute"/>
+ </context_menu>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_friends_view_sort.xml b/indra/newview/skins/minimal/xui/fr/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..a6170a6c16
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_friends_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Trier par nom" name="sort_name"/>
+ <menu_item_check label="Trier par statut" name="sort_status"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="view_icons"/>
+ <menu_item_check label="Afficher les droits octroyés" name="view_permissions"/>
+ <menu_item_call label="Afficher les résidents et les objets ignorés" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_groups.xml b/indra/newview/skins/minimal/xui/fr/menu_people_groups.xml
new file mode 100644
index 0000000000..eb51b4cf7e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_groups.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Afficher les infos" name="View Info"/>
+ <menu_item_call label="Chat" name="Chat"/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Activer" name="Activate"/>
+ <menu_item_call label="Quitter" name="Leave"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_groups_view_sort.xml b/indra/newview/skins/minimal/xui/fr/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..34f949cf2c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Afficher les icônes des groupes" name="Display Group Icons"/>
+ <menu_item_call label="Quitter le groupe sélectionné" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/fr/menu_people_nearby.xml
new file mode 100644
index 0000000000..f153ed15ae
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_nearby.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="Voir le profil" name="View Profile"/>
+ <menu_item_call label="Devenir amis" name="Add Friend"/>
+ <menu_item_call label="Supprimer cet ami" name="Remove Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Carte" name="Map"/>
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Payer" name="Pay"/>
+ <menu_item_check label="Ignorer/Ne plus ignorer" name="Block/Unblock"/>
+ <menu_item_call label="Téléporter" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_nearby_multiselect.xml b/indra/newview/skins/minimal/xui/fr/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..8400ec0a14
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_nearby_multiselect.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="Devenir amis" name="Add Friends"/>
+ <menu_item_call label="Supprimer des amis" name="Remove Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Appeler" name="Call"/>
+ <menu_item_call label="Partager" name="Share"/>
+ <menu_item_call label="Payer" name="Pay"/>
+ <menu_item_call label="Proposer une téléportation" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_nearby_view_sort.xml b/indra/newview/skins/minimal/xui/fr/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..45f97e062e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Trier par intervenants récents" name="sort_by_recent_speakers"/>
+ <menu_item_check label="Trier par nom" name="sort_name"/>
+ <menu_item_check label="Trier par distance" name="sort_distance"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="view_icons"/>
+ <menu_item_call label="Afficher les résidents et les objets interdits" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_people_recent_view_sort.xml b/indra/newview/skins/minimal/xui/fr/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..93b90ae61c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Trier en commençant par le plus récent" name="sort_most"/>
+ <menu_item_check label="Trier par nom" name="sort_name"/>
+ <menu_item_check label="Afficher les icônes des résidents" name="view_icons"/>
+ <menu_item_call label="Afficher les résidents et les objets ignorés" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_picks.xml b/indra/newview/skins/minimal/xui/fr/menu_picks.xml
new file mode 100644
index 0000000000..7d7174d43c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Infos" name="pick_info"/>
+ <menu_item_call label="Modifier" name="pick_edit"/>
+ <menu_item_call label="Téléporter" name="pick_teleport"/>
+ <menu_item_call label="Carte" name="pick_map"/>
+ <menu_item_call label="Supprimer" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_picks_plus.xml b/indra/newview/skins/minimal/xui/fr/menu_picks_plus.xml
new file mode 100644
index 0000000000..b6cde6d6e2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="Nouveau favori" name="create_pick"/>
+ <menu_item_call label="Nouvelle petite annonce" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_place.xml b/indra/newview/skins/minimal/xui/fr/menu_place.xml
new file mode 100644
index 0000000000..6b0f4db752
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="Enregistrer comme repère" name="landmark"/>
+ <menu_item_call label="Créer un favori" name="pick"/>
+ <menu_item_call label="Acheter un pass" name="pass"/>
+ <menu_item_call label="Modifier" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_place_add_button.xml b/indra/newview/skins/minimal/xui/fr/menu_place_add_button.xml
new file mode 100644
index 0000000000..92f9e7719d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Ajouter un dossier" name="add_folder"/>
+ <menu_item_call label="Ajouter un repère" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_places_gear_folder.xml b/indra/newview/skins/minimal/xui/fr/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..3570bdec7f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Ajouter un repère" name="add_landmark"/>
+ <menu_item_call label="Ajouter un dossier" name="add_folder"/>
+ <menu_item_call label="Couper" name="cut"/>
+ <menu_item_call label="Copier" name="copy_folder"/>
+ <menu_item_call label="Coller" name="paste"/>
+ <menu_item_call label="Renommer" name="rename"/>
+ <menu_item_call label="Supprimer" name="delete"/>
+ <menu_item_call label="Agrandir" name="expand"/>
+ <menu_item_call label="Réduire" name="collapse"/>
+ <menu_item_call label="Développer tous les dossiers" name="expand_all"/>
+ <menu_item_call label="Réduire tous les dossiers" name="collapse_all"/>
+ <menu_item_check label="Trier par date" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_places_gear_landmark.xml b/indra/newview/skins/minimal/xui/fr/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..5491c1b3fc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Téléporter" name="teleport"/>
+ <menu_item_call label="Plus d&apos;informations" name="more_info"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Ajouter un repère" name="add_landmark"/>
+ <menu_item_call label="Ajouter un dossier" name="add_folder"/>
+ <menu_item_call label="Couper" name="cut"/>
+ <menu_item_call label="Copier le repère" name="copy_landmark"/>
+ <menu_item_call label="Copier la SLurl" name="copy_slurl"/>
+ <menu_item_call label="Coller" name="paste"/>
+ <menu_item_call label="Renommer" name="rename"/>
+ <menu_item_call label="Supprimer" name="delete"/>
+ <menu_item_call label="Développer tous les dossiers" name="expand_all"/>
+ <menu_item_call label="Réduire tous les dossiers" name="collapse_all"/>
+ <menu_item_check label="Trier par date" name="sort_by_date"/>
+ <menu_item_call label="Créer un favori" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_profile_overflow.xml b/indra/newview/skins/minimal/xui/fr/menu_profile_overflow.xml
new file mode 100644
index 0000000000..ddf898b791
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_profile_overflow.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="Carte" name="show_on_map"/>
+ <menu_item_call label="Payer" name="pay"/>
+ <menu_item_call label="Partager" name="share"/>
+ <menu_item_call label="Ignorer" name="block"/>
+ <menu_item_call label="Ne plus ignorer" name="unblock"/>
+ <menu_item_call label="Éjecter" name="kick"/>
+ <menu_item_call label="Figer" name="freeze"/>
+ <menu_item_call label="Libérer" name="unfreeze"/>
+ <menu_item_call label="Représentant du service consommateur" name="csr"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_save_outfit.xml b/indra/newview/skins/minimal/xui/fr/menu_save_outfit.xml
new file mode 100644
index 0000000000..f78db411b3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_save_outfit.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_outfit_menu">
+ <menu_item_call label="Enregistrer" name="save_outfit"/>
+ <menu_item_call label="Enregistrer sous" name="save_as_new_outfit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_script_chiclet.xml b/indra/newview/skins/minimal/xui/fr/menu_script_chiclet.xml
new file mode 100644
index 0000000000..46efa30bd6
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_script_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="ScriptChiclet Menu">
+ <menu_item_call label="Fermer" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_slurl.xml b/indra/newview/skins/minimal/xui/fr/menu_slurl.xml
new file mode 100644
index 0000000000..ddfa5c0849
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_slurl.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="À propos de l&apos;URL" name="about_url"/>
+ <menu_item_call label="Téléporter vers l&apos;URL" name="teleport_to_url"/>
+ <menu_item_call label="Carte" name="show_on_map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_teleport_history_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..3dea662cc2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="Développer tous les dossiers" name="Expand all folders"/>
+ <menu_item_call label="Réduire tous les dossiers" name="Collapse all folders"/>
+ <menu_item_call label="Effacer l&apos;historique des téléportations" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_teleport_history_item.xml b/indra/newview/skins/minimal/xui/fr/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..fb4582dbce
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Téléporter" name="Teleport"/>
+ <menu_item_call label="Plus d&apos;informations" name="More Information"/>
+ <menu_item_call label="Copier dans le presse-papiers" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_teleport_history_tab.xml b/indra/newview/skins/minimal/xui/fr/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..369680985d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Ouvrir" name="TabOpen"/>
+ <menu_item_call label="Fermer" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_text_editor.xml b/indra/newview/skins/minimal/xui/fr/menu_text_editor.xml
new file mode 100644
index 0000000000..b6f429aec9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="Couper" name="Cut"/>
+ <menu_item_call label="Copier" name="Copy"/>
+ <menu_item_call label="Coller" name="Paste"/>
+ <menu_item_call label="Supprimer" name="Delete"/>
+ <menu_item_call label="Tout sélectionner" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_topinfobar.xml b/indra/newview/skins/minimal/xui/fr/menu_topinfobar.xml
new file mode 100644
index 0000000000..dc68f40fe7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_topinfobar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_topinfobar">
+ <menu_item_check label="Afficher les coordonnées" name="Show Coordinates"/>
+ <menu_item_check label="Afficher les propriétés de la parcelle" name="Show Parcel Properties"/>
+ <menu_item_call label="Repère" name="Landmark"/>
+ <menu_item_call label="Copier" name="Copy"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_agent.xml b/indra/newview/skins/minimal/xui/fr/menu_url_agent.xml
new file mode 100644
index 0000000000..5ed627fbc3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Voir le profil du résident" name="show_agent"/>
+ <menu_item_call label="Copier le nom dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_group.xml b/indra/newview/skins/minimal/xui/fr/menu_url_group.xml
new file mode 100644
index 0000000000..de90c3ff7e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Voir le profil du groupe" name="show_group"/>
+ <menu_item_call label="Copier le groupe dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_http.xml b/indra/newview/skins/minimal/xui/fr/menu_url_http.xml
new file mode 100644
index 0000000000..5e96352999
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Ouvrir la page Web" name="url_open"/>
+ <menu_item_call label="Ouvrir dans un navigateur interne" name="url_open_internal"/>
+ <menu_item_call label="Ouvrir dans un navigateur externe" name="url_open_external"/>
+ <menu_item_call label="Copier l&apos;URL dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_inventory.xml b/indra/newview/skins/minimal/xui/fr/menu_url_inventory.xml
new file mode 100644
index 0000000000..8ab88b4be7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher l&apos;article d&apos;inventaire" name="show_item"/>
+ <menu_item_call label="Copier le nom dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_map.xml b/indra/newview/skins/minimal/xui/fr/menu_url_map.xml
new file mode 100644
index 0000000000..67e6986f5d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Me téléporter à cet endroit" name="teleport_to_location"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_objectim.xml b/indra/newview/skins/minimal/xui/fr/menu_url_objectim.xml
new file mode 100644
index 0000000000..f581c3ef9d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher les informations sur l&apos;objet" name="show_object"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Me téléporter à l&apos;emplacement de l&apos;objet" name="teleport_to_object"/>
+ <menu_item_call label="Copier le nom de l&apos;objet dans le presse-papiers" name="url_copy_label"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_parcel.xml b/indra/newview/skins/minimal/xui/fr/menu_url_parcel.xml
new file mode 100644
index 0000000000..07b0eeca49
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher les informations sur la parcelle" name="show_parcel"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_slapp.xml b/indra/newview/skins/minimal/xui/fr/menu_url_slapp.xml
new file mode 100644
index 0000000000..f4b7e212ca
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Exécuter cette commande" name="run_slapp"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_slurl.xml b/indra/newview/skins/minimal/xui/fr/menu_url_slurl.xml
new file mode 100644
index 0000000000..e44943cf15
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Afficher les informations sur ce lieu" name="show_place"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Me téléporter à cet endroit" name="teleport_to_location"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_url_teleport.xml b/indra/newview/skins/minimal/xui/fr/menu_url_teleport.xml
new file mode 100644
index 0000000000..a5075a2740
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Me téléporter à cet endroit." name="teleport"/>
+ <menu_item_call label="Voir sur la carte" name="show_on_map"/>
+ <menu_item_call label="Copier la SLurl dans le presse-papiers" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_viewer.xml b/indra/newview/skins/minimal/xui/fr/menu_viewer.xml
new file mode 100644
index 0000000000..bd1c077f52
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_viewer.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Main Menu">
+ <menu label="Aide" name="Help">
+ <menu_item_call label="Aide de [SECOND_LIFE]" name="Second Life Help"/>
+ </menu>
+ <menu label="Avancé" name="Advanced">
+ <menu label="Raccourcis" name="Shortcuts">
+ <menu_item_check label="Voler" name="Fly"/>
+ <menu_item_call label="Fermer la fenêtre" name="Close Window"/>
+ <menu_item_call label="Fermer toutes les fenêtres" name="Close All Windows"/>
+ <menu_item_call label="Réinitialiser la vue" name="Reset View"/>
+ </menu>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_wearable_list_item.xml b/indra/newview/skins/minimal/xui/fr/menu_wearable_list_item.xml
new file mode 100644
index 0000000000..187cb4bcd2
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_wearable_list_item.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit Wearable Context Menu">
+ <menu_item_call label="Remplacer" name="wear_replace"/>
+ <menu_item_call label="Porter" name="wear_wear"/>
+ <menu_item_call label="Ajouter" name="wear_add"/>
+ <menu_item_call label="Enlever / Détacher" name="take_off_or_detach"/>
+ <menu_item_call label="Détacher" name="detach"/>
+ <context_menu label="Attacher à" name="wearable_attach_to"/>
+ <context_menu label="Attacher au HUD" name="wearable_attach_to_hud"/>
+ <menu_item_call label="Enlever" name="take_off"/>
+ <menu_item_call label="Modifier" name="edit"/>
+ <menu_item_call label="Profil de l&apos;article" name="object_profile"/>
+ <menu_item_call label="Afficher l&apos;original" name="show_original"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_wearing_gear.xml b/indra/newview/skins/minimal/xui/fr/menu_wearing_gear.xml
new file mode 100644
index 0000000000..0ca9fe1879
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_wearing_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Wearing">
+ <menu_item_call label="Modifier la tenue" name="edit"/>
+ <menu_item_call label="Enlever" name="takeoff"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/fr/menu_wearing_tab.xml b/indra/newview/skins/minimal/xui/fr/menu_wearing_tab.xml
new file mode 100644
index 0000000000..4d88445506
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/menu_wearing_tab.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Wearing">
+ <menu_item_call label="Enlever" name="take_off"/>
+ <menu_item_call label="Détacher" name="detach"/>
+ <menu_item_call label="Modifier la tenue" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/fr/notifications.xml b/indra/newview/skins/minimal/xui/fr/notifications.xml
new file mode 100644
index 0000000000..41dd42c39f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/notifications.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<notifications>
+ <notification name="UserGiveItem">
+ [NAME_SLURL] vous offre [ITEM_SLURL]. Pour utiliser cet article, vous devez passer en mode Avancé. L&apos;article se trouve dans votre inventaire. Pour changer de mode, quittez l&apos;application, redémarrez-la, puis sélectionnez un autre mode sur l&apos;écran de connexion.
+ <form name="form">
+ <button name="Show" text="Garder l&apos;article"/>
+ <button name="Discard" text="Refuser l&apos;article"/>
+ <button name="Mute" text="Ignorer l&apos;utilisateur"/>
+ </form>
+ </notification>
+ <notification name="ObjectGiveItem">
+ Un objet nommé &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; appartenant à [NAME_SLURL] vous offre [ITEM_SLURL]. Pour utiliser cet article, vous devez passer en mode Avancé. L&apos;article se trouve dans votre inventaire. Pour changer de mode, quittez l&apos;application, redémarrez-la, puis sélectionnez un autre mode sur l&apos;écran de connexion.
+ <form name="form">
+ <button name="Keep" text="Garder l&apos;article"/>
+ <button name="Discard" text="Refuser l&apos;article"/>
+ <button name="Mute" text="Ignorer l&apos;objet"/>
+ </form>
+ </notification>
+</notifications>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/fr/panel_bottomtray.xml
new file mode 100644
index 0000000000..ef62901e99
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_bottomtray.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="DragIndicationImageName" value="Accordion_ArrowOpened_Off"/>
+ <string name="SpeakBtnToolTip" value="Active/Désactive le micro"/>
+ <string name="VoiceControlBtnToolTip" value="Affiche/Masque le panneau de contrôle de la voix"/>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_list label="Geste" name="Gesture" tool_tip="Affiche/Masque les gestes"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <bottomtray_button label="Affichage" name="camera_btn" tool_tip="Affiche/Masque le contrôle de la caméra"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Destinations" name="destination_btn" tool_tip="Afficher la fenêtre des personnes."/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Mon avatar" name="avatar_btn"/>
+ </layout_panel>
+ <layout_panel name="people_panel">
+ <bottomtray_button label="Personnes" name="show_people_button" tool_tip="Afficher la fenêtre des personnes."/>
+ </layout_panel>
+ <layout_panel name="profile_panel">
+ <bottomtray_button label="Profil" name="show_profile_btn" tool_tip="Afficher la fenêtre de profil."/>
+ </layout_panel>
+ <layout_panel name="howto_panel">
+ <bottomtray_button label="Aide rapide" name="show_help_btn" tool_tip="Ouvrir les rubriques d&apos;aide rapide Second Life."/>
+ </layout_panel>
+ <layout_panel name="im_well_panel">
+ <chiclet_im_well name="im_well">
+ <button name="Unread IM messages" tool_tip="Conversations"/>
+ </chiclet_im_well>
+ </layout_panel>
+ <layout_panel name="notification_well_panel">
+ <chiclet_notification name="notification_well">
+ <button name="Unread" tool_tip="Notifications"/>
+ </chiclet_notification>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/fr/panel_group_control_panel.xml
new file mode 100644
index 0000000000..676fa1d222
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_group_control_panel.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="vertical_stack">
+ <layout_panel name="end_call_btn_panel">
+ <button label="Quitter l&apos;appel" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Ouvrir contrôles vocaux" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/fr/panel_im_control_panel.xml
new file mode 100644
index 0000000000..1f2169e22c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_im_control_panel.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <text name="avatar_name" value="Inconnu"/>
+ <layout_stack name="button_stack">
+ <layout_panel name="view_profile_btn_panel">
+ <button label="Profil" name="view_profile_btn"/>
+ </layout_panel>
+ <layout_panel name="add_friend_btn_panel">
+ <button label="Devenir amis" name="add_friend_btn"/>
+ </layout_panel>
+ <layout_panel name="teleport_btn_panel">
+ <button label="Téléporter" name="teleport_btn" tool_tip="Proposer de téléporter cette personne"/>
+ </layout_panel>
+ <layout_panel name="share_btn_panel">
+ <button label="Partager" name="share_btn"/>
+ </layout_panel>
+ <layout_panel name="pay_btn_panel">
+ <button label="Payer" name="pay_btn"/>
+ </layout_panel>
+ <layout_panel name="call_btn_panel">
+ <button label="Appeler" name="call_btn"/>
+ </layout_panel>
+ <layout_panel name="end_call_btn_panel">
+ <button label="Quitter l&apos;appel" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Contrôles vocaux" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_login.xml b/indra/newview/skins/minimal/xui/fr/panel_login.xml
new file mode 100644
index 0000000000..0869778a54
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_login.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_login">
+ <panel.string name="create_account_url">
+ http://fr.secondlife.com/registration/
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=fr
+ </panel.string>
+ <layout_stack name="login_widgets">
+ <layout_panel name="login">
+ <text name="username_text">
+ Nom d&apos;utilisateur :
+ </text>
+ <combo_box name="username_combo" tool_tip="Nom d&apos;utilisateur que vous avez choisi lors de votre inscription (par exemple, bobsmith12 ou Steller Sunshine)."/>
+ <text name="password_text">
+ Mot de passe :
+ </text>
+ <check_box label="Enregistrer" name="remember_check"/>
+ <button label="Connexion" name="connect_btn"/>
+ <text name="mode_selection_text">
+ Mode :
+ </text>
+ <combo_box name="mode_combo" tool_tip="Sélectionnez un mode. Pour une exploration facile et rapide avec chat, choisissez Basique. Pour accéder à plus de fonctionnalités, choisissez Avancé.">
+ <combo_box.item label="Basique" name="Basic"/>
+ <combo_box.item label="Avancé" name="Advanced"/>
+ </combo_box>
+ </layout_panel>
+ <layout_panel name="links">
+ <text name="create_new_account_text">
+ S&apos;inscrire
+ </text>
+ <text name="forgot_password_text">
+ Nom d&apos;utilisateur ou mot de passe oublié ?
+ </text>
+ <text name="login_help">
+ Besoin d&apos;aide ?
+ </text>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/fr/panel_navigation_bar.xml
new file mode 100644
index 0000000000..45caf2323d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_navigation_bar.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <pull_button name="back_btn" tool_tip="Revenir à l&apos;emplacement précédent"/>
+ <pull_button name="forward_btn" tool_tip="Avancer d&apos;un emplacement"/>
+ <button name="home_btn" tool_tip="Me téléporter jusqu&apos;à mon domicile"/>
+ <location_input label="Emplacement" name="location_combo"/>
+ <search_combo_box label="Rechercher" name="search_combo_box" tool_tip="Rechercher">
+ <combo_editor label="Rechercher dans [SECOND_LIFE]" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+ <favorites_bar name="favorite" tool_tip="Faites glisser des repères ici pour un accès rapide à vos lieux favoris dans Second Life.">
+ <label name="favorites_bar_label" tool_tip="Faites glisser des repères ici pour un accès rapide à vos lieux favoris dans Second Life.">
+ Favoris
+ </label>
+ <chevron_button name="&gt;&gt;" tool_tip="Afficher d&apos;avantage de Favoris"/>
+ </favorites_bar>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_people.xml b/indra/newview/skins/minimal/xui/fr/panel_people.xml
new file mode 100644
index 0000000000..88409a2a86
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_people.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="Résidents" name="people_panel">
+ <string name="no_recent_people" value="Personne de récent. Vous recherchez des résidents avec qui passer du temps ? Essayez avec le bouton Destinations ci-dessous."/>
+ <string name="no_filtered_recent_people" value="Personne de récent portant ce nom."/>
+ <string name="no_one_near" value="Personne près de vous. Vous recherchez des résidents avec qui passer du temps ? Essayez avec le bouton Destinations ci-dessous."/>
+ <string name="no_one_filtered_near" value="Personne près de vous portant ce nom."/>
+ <string name="no_friends_online" value="Pas d&apos;amis connectés"/>
+ <string name="no_friends" value="Pas d&apos;amis"/>
+ <string name="no_friends_msg">
+ Pour ajouter un résident à votre liste d&apos;amis, cliquez-droit dessus.
+Vous recherchez des résidents avec qui passer du temps ? Essayez avec le bouton Destinations ci-dessous.
+ </string>
+ <string name="no_filtered_friends_msg">
+ Vous n&apos;avez pas trouvé ce que vous cherchiez ? Essayez avec le bouton Destinations ci-dessous.
+ </string>
+ <string name="people_filter_label" value="Filtrer les personnes"/>
+ <string name="groups_filter_label" value="Filtrer les groupes"/>
+ <string name="no_filtered_groups_msg" value="Vous n&apos;avez pas trouvé ce que vous cherchiez ? Essayez [secondlife:///app/search/groups/[SEARCH_TERM] Rechercher]."/>
+ <string name="no_groups_msg" value="Vous souhaitez trouver des groupes à rejoindre ? Utilisez [secondlife:///app/search/groups Rechercher]."/>
+ <string name="MiniMapToolTipMsg" value="[REGION](Carte : double-clic ; Panoramique : Maj + faire glisser)"/>
+ <string name="AltMiniMapToolTipMsg" value="[REGION](Téléportation : double-clic ; Panoramique : Maj + faire glisser)"/>
+ <filter_editor label="Filtre" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="PRÈS DE VOUS" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel"/>
+ </panel>
+ <panel label="MES AMIS" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="En ligne"/>
+ <accordion_tab name="tab_all" title="Tout"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <layout_stack name="bottom_panel">
+ <layout_panel name="trash_btn_panel">
+ <dnd_button name="del_btn" tool_tip="Supprimer le résident sélectionné de votre liste d&apos;amis."/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ </panel>
+ <panel label="RÉCENT" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="add_friend_btn" tool_tip="Ajouter le résident sélectionné à votre liste d&apos;amis"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <layout_stack name="bottom_bar_ls">
+ <layout_panel name="view_profile_btn_lp">
+ <button label="Profil" name="view_profile_btn" tool_tip="Afficher la photo, les groupes et autres infos des résidents"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="IM" name="im_btn" tool_tip="Ouvrir une session IM"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Téléporter" name="teleport_btn" tool_tip="Proposer une téléportation"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack name="bottom_bar_ls1">
+ <layout_panel name="group_info_btn_lp">
+ <button label="Profil du groupe" name="group_info_btn" tool_tip="Afficher les informations sur le groupe"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Chat de groupe" name="chat_btn" tool_tip="Ouvrir une session de chat"/>
+ </layout_panel>
+ <layout_panel name="group_call_btn_lp">
+ <button label="Appel de groupe" name="group_call_btn" tool_tip="Appeler ce groupe"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_side_tray_tab_caption.xml b/indra/newview/skins/minimal/xui/fr/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..45efbdc980
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_side_tray_tab_caption.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="Panneau latéral"/>
+ <button name="undock" tool_tip="Détacher"/>
+ <button name="dock" tool_tip="Attacher"/>
+ <button name="show_help" tool_tip="Afficher l&apos;aide"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/fr/panel_status_bar.xml b/indra/newview/skins/minimal/xui/fr/panel_status_bar.xml
new file mode 100644
index 0000000000..69aec99e1d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/fr/panel_status_bar.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="status">
+ <panel.string name="StatBarDaysOfWeek">
+ Sunday:Monday:Tuesday:Wednesday:Thursday:Friday:Saturday
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
+ January:February:March:April:May:June:July:August:September:October:November:December
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
+ Perte de paquets
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
+ Bande passante
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ [AMT] L$
+ </panel.string>
+ <panel name="balance_bg">
+ <text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="20 L$"/>
+ <button label="ACHETER L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$"/>
+ </panel>
+ <text name="TimeText" tool_tip="Heure actuelle (Pacifique)">
+ 00h00 PST
+ </text>
+ <button name="media_toggle_btn" tool_tip="Arrêter tous les médias (musique, vidéo, pages web)"/>
+ <button name="volume_btn" tool_tip="Contrôle du volume global"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/floater_camera.xml b/indra/newview/skins/minimal/xui/pt/floater_camera.xml
new file mode 100644
index 0000000000..4f3729c623
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/floater_camera.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
+ Girar a Câmera ao redor do Foco
+ </floater.string>
+ <floater.string name="zoom_tooltip">
+ Aproximar a Câmera in direção ao Foco
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Mover a Câmera para Cima e para Baixo, para a Esquerda e para a Direita
+ </floater.string>
+ <floater.string name="camera_modes_title">
+ Modos de câmera
+ </floater.string>
+ <floater.string name="pan_mode_title">
+ Pan zoom orbital
+ </floater.string>
+ <floater.string name="presets_mode_title">
+ Ângulos predefinidos
+ </floater.string>
+ <floater.string name="free_mode_title">
+ Visualizar objeto
+ </floater.string>
+ <panel name="controls">
+ <panel name="preset_views_list">
+ <panel_camera_item name="front_view">
+ <panel_camera_item.text name="front_view_text">
+ Vista frontal
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="group_view">
+ <panel_camera_item.text name="side_view_text">
+ Vista lateral
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="rear_view">
+ <panel_camera_item.text name="rear_view_text">
+ Vista de trás
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="camera_modes_list">
+ <panel_camera_item name="object_view">
+ <panel_camera_item.text name="object_view_text">
+ Vista de objetos
+ </panel_camera_item.text>
+ </panel_camera_item>
+ <panel_camera_item name="mouselook_view">
+ <panel_camera_item.text name="mouselook_view_text">
+ Vista do mouse
+ </panel_camera_item.text>
+ </panel_camera_item>
+ </panel>
+ <panel name="zoom" tool_tip="Aproximar a Câmera in direção ao Foco">
+ <joystick_rotate name="cam_rotate_stick" tool_tip="Girar câmera ao redor do foco"/>
+ <slider_bar name="zoom_slider" tool_tip="Zoom de câmera para focalizar"/>
+ <joystick_track name="cam_track_stick" tool_tip="Move a câmera para cima e para baixo, direita e esquerda"/>
+ </panel>
+ </panel>
+ <panel name="buttons">
+ <button label="" name="presets_btn" tool_tip="Ângulos predefinidos"/>
+ <button label="" name="pan_btn" tool_tip="Pan zoom orbital"/>
+ <button label="" name="avatarview_btn" tool_tip="Modos de câmera"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/floater_help_browser.xml b/indra/newview/skins/minimal/xui/pt/floater_help_browser.xml
new file mode 100644
index 0000000000..11428ff651
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/floater_help_browser.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_help_browser" title="COMO">
+ <floater.string name="loading_text">
+ Carregando...
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="external_controls"/>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/floater_media_browser.xml b/indra/newview/skins/minimal/xui/pt/floater_media_browser.xml
new file mode 100644
index 0000000000..da7428007e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/floater_media_browser.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_about" title="NAVEGADOR DE MÍDIA">
+ <floater.string name="home_page_url">
+ http://www.secondlife.com
+ </floater.string>
+ <floater.string name="support_page_url">
+ http://support.secondlife.com
+ </floater.string>
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button label="Atrás" name="back"/>
+ <button label="Frente" name="forward"/>
+ <button label="Recarregar" name="reload"/>
+ <button label="OK" name="go"/>
+ </layout_panel>
+ <layout_panel name="time_controls">
+ <button label="p/ trás" name="rewind"/>
+ <button label="parar" name="stop"/>
+ <button label="p/ frente" name="seek"/>
+ </layout_panel>
+ <layout_panel name="parcel_owner_controls">
+ <button label="Enviar esta página para lote" name="assign"/>
+ </layout_panel>
+ <layout_panel name="external_controls">
+ <button label="Abrir no meu navegador" name="open_browser"/>
+ <check_box label="Abrir sempre no meu navegador" name="open_always"/>
+ <button label="Fechar" name="close"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/floater_nearby_chat.xml b/indra/newview/skins/minimal/xui/pt/floater_nearby_chat.xml
new file mode 100644
index 0000000000..60edfa505f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/floater_nearby_chat.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="nearby_chat" title="Bate-papo local">
+ <check_box label="Traduzir bate-papo (via Google)" name="translate_chat_checkbox"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/floater_web_content.xml b/indra/newview/skins/minimal/xui/pt/floater_web_content.xml
new file mode 100644
index 0000000000..5101579c6f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/floater_web_content.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="floater_web_content" title="">
+ <layout_stack name="stack1">
+ <layout_panel name="nav_controls">
+ <button name="back" tool_tip="Navegar para trás"/>
+ <button name="forward" tool_tip="Navegar para frente"/>
+ <button name="stop" tool_tip="Parar a navegação"/>
+ <button name="reload" tool_tip="Recarregar página"/>
+ <combo_box name="address" tool_tip="Digite a URL aqui"/>
+ <icon name="media_secure_lock_flag" tool_tip="Navegação segura"/>
+ <button name="popexternal" tool_tip="Abrir a URL atual no navegador do seu computador"/>
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/inspect_avatar.xml b/indra/newview/skins/minimal/xui/pt/inspect_avatar.xml
new file mode 100644
index 0000000000..a199c58c15
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/inspect_avatar.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_avatar">
+ <string name="Subtitle">
+ [IDADE]
+ </string>
+ <string name="Details">
+ [PERFIL_SL]
+ </string>
+ <text name="user_details">
+ This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot
+ </text>
+ <slider name="volume_slider" tool_tip="Volume de Voz" value="0.5"/>
+ <button label="Adicionar amigo" name="add_friend_btn"/>
+ <button label="MI" name="im_btn"/>
+ <button label="Perfil" name="view_profile_btn"/>
+ <panel name="moderator_panel">
+ <button label="Disabilitar Voz" name="disable_voice"/>
+ <button label="Habilitar Voz" name="enable_voice"/>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/inspect_object.xml b/indra/newview/skins/minimal/xui/pt/inspect_object.xml
new file mode 100644
index 0000000000..b72de7038d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/inspect_object.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ Not can_close / no title to avoid window chrome
+ Single instance - only have one at a time, recycle it each spawn
+-->
+<floater name="inspect_object">
+ <string name="Creator">
+ Autor: [CREATOR]
+ </string>
+ <string name="CreatorAndOwner">
+ Autor [CREATOR]
+Proprietário [OWNER]
+ </string>
+ <string name="Price">
+ L$[AMOUNT]
+ </string>
+ <string name="PriceFree">
+ Grátis!
+ </string>
+ <string name="Touch">
+ Tocar
+ </string>
+ <string name="Sit">
+ Sentar
+ </string>
+ <text name="object_name" value="Test Object Name That Is actually two lines and Really Long"/>
+ <text name="price_text">
+ L$30.000
+ </text>
+ <text name="object_description">
+ This is a really long description for an object being as how it is at least 80 characters in length and so but maybe more like 120 at this point. Who knows, really?
+ </text>
+ <button label="Comprar" name="buy_btn"/>
+ <button label="Pagar" name="pay_btn"/>
+ <button label="Pegar uma cópia" name="take_free_copy_btn"/>
+ <button label="Tocar" name="touch_btn"/>
+ <button label="Sentar" name="sit_btn"/>
+ <button label="Abrir" name="open_btn"/>
+ <icon name="secure_browsing" tool_tip="Navegação segura"/>
+ <button label="Mais" name="more_info_btn"/>
+</floater>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_add_wearable_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_add_wearable_gear.xml
new file mode 100644
index 0000000000..4b81276ab3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_add_wearable_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Add Wearable Gear Menu">
+ <menu_item_check label="Ordenar por mais recente" name="sort_by_most_recent"/>
+ <menu_item_check label="Ordenar por nome" name="sort_by_name"/>
+ <menu_item_check label="Ordenar por tipo" name="sort_by_type"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_attachment_other.xml b/indra/newview/skins/minimal/xui/pt/menu_attachment_other.xml
new file mode 100644
index 0000000000..cfd69158bc
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_attachment_other.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_avatar_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Ver perfil" name="Profile..."/>
+ <menu_item_call label="Adicionar amigo..." name="Add Friend"/>
+ <menu_item_call label="MI" name="Send IM..."/>
+ <menu_item_call label="Ligar" name="Call"/>
+ <menu_item_call label="Convidar para entrar no grupo" name="Invite..."/>
+ <menu_item_call label="Bloquear" name="Avatar Mute"/>
+ <menu_item_call label="Denunciar" name="abuse"/>
+ <menu_item_call label="Congelar" name="Freeze..."/>
+ <menu_item_call label="Ejetar" name="Eject..."/>
+ <menu_item_call label="Depurar texturas" name="Debug..."/>
+ <menu_item_call label="Mais zoom" name="Zoom In"/>
+ <menu_item_call label="Pagar" name="Pay..."/>
+ <menu_item_call label="Perfil do objeto" name="Object Inspect"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_attachment_self.xml b/indra/newview/skins/minimal/xui/pt/menu_attachment_self.xml
new file mode 100644
index 0000000000..09060cf3ae
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_attachment_self.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Attachment Pie">
+ <menu_item_call label="Tocar" name="Attachment Object Touch"/>
+ <menu_item_call label="Editar" name="Edit..."/>
+ <menu_item_call label="Tirar" name="Detach"/>
+ <menu_item_call label="Sentar" name="Sit Down Here"/>
+ <menu_item_call label="Ficar de pé" name="Stand Up"/>
+ <menu_item_call label="Trocar de look" name="Change Outfit"/>
+ <menu_item_call label="Editar meu look" name="Edit Outfit"/>
+ <menu_item_call label="Editar meu corpo" name="Edit My Shape"/>
+ <menu_item_call label="Meus amigos" name="Friends..."/>
+ <menu_item_call label="Meus grupos" name="Groups..."/>
+ <menu_item_call label="Meu perfil" name="Profile..."/>
+ <menu_item_call label="Depurar texturas" name="Debug..."/>
+ <menu_item_call label="Largar" name="Drop"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_avatar_icon.xml b/indra/newview/skins/minimal/xui/pt/menu_avatar_icon.xml
new file mode 100644
index 0000000000..beba969b7e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_avatar_icon.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Avatar Icon Menu">
+ <menu_item_call label="Ver perfil" name="Show Profile"/>
+ <menu_item_call label="Enviar MI..." name="Send IM"/>
+ <menu_item_call label="Adicionar amigo..." name="Add Friend"/>
+ <menu_item_call label="Remover amigo..." name="Remove Friend"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_avatar_other.xml b/indra/newview/skins/minimal/xui/pt/menu_avatar_other.xml
new file mode 100644
index 0000000000..a4a26144c7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_avatar_other.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- *NOTE: See also menu_attachment_other.xml -->
+<context_menu name="Avatar Pie">
+ <menu_item_call label="Ver perfil" name="Profile..."/>
+ <menu_item_call label="Adicionar amigo..." name="Add Friend"/>
+ <menu_item_call label="MI" name="Send IM..."/>
+ <menu_item_call label="Ligar" name="Call"/>
+ <menu_item_call label="Convidar para entrar no grupo" name="Invite..."/>
+ <menu_item_call label="Bloquear" name="Avatar Mute"/>
+ <menu_item_call label="Denunciar" name="abuse"/>
+ <menu_item_call label="Congelar" name="Freeze..."/>
+ <menu_item_call label="Ejetar" name="Eject..."/>
+ <menu_item_call label="Depurar texturas" name="Debug..."/>
+ <menu_item_call label="Mais zoom" name="Zoom In"/>
+ <menu_item_call label="Pagar" name="Pay..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_avatar_self.xml b/indra/newview/skins/minimal/xui/pt/menu_avatar_self.xml
new file mode 100644
index 0000000000..6e203d5a25
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_avatar_self.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Self Pie">
+ <menu_item_call label="Sentar" name="Sit Down Here"/>
+ <menu_item_call label="Ficar de pé" name="Stand Up"/>
+ <context_menu label="Tirar" name="Take Off &gt;">
+ <context_menu label="Roupa" name="Clothes &gt;">
+ <menu_item_call label="Camisa" name="Shirt"/>
+ <menu_item_call label="Calças" name="Pants"/>
+ <menu_item_call label="Saia" name="Skirt"/>
+ <menu_item_call label="Sapatos" name="Shoes"/>
+ <menu_item_call label="Meias" name="Socks"/>
+ <menu_item_call label="Jaqueta" name="Jacket"/>
+ <menu_item_call label="Luvas" name="Gloves"/>
+ <menu_item_call label="Camiseta" name="Self Undershirt"/>
+ <menu_item_call label="Roupa de baixo" name="Self Underpants"/>
+ <menu_item_call label="Tatuagem" name="Self Tattoo"/>
+ <menu_item_call label="Alpha" name="Self Alpha"/>
+ <menu_item_call label="Todas as roupas" name="All Clothes"/>
+ </context_menu>
+ <context_menu label="HUD" name="Object Detach HUD"/>
+ <context_menu label="Tirar" name="Object Detach"/>
+ <menu_item_call label="Tirar tudo" name="Detach All"/>
+ </context_menu>
+ <menu_item_call label="Trocar de look" name="Chenge Outfit"/>
+ <menu_item_call label="Editar meu look" name="Edit Outfit"/>
+ <menu_item_call label="Editar meu corpo" name="Edit My Shape"/>
+ <menu_item_call label="Meus amigos" name="Friends..."/>
+ <menu_item_call label="Meus grupos" name="Groups..."/>
+ <menu_item_call label="Meu perfil" name="Profile..."/>
+ <menu_item_call label="Depurar texturas" name="Debug..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_bottomtray.xml b/indra/newview/skins/minimal/xui/pt/menu_bottomtray.xml
new file mode 100644
index 0000000000..479d02512f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_bottomtray.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_camera_move_controls_menu">
+ <menu_item_check label="Botão de gestos" name="ShowGestureButton"/>
+ <menu_item_check label="Botão de movimento" name="ShowMoveButton"/>
+ <menu_item_check label="Botão de ver" name="ShowCameraButton"/>
+ <menu_item_check label="Botão de fotos" name="ShowSnapshotButton"/>
+ <menu_item_check label="Botão da Barra lateral" name="ShowSidebarButton"/>
+ <menu_item_check label="Botão Construir" name="ShowBuildButton"/>
+ <menu_item_check label="Botão Buscar" name="ShowSearchButton"/>
+ <menu_item_check label="Botão Mapa" name="ShowWorldMapButton"/>
+ <menu_item_check label="Botão do Mini Mapa" name="ShowMiniMapButton"/>
+ <menu_item_call label="Cortar" name="NearbyChatBar_Cut"/>
+ <menu_item_call label="Copiar" name="NearbyChatBar_Copy"/>
+ <menu_item_call label="Colar" name="NearbyChatBar_Paste"/>
+ <menu_item_call label="Excluir" name="NearbyChatBar_Delete"/>
+ <menu_item_call label="Selecionar tudo" name="NearbyChatBar_Select_All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_cof_attachment.xml b/indra/newview/skins/minimal/xui/pt/menu_cof_attachment.xml
new file mode 100644
index 0000000000..527e3af3c9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_cof_attachment.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Attachment">
+ <menu_item_call label="Separar" name="detach"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_cof_body_part.xml b/indra/newview/skins/minimal/xui/pt/menu_cof_body_part.xml
new file mode 100644
index 0000000000..704fd226eb
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_cof_body_part.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Body">
+ <menu_item_call label="Trocar" name="replace"/>
+ <menu_item_call label="Editar" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_cof_clothing.xml b/indra/newview/skins/minimal/xui/pt/menu_cof_clothing.xml
new file mode 100644
index 0000000000..051323ae6a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_cof_clothing.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="COF Clothing">
+ <menu_item_call label="Tirar" name="take_off"/>
+ <menu_item_call label="Editar" name="edit"/>
+ <menu_item_call label="Trocar" name="replace"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_cof_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_cof_gear.xml
new file mode 100644
index 0000000000..8716992a5e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_cof_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear COF">
+ <menu label="Roupas novas" name="COF.Gear.New_Clothes"/>
+ <menu label="Nova parte do corpo" name="COF.Geear.New_Body_Parts"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_edit.xml b/indra/newview/skins/minimal/xui/pt/menu_edit.xml
new file mode 100644
index 0000000000..ff431c9a21
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_edit.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu label="Editar" name="Edit">
+ <menu_item_call label="Desfazer" name="Undo"/>
+ <menu_item_call label="Repetir" name="Redo"/>
+ <menu_item_call label="Cortar" name="Cut"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Colar" name="Paste"/>
+ <menu_item_call label="Excluir" name="Delete"/>
+ <menu_item_call label="Replicar" name="Duplicate"/>
+ <menu_item_call label="Selecionar tudo" name="Select All"/>
+ <menu_item_call label="Desfazer seleção" name="Deselect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_favorites.xml b/indra/newview/skins/minimal/xui/pt/menu_favorites.xml
new file mode 100644
index 0000000000..062820fbca
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_favorites.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Teletransportar" name="Teleport To Landmark"/>
+ <menu_item_call label="Ver/Editar marco" name="Landmark Open"/>
+ <menu_item_call label="Copiar SLurl" name="Copy slurl"/>
+ <menu_item_call label="Mostrar no mapa" name="Show On Map"/>
+ <menu_item_call label="Copiar" name="Landmark Copy"/>
+ <menu_item_call label="Colar" name="Landmark Paste"/>
+ <menu_item_call label="Excluir" name="Delete"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_gesture_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_gesture_gear.xml
new file mode 100644
index 0000000000..70d8ae7a8e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_gesture_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_gesture_gear">
+ <menu_item_call label="Adicionar/remover de favoritos" name="activate"/>
+ <menu_item_call label="Copiar" name="copy_gesture"/>
+ <menu_item_call label="Colar" name="paste"/>
+ <menu_item_call label="Copiar UUID" name="copy_uuid"/>
+ <menu_item_call label="Salvar para look atual" name="save_to_outfit"/>
+ <menu_item_call label="Editar" name="edit_gesture"/>
+ <menu_item_call label="Verificar" name="inspect"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_group_plus.xml b/indra/newview/skins/minimal/xui/pt/menu_group_plus.xml
new file mode 100644
index 0000000000..1083845d68
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_group_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Entrar no grupo..." name="item_join"/>
+ <menu_item_call label="Novo grupo..." name="item_new"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_hide_navbar.xml b/indra/newview/skins/minimal/xui/pt/menu_hide_navbar.xml
new file mode 100644
index 0000000000..c2b063193e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_hide_navbar.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="hide_navbar_menu">
+ <menu_item_check label="Mostrar barra de navegação" name="ShowNavbarNavigationPanel"/>
+ <menu_item_check label="Mostrar barra de favoritos" name="ShowNavbarFavoritesPanel"/>
+ <menu_item_check label="Mostrar minibarra de localização" name="ShowMiniLocationPanel"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_im_well_button.xml b/indra/newview/skins/minimal/xui/pt/menu_im_well_button.xml
new file mode 100644
index 0000000000..2d37cefd6f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_im_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="IM Well Button Context Menu">
+ <menu_item_call label="Fechar tudo" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_imchiclet_adhoc.xml b/indra/newview/skins/minimal/xui/pt/menu_imchiclet_adhoc.xml
new file mode 100644
index 0000000000..ead949ba13
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_imchiclet_adhoc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet AdHoc Menu">
+ <menu_item_call label="Encerrar esta sessão" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_imchiclet_group.xml b/indra/newview/skins/minimal/xui/pt/menu_imchiclet_group.xml
new file mode 100644
index 0000000000..dd177d1b8d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_imchiclet_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet Group Menu">
+ <menu_item_call label="Sobre o grupo" name="Show Profile"/>
+ <menu_item_call label="Mostrar sessão" name="Chat"/>
+ <menu_item_call label="Encerrar esta sessão" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_imchiclet_p2p.xml b/indra/newview/skins/minimal/xui/pt/menu_imchiclet_p2p.xml
new file mode 100644
index 0000000000..d821b3ded0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_imchiclet_p2p.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="IMChiclet P2P Menu">
+ <menu_item_call label="Ver perfil" name="Show Profile"/>
+ <menu_item_call label="Adicionar amigo..." name="Add Friend"/>
+ <menu_item_call label="Mostrar sessão" name="Send IM"/>
+ <menu_item_call label="Encerrar esta sessão" name="End Session"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inspect_avatar_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_inspect_avatar_gear.xml
new file mode 100644
index 0000000000..f7fe5640ef
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inspect_avatar_gear.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<toggleable_menu name="Gear Menu">
+ <menu_item_call label="Ver perfil" name="view_profile"/>
+ <menu_item_call label="Adicionar amigo..." name="add_friend"/>
+ <menu_item_call label="MI" name="im"/>
+ <menu_item_call label="Teletransportar" name="teleport"/>
+ <menu_item_call label="Bloquear" name="block"/>
+ <menu_item_call label="Desbloquear" name="unblock"/>
+ <menu_item_call label="Denunciar" name="report"/>
+ <menu_item_call label="Congelar" name="freeze"/>
+ <menu_item_call label="Ejetar" name="eject"/>
+ <menu_item_call label="Chutar" name="kick"/>
+ <menu_item_call label="CSR" name="csr"/>
+ <menu_item_call label="Depurar texturas" name="debug"/>
+ <menu_item_call label="Localizar no mapa" name="find_on_map"/>
+ <menu_item_call label="Mais zoom" name="zoom_in"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inspect_object_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_inspect_object_gear.xml
new file mode 100644
index 0000000000..184db26538
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inspect_object_gear.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu name="Gear Menu">
+ <menu_item_call label="Tocar" name="touch"/>
+ <menu_item_call label="Sentar" name="sit"/>
+ <menu_item_call label="Pagar" name="pay"/>
+ <menu_item_call label="Comprar" name="buy"/>
+ <menu_item_call label="Pegar" name="take"/>
+ <menu_item_call label="Pegar uma cópia" name="take_copy"/>
+ <menu_item_call label="Abrir" name="open"/>
+ <menu_item_call label="Editar" name="edit"/>
+ <menu_item_call label="Vestir" name="wear"/>
+ <menu_item_call label="Adicionar" name="add"/>
+ <menu_item_call label="Denunciar" name="report"/>
+ <menu_item_call label="Bloquear" name="block"/>
+ <menu_item_call label="Mais zoom" name="zoom_in"/>
+ <menu_item_call label="Tirar" name="remove"/>
+ <menu_item_call label="Mais informações" name="more_info"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inspect_self_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_inspect_self_gear.xml
new file mode 100644
index 0000000000..c1f27e765d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inspect_self_gear.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="Self Pie">
+ <menu_item_call label="Sentar" name="Sit Down Here"/>
+ <menu_item_call label="Ficar de pé" name="Stand Up"/>
+ <menu_item_call label="Meus amigos" name="Friends..."/>
+ <menu_item_call label="Meu perfil" name="Profile..."/>
+ <menu_item_call label="Depurar texturas" name="Debug..."/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inv_offer_chiclet.xml b/indra/newview/skins/minimal/xui/pt/menu_inv_offer_chiclet.xml
new file mode 100644
index 0000000000..c404719c95
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inv_offer_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="InvOfferChiclet Menu">
+ <menu_item_call label="Fechar" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inventory.xml b/indra/newview/skins/minimal/xui/pt/menu_inventory.xml
new file mode 100644
index 0000000000..1b1efd3270
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inventory.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Compartilhar" name="Share"/>
+ <menu_item_call label="Comprar" name="Task Buy"/>
+ <menu_item_call label="Abrir" name="Task Open"/>
+ <menu_item_call label="Executar" name="Task Play"/>
+ <menu_item_call label="Propriedades" name="Task Properties"/>
+ <menu_item_call label="Renomear" name="Task Rename"/>
+ <menu_item_call label="Apagar" name="Task Remove"/>
+ <menu_item_call label="Limpar lixeira" name="Empty Trash"/>
+ <menu_item_call label="Limpar Achados &amp; perdidos" name="Empty Lost And Found"/>
+ <menu_item_call label="Nova pasta" name="New Folder"/>
+ <menu_item_call label="Novo script" name="New Script"/>
+ <menu_item_call label="Nova anotação" name="New Note"/>
+ <menu_item_call label="Novo gesto" name="New Gesture"/>
+ <menu label="Novas roupas" name="New Clothes">
+ <menu_item_call label="Nova camisa" name="New Shirt"/>
+ <menu_item_call label="Nova calça" name="New Pants"/>
+ <menu_item_call label="Novos sapatos" name="New Shoes"/>
+ <menu_item_call label="Novas meias" name="New Socks"/>
+ <menu_item_call label="Nova jaqueta" name="New Jacket"/>
+ <menu_item_call label="Nova saia" name="New Skirt"/>
+ <menu_item_call label="Novas luvas" name="New Gloves"/>
+ <menu_item_call label="Nova anágua" name="New Undershirt"/>
+ <menu_item_call label="Nova roupa de baixo" name="New Underpants"/>
+ <menu_item_call label="Nova máscara alfa" name="New Alpha Mask"/>
+ <menu_item_call label="Nova tatuagem" name="New Tattoo"/>
+ </menu>
+ <menu label="Nova parte do corpo" name="New Body Parts">
+ <menu_item_call label="Nova forma" name="New Shape"/>
+ <menu_item_call label="Nova pele" name="New Skin"/>
+ <menu_item_call label="Novo cabelo" name="New Hair"/>
+ <menu_item_call label="Novos olhos" name="New Eyes"/>
+ </menu>
+ <menu label="Alterar fonte" name="Change Type">
+ <menu_item_call label="Padrão" name="Default"/>
+ <menu_item_call label="Luvas" name="Gloves"/>
+ <menu_item_call label="Jaqueta" name="Jacket"/>
+ <menu_item_call label="Calças" name="Pants"/>
+ <menu_item_call label="Silhueta" name="Shape"/>
+ <menu_item_call label="Sapatos" name="Shoes"/>
+ <menu_item_call label="Camisa" name="Shirt"/>
+ <menu_item_call label="Saia" name="Skirt"/>
+ <menu_item_call label="Roupa de baixo" name="Underpants"/>
+ <menu_item_call label="Camiseta" name="Undershirt"/>
+ </menu>
+ <menu_item_call label="Teletransporte" name="Landmark Open"/>
+ <menu_item_call label="Abrir" name="Animation Open"/>
+ <menu_item_call label="Abrir" name="Sound Open"/>
+ <menu_item_call label="Substituir look" name="Replace Outfit"/>
+ <menu_item_call label="Adicionar a look" name="Add To Outfit"/>
+ <menu_item_call label="Tirar do look atual" name="Remove From Outfit"/>
+ <menu_item_call label="Encontrar original" name="Find Original"/>
+ <menu_item_call label="Remover item" name="Purge Item"/>
+ <menu_item_call label="Restaurar item" name="Restore Item"/>
+ <menu_item_call label="Abrir" name="Open"/>
+ <menu_item_call label="Abrir original" name="Open Original"/>
+ <menu_item_call label="Propriedades" name="Properties"/>
+ <menu_item_call label="Renomear" name="Rename"/>
+ <menu_item_call label="Copiar item UUID" name="Copy Asset UUID"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Colar" name="Paste"/>
+ <menu_item_call label="Colar como link" name="Paste As Link"/>
+ <menu_item_call label="Excluir" name="Remove Link"/>
+ <menu_item_call label="Apagar" name="Delete"/>
+ <menu_item_call label="Excluir pasta do sistema" name="Delete System Folder"/>
+ <menu_item_call label="Pasta conversa em conferência" name="Conference Chat Folder"/>
+ <menu_item_call label="Executar som" name="Sound Play"/>
+ <menu_item_call label="Sobre o marco" name="About Landmark"/>
+ <menu_item_call label="Executar animação" name="Animation Play"/>
+ <menu_item_call label="Executar áudio" name="Animation Audition"/>
+ <menu_item_call label="Mandar MI" name="Send Instant Message"/>
+ <menu_item_call label="Oferecer teletransporte..." name="Offer Teleport..."/>
+ <menu_item_call label="Bate-papo em conferência" name="Conference Chat"/>
+ <menu_item_call label="Ativar" name="Activate"/>
+ <menu_item_call label="Desativar" name="Deactivate"/>
+ <menu_item_call label="Salvar como" name="Save As"/>
+ <menu_item_call label="Tirar de si mesmo" name="Detach From Yourself"/>
+ <menu_item_call label="Vestir" name="Wearable And Object Wear"/>
+ <menu label="Anexar a" name="Attach To"/>
+ <menu label="Anexar ao HUD" name="Attach To HUD"/>
+ <menu_item_call label="Editar" name="Wearable Edit"/>
+ <menu_item_call label="Adicionar" name="Wearable Add"/>
+ <menu_item_call label="Tirar" name="Take Off"/>
+ <menu_item_call label="--Sem opções--" name="--no options--"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inventory_add.xml b/indra/newview/skins/minimal/xui/pt/menu_inventory_add.xml
new file mode 100644
index 0000000000..2723f39287
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inventory_add.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_inventory_add">
+ <menu label="Upload" name="upload">
+ <menu_item_call label="Imagem (L$[COST])..." name="Upload Image"/>
+ <menu_item_call label="Som (L$[COST])..." name="Upload Sound"/>
+ <menu_item_call label="Animação (L$[COST])..." name="Upload Animation"/>
+ <menu_item_call label="Volume (L$[COST] per file)..." name="Bulk Upload"/>
+ <menu_item_call label="Autorizações de upload padrão" name="perm prefs"/>
+ </menu>
+ <menu_item_call label="Nova pasta" name="New Folder"/>
+ <menu_item_call label="Novo script" name="New Script"/>
+ <menu_item_call label="Nova anotação" name="New Note"/>
+ <menu_item_call label="Novo gesto" name="New Gesture"/>
+ <menu label="Novas roupas" name="New Clothes">
+ <menu_item_call label="Nova camisa" name="New Shirt"/>
+ <menu_item_call label="Novas calças" name="New Pants"/>
+ <menu_item_call label="Novos sapatos" name="New Shoes"/>
+ <menu_item_call label="Novas meias" name="New Socks"/>
+ <menu_item_call label="Nova blusa" name="New Jacket"/>
+ <menu_item_call label="Nova saia" name="New Skirt"/>
+ <menu_item_call label="Novas luvas" name="New Gloves"/>
+ <menu_item_call label="Nova camiseta" name="New Undershirt"/>
+ <menu_item_call label="Novas roupa de baixo" name="New Underpants"/>
+ <menu_item_call label="Novo alpha" name="New Alpha"/>
+ <menu_item_call label="Nova tatuagem" name="New Tattoo"/>
+ </menu>
+ <menu label="Nova parte do corpo" name="New Body Parts">
+ <menu_item_call label="Nova forma" name="New Shape"/>
+ <menu_item_call label="Nova pele" name="New Skin"/>
+ <menu_item_call label="Novo cabelo" name="New Hair"/>
+ <menu_item_call label="Novos olhos" name="New Eyes"/>
+ </menu>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_inventory_gear_default.xml b/indra/newview/skins/minimal/xui/pt/menu_inventory_gear_default.xml
new file mode 100644
index 0000000000..3400578d9a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_inventory_gear_default.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_gear_default">
+ <menu_item_call label="Nova janela de inventário" name="new_window"/>
+ <menu_item_check label="Ordenar por nome" name="sort_by_name"/>
+ <menu_item_check label="Ordenar por mais recente" name="sort_by_recent"/>
+ <menu_item_check label="Pastas do sistema no topo" name="sort_system_folders_to_top"/>
+ <menu_item_call label="Mostrar filtros" name="show_filters"/>
+ <menu_item_call label="Restabelecer filtros" name="reset_filters"/>
+ <menu_item_call label="Fechar todas as pastas" name="close_folders"/>
+ <menu_item_call label="Esvaziar achados e perdidos" name="empty_lostnfound"/>
+ <menu_item_call label="Salvar textura como" name="Save Texture As"/>
+ <menu_item_call label="Compartilhar" name="Share"/>
+ <menu_item_call label="Encontrar original" name="Find Original"/>
+ <menu_item_call label="Encontrar todos os links" name="Find All Links"/>
+ <menu_item_call label="Esvaziar lixeira" name="empty_trash"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_land.xml b/indra/newview/skins/minimal/xui/pt/menu_land.xml
new file mode 100644
index 0000000000..9182ce321a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_land.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Land Pie">
+ <menu_item_call label="Sobre terrenos" name="Place Information..."/>
+ <menu_item_call label="Sentar aqui" name="Sit Here"/>
+ <menu_item_call label="Comprar este terreno" name="Land Buy"/>
+ <menu_item_call label="Comprar passe" name="Land Buy Pass"/>
+ <menu_item_call label="Construir" name="Create"/>
+ <menu_item_call label="Editar a topografia" name="Edit Terrain"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_landmark.xml b/indra/newview/skins/minimal/xui/pt/menu_landmark.xml
new file mode 100644
index 0000000000..6accfebee7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_landmark.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="landmark_overflow_menu">
+ <menu_item_call label="Copiar SLurl" name="copy"/>
+ <menu_item_call label="Excluir" name="delete"/>
+ <menu_item_call label="Criar destaque" name="pick"/>
+ <menu_item_call label="Adicionar à barra de favoritos" name="add_to_favbar"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_login.xml b/indra/newview/skins/minimal/xui/pt/menu_login.xml
new file mode 100644
index 0000000000..3dff3d7c8a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_login.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Login Menu">
+ <menu label="Eu" name="File">
+ <menu_item_call label="Preferências" name="Preferences..."/>
+ <menu_item_call label="Sair do [APP_NAME]" name="Quit"/>
+ </menu>
+ <menu label="Ajuda" name="Help">
+ <menu_item_call label="Ajuda do [SECOND_LIFE]" name="Second Life Help"/>
+ <menu_item_call label="Sobre [APP_NAME]" name="About Second Life"/>
+ </menu>
+ <menu_item_check label="Exibir menu de depuração" name="Show Debug Menu"/>
+ <menu label="Depurar" name="Debug">
+ <menu_item_call label="Mostrar configurações" name="Debug Settings"/>
+ <menu_item_call label="Configurações da interface e cor" name="UI/Color Settings"/>
+ <menu label="Testes de UI" name="UI Tests"/>
+ <menu_item_call label="Definir tamanho da janela:" name="Set Window Size..."/>
+ <menu_item_call label="Mostrar TOS" name="TOS"/>
+ <menu_item_call label="Mostrar mensagem crítica" name="Critical"/>
+ <menu_item_call label="Teste de mídia do navegador" name="Web Browser Test"/>
+ <menu_item_call label="Teste de conteúdo web" name="Web Content Floater Test"/>
+ <menu_item_check label="Exibir seletor da grade" name="Show Grid Picker"/>
+ <menu_item_call label="Exibir painel de notificações" name="Show Notifications Console"/>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_mini_map.xml b/indra/newview/skins/minimal/xui/pt/menu_mini_map.xml
new file mode 100644
index 0000000000..6a3fe55de5
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_mini_map.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Zoom Perto" name="Zoom Close"/>
+ <menu_item_call label="Zoom Médio" name="Zoom Medium"/>
+ <menu_item_call label="Zoom Longe" name="Zoom Far"/>
+ <menu_item_call label="Zoom padrão" name="Zoom Default"/>
+ <menu_item_check label="Girar mapa" name="Rotate Map"/>
+ <menu_item_check label="Auto Center" name="Auto Center"/>
+ <menu_item_call label="Parar Acompanhamento" name="Stop Tracking"/>
+ <menu_item_call label="Mapa-múndi" name="World Map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_navbar.xml b/indra/newview/skins/minimal/xui/pt/menu_navbar.xml
new file mode 100644
index 0000000000..57c1471de3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_navbar.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Navbar Menu">
+ <menu_item_check label="Mostrar coordenadas" name="Show Coordinates"/>
+ <menu_item_check label="Mostrar as propriedades do terreno" name="Show Parcel Properties"/>
+ <menu_item_call label="Marco" name="Landmark"/>
+ <menu_item_call label="Cortar" name="Cut"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Colar" name="Paste"/>
+ <menu_item_call label="Excluir" name="Delete"/>
+ <menu_item_call label="Selecionar tudo" name="Select All"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_nearby_chat.xml b/indra/newview/skins/minimal/xui/pt/menu_nearby_chat.xml
new file mode 100644
index 0000000000..f1ea83c837
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_nearby_chat.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="NearBy Chat Menu">
+ <menu_item_call label="Mostrar quem está aqui..." name="nearby_people"/>
+ <menu_item_check label="Mostrar texto bloqueado" name="muted_text"/>
+ <menu_item_check label="Mostrar ícones de amigos" name="show_buddy_icons"/>
+ <menu_item_check label="Mostrar nomes" name="show_names"/>
+ <menu_item_check label="Mostrar ícones e nomes" name="show_icons_and_names"/>
+ <menu_item_call label="Tamanho da fonte" name="font_size"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_notification_well_button.xml b/indra/newview/skins/minimal/xui/pt/menu_notification_well_button.xml
new file mode 100644
index 0000000000..43ad4134ec
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_notification_well_button.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Notification Well Button Context Menu">
+ <menu_item_call label="Fechar tudo" name="Close All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_object.xml b/indra/newview/skins/minimal/xui/pt/menu_object.xml
new file mode 100644
index 0000000000..bf94859699
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_object.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Object Pie">
+ <menu_item_call label="Tocar" name="Object Touch">
+ <menu_item_call.on_enable name="EnableTouch" parameter="Tocar"/>
+ </menu_item_call>
+ <menu_item_call label="Editar" name="Edit..."/>
+ <menu_item_call label="Construir" name="Build"/>
+ <menu_item_call label="Abrir" name="Open"/>
+ <menu_item_call label="Sentar aqui" name="Object Sit"/>
+ <menu_item_call label="Ficar de pé" name="Object Stand Up"/>
+ <menu_item_call label="Perfil do objeto" name="Object Inspect"/>
+ <menu_item_call label="Mais zoom" name="Zoom In"/>
+ <context_menu label="Colocar no(a)" name="Put On">
+ <menu_item_call label="Vestir" name="Wear"/>
+ <menu_item_call label="Adicionar" name="Add"/>
+ <context_menu label="Anexar" name="Object Attach"/>
+ <context_menu label="Anexar o HUD" name="Object Attach HUD"/>
+ </context_menu>
+ <context_menu label="Tirar" name="Remove">
+ <menu_item_call label="Denunciar abuso" name="Report Abuse..."/>
+ <menu_item_call label="Bloquear" name="Object Mute"/>
+ <menu_item_call label="Devolver" name="Return..."/>
+ <menu_item_call label="Excluir" name="Delete"/>
+ </context_menu>
+ <menu_item_call label="Pegar" name="Pie Object Take"/>
+ <menu_item_call label="Pegar uma cópia" name="Take Copy"/>
+ <menu_item_call label="Pagar" name="Pay..."/>
+ <menu_item_call label="Comprar" name="Buy..."/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_object_icon.xml b/indra/newview/skins/minimal/xui/pt/menu_object_icon.xml
new file mode 100644
index 0000000000..7af760a6ee
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_object_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Object Icon Menu">
+ <menu_item_call label="Perfil do objeto..." name="Object Profile"/>
+ <menu_item_call label="Bloquear..." name="Block"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_outfit_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_outfit_gear.xml
new file mode 100644
index 0000000000..11b3e653c6
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_outfit_gear.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Outfit">
+ <menu_item_call label="Vestir - Substituir look atual" name="wear"/>
+ <menu_item_call label="Vestir - Adicionar ao look atual" name="wear_add"/>
+ <menu_item_call label="Tirar - Tirar do look atual" name="take_off"/>
+ <menu label="Roupas novas" name="New Clothes">
+ <menu_item_call label="Nova camisa" name="New Shirt"/>
+ <menu_item_call label="Novas calças" name="New Pants"/>
+ <menu_item_call label="Novos sapatos" name="New Shoes"/>
+ <menu_item_call label="Novas meias" name="New Socks"/>
+ <menu_item_call label="Nova blusa" name="New Jacket"/>
+ <menu_item_call label="Nova saia" name="New Skirt"/>
+ <menu_item_call label="Novas luvas" name="New Gloves"/>
+ <menu_item_call label="Nova camiseta" name="New Undershirt"/>
+ <menu_item_call label="Novas roupa de baixo" name="New Underpants"/>
+ <menu_item_call label="Novo alpha" name="New Alpha"/>
+ <menu_item_call label="Nova tatuagem" name="New Tattoo"/>
+ </menu>
+ <menu label="Nova parte do corpo" name="New Body Parts">
+ <menu_item_call label="Nova silhueta" name="New Shape"/>
+ <menu_item_call label="Nova pele" name="New Skin"/>
+ <menu_item_call label="Novo cabelo" name="New Hair"/>
+ <menu_item_call label="Novos olhos" name="New Eyes"/>
+ </menu>
+ <menu_item_call label="Renomear look" name="rename"/>
+ <menu_item_call label="Excluir visual" name="delete_outfit"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_outfit_tab.xml b/indra/newview/skins/minimal/xui/pt/menu_outfit_tab.xml
new file mode 100644
index 0000000000..8db5e405b3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_outfit_tab.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit">
+ <menu_item_call label="Vestir - Substituir look atual" name="wear_replace"/>
+ <menu_item_call label="Vestir - Sem tirar look atual" name="wear_add"/>
+ <menu_item_call label="Tirar - Tirar do look atual" name="take_off"/>
+ <menu_item_call label="Editar look" name="edit"/>
+ <menu_item_call label="Renomear look" name="rename"/>
+ <menu_item_call label="Excluir visual" name="delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_participant_list.xml b/indra/newview/skins/minimal/xui/pt/menu_participant_list.xml
new file mode 100644
index 0000000000..01f1d4ef80
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_participant_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Participant List Context Menu">
+ <menu_item_check label="Ordenar por nome" name="SortByName"/>
+ <menu_item_check label="Ordenar por conversas mais recentes" name="SortByRecentSpeakers"/>
+ <menu_item_call label="Ver perfil" name="View Profile"/>
+ <menu_item_call label="Adicionar amigo..." name="Add Friend"/>
+ <menu_item_call label="MI" name="IM"/>
+ <menu_item_call label="Ligar" name="Call"/>
+ <menu_item_call label="Compartilhar" name="Share"/>
+ <menu_item_call label="Pagar" name="Pay"/>
+ <menu_item_check label="Ver ícones de pessoas" name="View Icons"/>
+ <menu_item_check label="Bloquear voz" name="Block/Unblock"/>
+ <menu_item_check label="Bloquear texto" name="MuteText"/>
+ <context_menu label="Opções do moderador &gt;" name="Moderator Options">
+ <menu_item_check label="Pode bater papo por escrito" name="AllowTextChat"/>
+ <menu_item_call label="Silenciar este participante" name="ModerateVoiceMuteSelected"/>
+ <menu_item_call label="Desfazer silenciar deste participante" name="ModerateVoiceUnMuteSelected"/>
+ <menu_item_call label="Silenciar todos" name="ModerateVoiceMute"/>
+ <menu_item_call label="Desfazer silenciar para todos" name="ModerateVoiceUnmute"/>
+ </context_menu>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_friends_view_sort.xml b/indra/newview/skins/minimal/xui/pt/menu_people_friends_view_sort.xml
new file mode 100644
index 0000000000..e7c325010f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_friends_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Ordenar por nome" name="sort_name"/>
+ <menu_item_check label="Ordenar por status" name="sort_status"/>
+ <menu_item_check label="Ver ícones de pessoas" name="view_icons"/>
+ <menu_item_check label="Autorizações de visualização dadas" name="view_permissions"/>
+ <menu_item_call label="Ver residentes e objetos bloqueados" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_groups.xml b/indra/newview/skins/minimal/xui/pt/menu_people_groups.xml
new file mode 100644
index 0000000000..9a924ad7b9
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_groups.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_call label="Ver dados" name="View Info"/>
+ <menu_item_call label="Bate-papo" name="Chat"/>
+ <menu_item_call label="Ligar" name="Call"/>
+ <menu_item_call label="Ativar" name="Activate"/>
+ <menu_item_call label="Sair" name="Leave"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_groups_view_sort.xml b/indra/newview/skins/minimal/xui/pt/menu_people_groups_view_sort.xml
new file mode 100644
index 0000000000..86a9d2263f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_groups_view_sort.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Mostrar ícones de grupos" name="Display Group Icons"/>
+ <menu_item_call label="Sair do grupo selecionado" name="Leave Selected Group"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_nearby.xml b/indra/newview/skins/minimal/xui/pt/menu_people_nearby.xml
new file mode 100644
index 0000000000..b446a2fe81
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_nearby.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Avatar Context Menu">
+ <menu_item_call label="Ver perfil" name="View Profile"/>
+ <menu_item_call label="Adicionar amigo" name="Add Friend"/>
+ <menu_item_call label="Remover amigo" name="Remove Friend"/>
+ <menu_item_call label="IM" name="IM"/>
+ <menu_item_call label="Ligar" name="Call"/>
+ <menu_item_call label="Mapa" name="Map"/>
+ <menu_item_call label="Compartilhar" name="Share"/>
+ <menu_item_call label="Pagar" name="Pay"/>
+ <menu_item_check label="Bloquear/desbloquear" name="Block/Unblock"/>
+ <menu_item_call label="Teletransportar?" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_nearby_multiselect.xml b/indra/newview/skins/minimal/xui/pt/menu_people_nearby_multiselect.xml
new file mode 100644
index 0000000000..79edb96b1c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_nearby_multiselect.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Multi-Selected People Context Menu">
+ <menu_item_call label="Adicionar amigo..." name="Add Friends"/>
+ <menu_item_call label="Remover amigo..." name="Remove Friend"/>
+ <menu_item_call label="MI" name="IM"/>
+ <menu_item_call label="Ligar" name="Call"/>
+ <menu_item_call label="Compartilhar" name="Share"/>
+ <menu_item_call label="Pagar" name="Pay"/>
+ <menu_item_call label="Teletransportar?" name="teleport"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_nearby_view_sort.xml b/indra/newview/skins/minimal/xui/pt/menu_people_nearby_view_sort.xml
new file mode 100644
index 0000000000..228ce46a31
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_nearby_view_sort.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Ordenar por conversas mais recentes" name="sort_by_recent_speakers"/>
+ <menu_item_check label="Ordenar por nome" name="sort_name"/>
+ <menu_item_check label="Ordenar por distância" name="sort_distance"/>
+ <menu_item_check label="Ver ícones de pessoas" name="view_icons"/>
+ <menu_item_call label="Ver residentes e objetos bloqueados" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_people_recent_view_sort.xml b/indra/newview/skins/minimal/xui/pt/menu_people_recent_view_sort.xml
new file mode 100644
index 0000000000..f3b89e01cd
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_people_recent_view_sort.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_group_plus">
+ <menu_item_check label="Ordenar por mais recente" name="sort_most"/>
+ <menu_item_check label="Ordenar por nome" name="sort_name"/>
+ <menu_item_check label="Ver ícones de pessoas" name="view_icons"/>
+ <menu_item_call label="Ver residentes e objetos bloqueados" name="show_blocked_list"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_picks.xml b/indra/newview/skins/minimal/xui/pt/menu_picks.xml
new file mode 100644
index 0000000000..8b9e10fc02
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_picks.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Picks">
+ <menu_item_call label="Info" name="pick_info"/>
+ <menu_item_call label="Editar" name="pick_edit"/>
+ <menu_item_call label="Teletransportar" name="pick_teleport"/>
+ <menu_item_call label="Mapa" name="pick_map"/>
+ <menu_item_call label="Excluir" name="pick_delete"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_picks_plus.xml b/indra/newview/skins/minimal/xui/pt/menu_picks_plus.xml
new file mode 100644
index 0000000000..95a7c05262
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_picks_plus.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="picks_plus_menu">
+ <menu_item_call label="Adicionar" name="create_pick"/>
+ <menu_item_call label="Novo anúncio" name="create_classified"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_place.xml b/indra/newview/skins/minimal/xui/pt/menu_place.xml
new file mode 100644
index 0000000000..282ea20a7a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_place.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="place_overflow_menu">
+ <menu_item_call label="Criar marco" name="landmark"/>
+ <menu_item_call label="Criar destaque" name="pick"/>
+ <menu_item_call label="Comprar passe" name="pass"/>
+ <menu_item_call label="Editar" name="edit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_place_add_button.xml b/indra/newview/skins/minimal/xui/pt/menu_place_add_button.xml
new file mode 100644
index 0000000000..d099d04f8d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_place_add_button.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Adicionar pasta" name="add_folder"/>
+ <menu_item_call label="Adicionar marco" name="add_landmark"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_places_gear_folder.xml b/indra/newview/skins/minimal/xui/pt/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..2059a9ed2d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_places_gear_folder.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_folder_gear">
+ <menu_item_call label="Adicionar marco" name="add_landmark"/>
+ <menu_item_call label="Adicionar pasta" name="add_folder"/>
+ <menu_item_call label="Cortar" name="cut"/>
+ <menu_item_call label="Copiar" name="copy_folder"/>
+ <menu_item_call label="Colar" name="paste"/>
+ <menu_item_call label="Renomear" name="rename"/>
+ <menu_item_call label="Excluir" name="delete"/>
+ <menu_item_call label="Expanda" name="expand"/>
+ <menu_item_call label="Recolher" name="collapse"/>
+ <menu_item_call label="Expandir todas as pastas" name="expand_all"/>
+ <menu_item_call label="Recolher todas as pastas" name="collapse_all"/>
+ <menu_item_check label="Ordenar por data" name="sort_by_date"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_places_gear_landmark.xml b/indra/newview/skins/minimal/xui/pt/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..52a9d13735
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_places_gear_landmark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_ladmark_gear">
+ <menu_item_call label="Teletransportar" name="teleport"/>
+ <menu_item_call label="Mais informações" name="more_info"/>
+ <menu_item_call label="Mostrar no mapa" name="show_on_map"/>
+ <menu_item_call label="Adicionar marco" name="add_landmark"/>
+ <menu_item_call label="Adicionar pasta" name="add_folder"/>
+ <menu_item_call label="Cortar" name="cut"/>
+ <menu_item_call label="Copiar marco" name="copy_landmark"/>
+ <menu_item_call label="Copiar SLurl" name="copy_slurl"/>
+ <menu_item_call label="Colar" name="paste"/>
+ <menu_item_call label="Renomear" name="rename"/>
+ <menu_item_call label="Excluir" name="delete"/>
+ <menu_item_call label="Expandir todas as pastas" name="expand_all"/>
+ <menu_item_call label="Recolher todas as pastas" name="collapse_all"/>
+ <menu_item_check label="Ordenar por data" name="sort_by_date"/>
+ <menu_item_call label="Criar destaque" name="create_pick"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_profile_overflow.xml b/indra/newview/skins/minimal/xui/pt/menu_profile_overflow.xml
new file mode 100644
index 0000000000..d41ecbd755
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_profile_overflow.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="profile_overflow_menu">
+ <menu_item_call label="Mapa" name="show_on_map"/>
+ <menu_item_call label="Pagar" name="pay"/>
+ <menu_item_call label="Compartilhar" name="share"/>
+ <menu_item_call label="Bloquear" name="block"/>
+ <menu_item_call label="Desbloquear" name="unblock"/>
+ <menu_item_call label="Chutar" name="kick"/>
+ <menu_item_call label="Congelar" name="freeze"/>
+ <menu_item_call label="Descongelar" name="unfreeze"/>
+ <menu_item_call label="CSR" name="csr"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_save_outfit.xml b/indra/newview/skins/minimal/xui/pt/menu_save_outfit.xml
new file mode 100644
index 0000000000..61c6b9202f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_save_outfit.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_outfit_menu">
+ <menu_item_call label="Salvar" name="save_outfit"/>
+ <menu_item_call label="Salvar como" name="save_as_new_outfit"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_script_chiclet.xml b/indra/newview/skins/minimal/xui/pt/menu_script_chiclet.xml
new file mode 100644
index 0000000000..ccf3878e14
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_script_chiclet.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="ScriptChiclet Menu">
+ <menu_item_call label="Fechar" name="Close"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_slurl.xml b/indra/newview/skins/minimal/xui/pt/menu_slurl.xml
new file mode 100644
index 0000000000..6d4c84fc3c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_slurl.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Popup">
+ <menu_item_call label="Sobre a URL" name="about_url"/>
+ <menu_item_call label="Teletransporte para a URL" name="teleport_to_url"/>
+ <menu_item_call label="Mapa" name="show_on_map"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_teleport_history_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_teleport_history_gear.xml
new file mode 100644
index 0000000000..f034509be8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_teleport_history_gear.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Teleport History Gear Context Menu">
+ <menu_item_call label="Expandir todas as pastas" name="Expand all folders"/>
+ <menu_item_call label="Recolher todas as pastas" name="Collapse all folders"/>
+ <menu_item_call label="Limpar histórico de teletransporte" name="Clear Teleport History"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_teleport_history_item.xml b/indra/newview/skins/minimal/xui/pt/menu_teleport_history_item.xml
new file mode 100644
index 0000000000..ec1e7a0950
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_teleport_history_item.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Teletransportar" name="Teleport"/>
+ <menu_item_call label="Mais informações" name="More Information"/>
+ <menu_item_call label="Copiar" name="CopyToClipboard"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_teleport_history_tab.xml b/indra/newview/skins/minimal/xui/pt/menu_teleport_history_tab.xml
new file mode 100644
index 0000000000..6a633cf74c
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_teleport_history_tab.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Teleport History Item Context Menu">
+ <menu_item_call label="Abrir" name="TabOpen"/>
+ <menu_item_call label="Fechar" name="TabClose"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_text_editor.xml b/indra/newview/skins/minimal/xui/pt/menu_text_editor.xml
new file mode 100644
index 0000000000..31c284c6ed
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_text_editor.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Text editor context menu">
+ <menu_item_call label="Cortar" name="Cut"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+ <menu_item_call label="Colar" name="Paste"/>
+ <menu_item_call label="Excluir" name="Delete"/>
+ <menu_item_call label="Selecionar tudo" name="Select All"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_topinfobar.xml b/indra/newview/skins/minimal/xui/pt/menu_topinfobar.xml
new file mode 100644
index 0000000000..d9347950b1
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_topinfobar.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="menu_topinfobar">
+ <menu_item_check label="Mostrar coordenadas" name="Show Coordinates"/>
+ <menu_item_check label="Mostrar as propriedades do terreno" name="Show Parcel Properties"/>
+ <menu_item_call label="Marco" name="Landmark"/>
+ <menu_item_call label="Copiar" name="Copy"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_agent.xml b/indra/newview/skins/minimal/xui/pt/menu_url_agent.xml
new file mode 100644
index 0000000000..ba5e055124
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_agent.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar perfil de residente" name="show_agent"/>
+ <menu_item_call label="Copiar nome para área de transferência" name="url_copy_label"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_group.xml b/indra/newview/skins/minimal/xui/pt/menu_url_group.xml
new file mode 100644
index 0000000000..5b67a69c9a
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_group.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar informações do grupo" name="show_group"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy_label"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_http.xml b/indra/newview/skins/minimal/xui/pt/menu_url_http.xml
new file mode 100644
index 0000000000..e53a2572b8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_http.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Abrir página da web" name="url_open"/>
+ <menu_item_call label="Abrir no navegador do SL" name="url_open_internal"/>
+ <menu_item_call label="Abrir no navegador externo" name="url_open_external"/>
+ <menu_item_call label="Copiar URL para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_inventory.xml b/indra/newview/skins/minimal/xui/pt/menu_url_inventory.xml
new file mode 100644
index 0000000000..45c14355d0
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_inventory.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar item de inventário" name="show_item"/>
+ <menu_item_call label="Copiar nome para área de transferência" name="url_copy_label"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_map.xml b/indra/newview/skins/minimal/xui/pt/menu_url_map.xml
new file mode 100644
index 0000000000..ba114cccaa
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_map.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar no mapa" name="show_on_map"/>
+ <menu_item_call label="Teletransportar para este lugar" name="teleport_to_location"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_objectim.xml b/indra/newview/skins/minimal/xui/pt/menu_url_objectim.xml
new file mode 100644
index 0000000000..c197444181
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_objectim.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar informações sobre o objeto" name="show_object"/>
+ <menu_item_call label="Mostrar no mapa" name="show_on_map"/>
+ <menu_item_call label="Teletransportar para lugar do objeto" name="teleport_to_object"/>
+ <menu_item_call label="Copiar nome do objeto para área de transferência" name="url_copy_label"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_parcel.xml b/indra/newview/skins/minimal/xui/pt/menu_url_parcel.xml
new file mode 100644
index 0000000000..6cc668bfd3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_parcel.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar informações sobre este lote" name="show_parcel"/>
+ <menu_item_call label="Mostrar no mapa" name="show_on_map"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_slapp.xml b/indra/newview/skins/minimal/xui/pt/menu_url_slapp.xml
new file mode 100644
index 0000000000..d0784149ac
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_slapp.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Executar este comando" name="run_slapp"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_slurl.xml b/indra/newview/skins/minimal/xui/pt/menu_url_slurl.xml
new file mode 100644
index 0000000000..7216ccf0b3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_slurl.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Mostrar informações sobre este lugar" name="show_place"/>
+ <menu_item_call label="Mostrar no mapa" name="show_on_map"/>
+ <menu_item_call label="Teletransportar para este lugar" name="teleport_to_location"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_url_teleport.xml b/indra/newview/skins/minimal/xui/pt/menu_url_teleport.xml
new file mode 100644
index 0000000000..f007425646
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_url_teleport.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Url Popup">
+ <menu_item_call label="Teletransportar para este lugar" name="teleport"/>
+ <menu_item_call label="Mostrar no mapa" name="show_on_map"/>
+ <menu_item_call label="Copiar SLurl para área de transferência" name="url_copy"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_viewer.xml b/indra/newview/skins/minimal/xui/pt/menu_viewer.xml
new file mode 100644
index 0000000000..2bd1e88279
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_viewer.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu_bar name="Main Menu">
+ <menu label="Ajuda" name="Help">
+ <menu_item_call label="[SECOND_LIFE] Ajuda" name="Second Life Help"/>
+ </menu>
+ <menu label="Avançado" name="Advanced">
+ <menu label="Atalhos" name="Shortcuts">
+ <menu_item_check label="Voar" name="Fly"/>
+ <menu_item_call label="Fechar janela" name="Close Window"/>
+ <menu_item_call label="Fechar todas as janelas" name="Close All Windows"/>
+ <menu_item_call label="Visão padrão" name="Reset View"/>
+ </menu>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_wearable_list_item.xml b/indra/newview/skins/minimal/xui/pt/menu_wearable_list_item.xml
new file mode 100644
index 0000000000..2487f6779f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_wearable_list_item.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Outfit Wearable Context Menu">
+ <menu_item_call label="Trocar" name="wear_replace"/>
+ <menu_item_call label="Vestir" name="wear_wear"/>
+ <menu_item_call label="Adicionar" name="wear_add"/>
+ <menu_item_call label="Tirar / Separar" name="take_off_or_detach"/>
+ <menu_item_call label="Separar" name="detach"/>
+ <context_menu label="Colocar em" name="wearable_attach_to"/>
+ <context_menu label="Anexar ao HUD" name="wearable_attach_to_hud"/>
+ <menu_item_call label="Tirar" name="take_off"/>
+ <menu_item_call label="Editar" name="edit"/>
+ <menu_item_call label="Perfil do item" name="object_profile"/>
+ <menu_item_call label="Mostrar original" name="show_original"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_wearing_gear.xml b/indra/newview/skins/minimal/xui/pt/menu_wearing_gear.xml
new file mode 100644
index 0000000000..7b6ce4d87e
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_wearing_gear.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<menu name="Gear Wearing">
+ <menu_item_call label="Editar look" name="edit"/>
+ <menu_item_call label="Tirar" name="takeoff"/>
+</menu>
diff --git a/indra/newview/skins/minimal/xui/pt/menu_wearing_tab.xml b/indra/newview/skins/minimal/xui/pt/menu_wearing_tab.xml
new file mode 100644
index 0000000000..4e6e52ebc7
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/menu_wearing_tab.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<context_menu name="Wearing">
+ <menu_item_call label="Tirar" name="take_off"/>
+ <menu_item_call label="Tirar" name="detach"/>
+ <menu_item_call label="Editar look" name="edit"/>
+</context_menu>
diff --git a/indra/newview/skins/minimal/xui/pt/notifications.xml b/indra/newview/skins/minimal/xui/pt/notifications.xml
new file mode 100644
index 0000000000..30ba6f68bf
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/notifications.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<notifications>
+ <notification name="UserGiveItem">
+ [NAME_SLURL] quer lhe dar [ITEM_SLURL]. Esta ação requer o modo Avançado. Passe para o modo avançado e você verá o item em seu inventário. Para passar para o modo avançado, feche e reinicialize esse aplicativo e mude o modo (indicado na tela de login).
+ <form name="form">
+ <button name="Show" text="Guardar item"/>
+ <button name="Discard" text="Recusar item"/>
+ <button name="Mute" text="Bloquear usuário"/>
+ </form>
+ </notification>
+ <notification name="ObjectGiveItem">
+ Um objeto chamado &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt;, de [NAME_SLURL], está lhe oferecendo [ITEM_SLURL]. Esta ação requer o modo Avançado. Passe para o modo Avançado e você verá o item em seu Inventário. Para passar para o modo Avançado, feche e reinicialize esse aplicativo e mude o modo (indicado na tela de login).
+ <form name="form">
+ <button name="Keep" text="Guardar item"/>
+ <button name="Discard" text="Recusar item"/>
+ <button name="Mute" text="Bloquear objeto"/>
+ </form>
+ </notification>
+</notifications>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_adhoc_control_panel.xml b/indra/newview/skins/minimal/xui/pt/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..bd50d4953d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_adhoc_control_panel.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="vertical_stack">
+ <layout_panel name="call_btn_panel">
+ <button label="Ligar" name="call_btn"/>
+ </layout_panel>
+ <layout_panel name="end_call_btn_panel">
+ <button label="Desligar" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Controles de voz" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_bottomtray.xml b/indra/newview/skins/minimal/xui/pt/panel_bottomtray.xml
new file mode 100644
index 0000000000..f67823dbd8
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_bottomtray.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="bottom_tray">
+ <string name="DragIndicationImageName" value="Accordion_ArrowOpened_Off"/>
+ <string name="SpeakBtnToolTip" value="Liga e desliga o microfone"/>
+ <string name="VoiceControlBtnToolTip" value="Mostra/oculta os controles de voz"/>
+ <layout_stack name="toolbar_stack">
+ <layout_panel name="gesture_panel">
+ <gesture_combo_list label="Gesto" name="Gesture" tool_tip="Mostra/oculta os gestos"/>
+ </layout_panel>
+ <layout_panel name="cam_panel">
+ <bottomtray_button label="Exibir" name="camera_btn" tool_tip="Mostra/oculta os controles da câmera"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Destinos" name="destination_btn" tool_tip="Exibe janela de pessoas"/>
+ </layout_panel>
+ <layout_panel name="avatar_and_destinations_panel">
+ <bottomtray_button label="Meu avatar" name="avatar_btn"/>
+ </layout_panel>
+ <layout_panel name="people_panel">
+ <bottomtray_button label="Pessoas" name="show_people_button" tool_tip="Exibe as pessoas"/>
+ </layout_panel>
+ <layout_panel name="profile_panel">
+ <bottomtray_button label="Perfil" name="show_profile_btn" tool_tip="Exibe o perfil"/>
+ </layout_panel>
+ <layout_panel name="howto_panel">
+ <bottomtray_button label="Como..." name="show_help_btn" tool_tip="Abrir &quot;Como...&quot; do Second Life"/>
+ </layout_panel>
+ <layout_panel name="im_well_panel">
+ <chiclet_im_well name="im_well">
+ <button name="Unread IM messages" tool_tip="Conversas"/>
+ </chiclet_im_well>
+ </layout_panel>
+ <layout_panel name="notification_well_panel">
+ <chiclet_notification name="notification_well">
+ <button name="Unread" tool_tip="Notificações"/>
+ </chiclet_notification>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_group_control_panel.xml b/indra/newview/skins/minimal/xui/pt/panel_group_control_panel.xml
new file mode 100644
index 0000000000..177cee28a6
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_group_control_panel.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="vertical_stack">
+ <layout_panel name="end_call_btn_panel">
+ <button label="Desligar" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Abrir controles de voz" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/pt/panel_im_control_panel.xml
new file mode 100644
index 0000000000..91b7d1b7cd
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_im_control_panel.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_im_control_panel">
+ <layout_stack name="button_stack">
+ <layout_panel name="view_profile_btn_panel">
+ <button label="Perfil" name="view_profile_btn"/>
+ </layout_panel>
+ <layout_panel name="add_friend_btn_panel">
+ <button label="Adicionar amigo" name="add_friend_btn"/>
+ </layout_panel>
+ <layout_panel name="teleport_btn_panel">
+ <button label="Teletransportar" name="teleport_btn" tool_tip="Oferecer teletransporte"/>
+ </layout_panel>
+ <layout_panel name="share_btn_panel">
+ <button label="Compartilhar" name="share_btn"/>
+ </layout_panel>
+ <layout_panel name="pay_btn_panel">
+ <button label="Pagar" name="pay_btn"/>
+ </layout_panel>
+ <layout_panel name="call_btn_panel">
+ <button label="Ligar" name="call_btn"/>
+ </layout_panel>
+ <layout_panel name="end_call_btn_panel">
+ <button label="Encerrar ligação" name="end_call_btn"/>
+ </layout_panel>
+ <layout_panel name="voice_ctrls_btn_panel">
+ <button label="Controles de voz" name="voice_ctrls_btn"/>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_login.xml b/indra/newview/skins/minimal/xui/pt/panel_login.xml
new file mode 100644
index 0000000000..de9717874f
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_login.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="panel_login">
+ <panel.string name="create_account_url">
+ http://join.secondlife.com/
+ </panel.string>
+ <panel.string name="forgot_password_url">
+ http://secondlife.com/account/request.php?lang=pt
+ </panel.string>
+ <layout_stack name="login_widgets">
+ <layout_panel name="login">
+ <text name="username_text">
+ Nome de usuário:
+ </text>
+ <combo_box name="username_combo" tool_tip="O nome de usuário que você escolheu ao fazer seu cadastro, como zecazc12 or Magia Solar"/>
+ <text name="password_text">
+ Senha:
+ </text>
+ <check_box label="Lembrar senha" name="remember_check"/>
+ <button label="conectar" name="connect_btn"/>
+ <text name="mode_selection_text">
+ Modo:
+ </text>
+ <combo_box name="mode_combo" tool_tip="Selecione o modo. O modo Básico é mais rápido e ideal para explorar e conversar. Use o modo Avançado para acessar mais recursos.">
+ <combo_box.item label="Básico" name="Basic"/>
+ <combo_box.item label="Avançado" name="Advanced"/>
+ </combo_box>
+ </layout_panel>
+ <layout_panel name="links">
+ <text name="create_new_account_text">
+ Cadastre-se
+ </text>
+ <text name="forgot_password_text">
+ Esqueceu seu nome ou senha?
+ </text>
+ <text name="login_help">
+ Precisa de ajuda ao conectar?
+ </text>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_navigation_bar.xml b/indra/newview/skins/minimal/xui/pt/panel_navigation_bar.xml
new file mode 100644
index 0000000000..01930bf3b3
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_navigation_bar.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="navigation_bar">
+ <panel name="navigation_panel">
+ <pull_button name="back_btn" tool_tip="Voltar para região anterior"/>
+ <pull_button name="forward_btn" tool_tip="Avançar uma região"/>
+ <button name="home_btn" tool_tip="Teletransportar para meu início"/>
+ <location_input label="Onde" name="location_combo"/>
+ <search_combo_box label="Busca" name="search_combo_box" tool_tip="Busca">
+ <combo_editor label="Buscar no [SECOND_LIFE]" name="search_combo_editor"/>
+ </search_combo_box>
+ </panel>
+ <favorites_bar name="favorite" tool_tip="Arraste marcos para cá para acessar seus lugares preferidos do Second Life!">
+ <label name="favorites_bar_label" tool_tip="Arraste marcos para cá para acessar seus lugares preferidos do Second Life!">
+ Barra Destaques
+ </label>
+ <chevron_button name="&gt;&gt;" tool_tip="Mostrar mais favoritos"/>
+ </favorites_bar>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_people.xml b/indra/newview/skins/minimal/xui/pt/panel_people.xml
new file mode 100644
index 0000000000..935ade2177
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_people.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- Side tray panel -->
+<panel label="Pessoas" name="people_panel">
+ <string name="no_recent_people" value="Ninguém, recentemente. Em busca de alguém para conversar? Confira o botão Destinos abaixo."/>
+ <string name="no_filtered_recent_people" value="Não há ninguém com esse nome ultimamente."/>
+ <string name="no_one_near" value="Ninguém por perto Em busca de alguém para conversar? Confira o botão Destinos abaixo."/>
+ <string name="no_one_filtered_near" value="Não há ninguém com esse nome por perto."/>
+ <string name="no_friends_online" value="Nenhum amigo online"/>
+ <string name="no_friends" value="Nenhum amigo"/>
+ <string name="no_friends_msg">
+ Clique em um residente com o botão direito to mouse para adicioná-lo como amigo.
+Em busca de alguém para conversar? Confira o botão Destinos abaixo.
+ </string>
+ <string name="no_filtered_friends_msg">
+ Não encontrou o que procura? Confira o botão Destinos abaixo.
+ </string>
+ <string name="people_filter_label" value="Filtro de pessoas"/>
+ <string name="groups_filter_label" value="Filtro de grupos"/>
+ <string name="no_filtered_groups_msg" value="Não encontrou o que procura? Tente buscar no [secondlife:///app/search/groups/[SEARCH_TERM] Search]."/>
+ <string name="no_groups_msg" value="À procura de grupos interessantes? Tente fazer uma [secondlife:///app/search/groups Busca]."/>
+ <string name="MiniMapToolTipMsg" value="[REGION](Clique duplo para abrir o Mapa, botão Shift e arrastar para ver mais)"/>
+ <string name="AltMiniMapToolTipMsg" value="[REGION](Clique duplo para se teletransportar, botão Shift e arrastar para ver mais)"/>
+ <filter_editor label="Filtro" name="filter_input"/>
+ <tab_container name="tabs">
+ <panel label="PROXIMIDADE" name="nearby_panel">
+ <panel label="bottom_panel" name="bottom_panel"/>
+ </panel>
+ <panel label="MEUS AMIGOS" name="friends_panel">
+ <accordion name="friends_accordion">
+ <accordion_tab name="tab_online" title="Online"/>
+ <accordion_tab name="tab_all" title="Todos"/>
+ </accordion>
+ <panel label="bottom_panel" name="bottom_panel">
+ <layout_stack name="bottom_panel">
+ <layout_panel name="trash_btn_panel">
+ <dnd_button name="del_btn" tool_tip="Remover a pessoa selecionada da sua lista de amigos"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+ </panel>
+ <panel label="RECENTE" name="recent_panel">
+ <panel label="bottom_panel" name="bottom_panel">
+ <button name="add_friend_btn" tool_tip="Adicionar o residente selecionado para sua lista de amigos"/>
+ </panel>
+ </panel>
+ </tab_container>
+ <panel name="button_bar">
+ <layout_stack name="bottom_bar_ls">
+ <layout_panel name="view_profile_btn_lp">
+ <button label="Perfil" name="view_profile_btn" tool_tip="Exibir fotografia, grupos e outras informações dos residentes"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="MI" name="im_btn" tool_tip="Abrir sessão de mensagem instantânea"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Teletransportar" name="teleport_btn" tool_tip="Oferecer teletransporte"/>
+ </layout_panel>
+ </layout_stack>
+ <layout_stack name="bottom_bar_ls1">
+ <layout_panel name="group_info_btn_lp">
+ <button label="Perfil do grupo" name="group_info_btn" tool_tip="Exibir dados do grupo"/>
+ </layout_panel>
+ <layout_panel name="chat_btn_lp">
+ <button label="Bate-papo de grupo" name="chat_btn" tool_tip="Nova sessão de bate-papo"/>
+ </layout_panel>
+ <layout_panel name="group_call_btn_lp">
+ <button label="Ligar para o grupo" name="group_call_btn" tool_tip="Ligar para este grupo"/>
+ </layout_panel>
+ </layout_stack>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_side_tray_tab_caption.xml b/indra/newview/skins/minimal/xui/pt/panel_side_tray_tab_caption.xml
new file mode 100644
index 0000000000..09444a5535
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_side_tray_tab_caption.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="sidetray_tab_panel">
+ <text name="sidetray_tab_title" value="Bandeja lateral"/>
+ <button name="undock" tool_tip="Soltar janela"/>
+ <button name="dock" tool_tip="Ancorar janela"/>
+ <button name="show_help" tool_tip="Mostrar ajuda"/>
+</panel>
diff --git a/indra/newview/skins/minimal/xui/pt/panel_status_bar.xml b/indra/newview/skins/minimal/xui/pt/panel_status_bar.xml
new file mode 100644
index 0000000000..f7890ae57d
--- /dev/null
+++ b/indra/newview/skins/minimal/xui/pt/panel_status_bar.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="status">
+ <panel.string name="StatBarDaysOfWeek">
+ Domingo:Segunda-feira:Terça-feira:Quarta-feira:Quinta-feira:Sexta-feira:Sábado
+ </panel.string>
+ <panel.string name="StatBarMonthsOfYear">
+ Janeiro:Fevereiro:Março:Abril:Maio:Junho:Julho:Agosto:Setembro:Outubro:Novembro:Dezembro
+ </panel.string>
+ <panel.string name="packet_loss_tooltip">
+ Perda de pacote
+ </panel.string>
+ <panel.string name="bandwidth_tooltip">
+ Banda
+ </panel.string>
+ <panel.string name="time">
+ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt]
+ </panel.string>
+ <panel.string name="timeTooltip">
+ [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt]
+ </panel.string>
+ <panel.string name="buycurrencylabel">
+ L$ [AMT]
+ </panel.string>
+ <panel name="balance_bg">
+ <text name="balance" tool_tip="Atualizar saldo de L$" value="L$20"/>
+ <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/>
+ </panel>
+ <text name="TimeText" tool_tip="Hora atual (Pacífico)">
+ 24:00 AM PST
+ </text>
+ <button name="media_toggle_btn" tool_tip="Tocar/Pausar todas mídias (música, vídeo, páginas web)"/>
+ <button name="volume_btn" tool_tip="Volume geral"/>
+</panel>
diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp
index 9da851ffc4..d691bb6c44 100644
--- a/indra/newview/tests/llcapabilitylistener_test.cpp
+++ b/indra/newview/tests/llcapabilitylistener_test.cpp
@@ -72,7 +72,7 @@ struct TestCapabilityProvider: public LLCapabilityProvider
{
mCaps[cap] = url;
}
- LLHost getHost() const { return mHost; }
+ const LLHost& getHost() const { return mHost; }
std::string getDescription() const { return "TestCapabilityProvider"; }
LLHost mHost;
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index db50b89620..9e321db889 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -40,6 +40,7 @@
#if defined(LL_WINDOWS)
#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
+#pragma warning(disable: 4702) // disable 'unreachable code' so we can safely use skip().
#endif
// Constants
@@ -48,6 +49,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.
//-----------------------------------------------------------------------------
@@ -65,6 +69,7 @@ static bool gDisconnectCalled = false;
#include "../llviewerwindow.h"
void LLViewerWindow::setShowProgress(BOOL show) {}
+LLProgressView * LLViewerWindow::getProgressView(void) const { return 0; }
LLViewerWindow* gViewerWindow;
@@ -160,7 +165,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 +181,45 @@ 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 "../llappviewer.h"
+void LLAppViewer::forceQuit(void) {}
+LLAppViewer * LLAppViewer::sInstance = 0;
+
+//-----------------------------------------------------------------------------
+#include "llnotificationsutil.h"
+LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ boost::function<void (const LLSD&, const LLSD&)> functor) { return LLNotificationPtr((LLNotification*)0); }
+
+
+//-----------------------------------------------------------------------------
+#include "llupdaterservice.h"
+
+std::string const & LLUpdaterService::pumpName(void)
+{
+ static std::string wakka = "wakka wakka wakka";
+ return wakka;
+}
+bool LLUpdaterService::updateReadyToInstall(void) { return false; }
+void LLUpdaterService::initialize(const std::string& protocol_version,
+ const std::string& url,
+ const std::string& path,
+ const std::string& channel,
+ const std::string& version) {}
+
+void LLUpdaterService::setCheckPeriod(unsigned int seconds) {}
+void LLUpdaterService::startChecking(bool install_if_ready) {}
+void LLUpdaterService::stopChecking() {}
+bool LLUpdaterService::isChecking() { return false; }
+LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; }
+std::string LLUpdaterService::updatedVersion() { return ""; }
//-----------------------------------------------------------------------------
#include "llnotifications.h"
@@ -192,6 +235,12 @@ LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key,
return NULL;
}
+//----------------------------------------------------------------------------
+#include "../llprogressview.h"
+void LLProgressView::setText(std::string const &){}
+void LLProgressView::setPercent(float){}
+void LLProgressView::setMessage(std::string const &){}
+
//-----------------------------------------------------------------------------
// LLNotifications
class MockNotifications : public LLNotificationsInterface
@@ -290,7 +339,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);
@@ -430,6 +478,8 @@ namespace tut
template<> template<>
void lllogininstance_object::test<3>()
{
+ skip();
+
set_test_name("Test Mandatory Update User Accepts");
// Part 1 - Mandatory Update, with User accepts response.
@@ -457,6 +507,8 @@ namespace tut
template<> template<>
void lllogininstance_object::test<4>()
{
+ skip();
+
set_test_name("Test Mandatory Update User Decline");
// Test connect with update needed.
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
new file mode 100644
index 0000000000..9a6e08ee84
--- /dev/null
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -0,0 +1,136 @@
+/**
+ * @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"
+#include "llurlentry.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 const* const _PREHASH_AgentID = 0; // never dereferenced during this test
+char const* const _PREHASH_AgentData = 0; // never dereferenced during this test
+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) { }
+void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { }
+
+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/llsimplestat_test.cpp b/indra/newview/tests/llsimplestat_test.cpp
new file mode 100644
index 0000000000..b556941f4a
--- /dev/null
+++ b/indra/newview/tests/llsimplestat_test.cpp
@@ -0,0 +1,580 @@
+/**
+ * @file llsimplestats_test.cpp
+ * @date 2010-10-22
+ * @brief Test cases for some of llsimplestat.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$
+ */
+
+#include "linden_common.h"
+
+#include <tut/tut.hpp>
+
+#include "lltut.h"
+#include "../llsimplestat.h"
+#include "llsd.h"
+#include "llmath.h"
+
+// @brief Used as a pointer cast type to get access to LLSimpleStatCounter
+class TutStatCounter: public LLSimpleStatCounter
+{
+public:
+ TutStatCounter(); // Not defined
+ ~TutStatCounter(); // Not defined
+ void operator=(const TutStatCounter &); // Not defined
+
+ void setRawCount(U32 c) { mCount = c; }
+ U32 getRawCount() const { return mCount; }
+};
+
+
+namespace tut
+{
+ struct stat_counter_index
+ {};
+ typedef test_group<stat_counter_index> stat_counter_index_t;
+ typedef stat_counter_index_t::object stat_counter_index_object_t;
+ tut::stat_counter_index_t tut_stat_counter_index("stat_counter_test");
+
+ // Testing LLSimpleStatCounter's external interface
+ template<> template<>
+ void stat_counter_index_object_t::test<1>()
+ {
+ LLSimpleStatCounter c1;
+ ensure("Initialized counter is zero", (0 == c1.getCount()));
+
+ ensure("Counter increment return is 1", (1 == ++c1));
+ ensure("Counter increment return is 2", (2 == ++c1));
+
+ ensure("Current counter is 2", (2 == c1.getCount()));
+
+ c1.reset();
+ ensure("Counter is 0 after reset", (0 == c1.getCount()));
+
+ ensure("Counter increment return is 1", (1 == ++c1));
+ }
+
+ // Testing LLSimpleStatCounter's internal state
+ template<> template<>
+ void stat_counter_index_object_t::test<2>()
+ {
+ LLSimpleStatCounter c1;
+ TutStatCounter * tc1 = (TutStatCounter *) &c1;
+
+ ensure("Initialized private counter is zero", (0 == tc1->getRawCount()));
+
+ ++c1;
+ ++c1;
+
+ ensure("Current private counter is 2", (2 == tc1->getRawCount()));
+
+ c1.reset();
+ ensure("Raw counter is 0 after reset", (0 == tc1->getRawCount()));
+ }
+
+ // Testing LLSimpleStatCounter's wrapping behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<3>()
+ {
+ LLSimpleStatCounter c1;
+ TutStatCounter * tc1 = (TutStatCounter *) &c1;
+
+ tc1->setRawCount(U32_MAX);
+ ensure("Initialized private counter is zero", (U32_MAX == c1.getCount()));
+
+ ensure("Increment of max value wraps to 0", (0 == ++c1));
+ }
+
+ // Testing LLSimpleStatMMM's external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<4>()
+ {
+ LLSimpleStatMMM<> m1;
+ typedef LLSimpleStatMMM<>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1.0);
+ ensure("Single insert MMM<> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("Single insert MMM<> has 1.0 max", (1.0 == m1.getMax()));
+ ensure("Single insert MMM<> has 1.0 mean", (1.0 == m1.getMean()));
+
+ // Second insert
+ m1.record(3.0);
+ ensure("2nd insert MMM<> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("2nd insert MMM<> has 3.0 max", (3.0 == m1.getMax()));
+ ensure_approximately_equals("2nd insert MMM<> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
+
+ // Third insert
+ m1.record(5.0);
+ ensure("3rd insert MMM<> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("3rd insert MMM<> has 5.0 max", (5.0 == m1.getMax()));
+ ensure_approximately_equals("3rd insert MMM<> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
+
+ // Fourth insert
+ m1.record(1000000.0);
+ ensure("4th insert MMM<> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("4th insert MMM<> has 100000.0 max", (1000000.0 == m1.getMax()));
+ ensure_approximately_equals("4th insert MMM<> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<5>()
+ {
+ LLSimpleStatMMM<> m1;
+ typedef LLSimpleStatMMM<>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Insert overflowing values
+ const lcl_float bignum(F32_MAX / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<> has fetchable mean", (1.0 == m1.getMean() || true));
+ // We should be infinte but not interested in proving the IEEE standard here.
+ LLSD sd1(m1.getMean());
+ // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl;
+ ensure("Overflowed MMM<> produces LLSDable Real", (sd1.isReal()));
+ }
+
+ // Testing LLSimpleStatMMM<F32>'s external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<6>()
+ {
+ LLSimpleStatMMM<F32> m1;
+ typedef LLSimpleStatMMM<F32>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<F32> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<F32> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<F32> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<F32> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1.0);
+ ensure("Single insert MMM<F32> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("Single insert MMM<F32> has 1.0 max", (1.0 == m1.getMax()));
+ ensure("Single insert MMM<F32> has 1.0 mean", (1.0 == m1.getMean()));
+
+ // Second insert
+ m1.record(3.0);
+ ensure("2nd insert MMM<F32> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("2nd insert MMM<F32> has 3.0 max", (3.0 == m1.getMax()));
+ ensure_approximately_equals("2nd insert MMM<F32> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
+
+ // Third insert
+ m1.record(5.0);
+ ensure("3rd insert MMM<F32> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("3rd insert MMM<F32> has 5.0 max", (5.0 == m1.getMax()));
+ ensure_approximately_equals("3rd insert MMM<F32> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
+
+ // Fourth insert
+ m1.record(1000000.0);
+ ensure("4th insert MMM<F32> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<F32> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("4th insert MMM<F32> has 1000000.0 max", (1000000.0 == m1.getMax()));
+ ensure_approximately_equals("4th insert MMM<F32> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<F32> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<F32> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<F32> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<F32> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<7>()
+ {
+ LLSimpleStatMMM<F32> m1;
+ typedef LLSimpleStatMMM<F32>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Insert overflowing values
+ const lcl_float bignum(F32_MAX / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<F32> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<F32> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<F32> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<F32> has fetchable mean", (1.0 == m1.getMean() || true));
+ // We should be infinte but not interested in proving the IEEE standard here.
+ LLSD sd1(m1.getMean());
+ // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl;
+ ensure("Overflowed MMM<F32> produces LLSDable Real", (sd1.isReal()));
+ }
+
+ // Testing LLSimpleStatMMM<F64>'s external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<8>()
+ {
+ LLSimpleStatMMM<F64> m1;
+ typedef LLSimpleStatMMM<F64>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<F64> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<F64> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<F64> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<F64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1.0);
+ ensure("Single insert MMM<F64> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("Single insert MMM<F64> has 1.0 max", (1.0 == m1.getMax()));
+ ensure("Single insert MMM<F64> has 1.0 mean", (1.0 == m1.getMean()));
+
+ // Second insert
+ m1.record(3.0);
+ ensure("2nd insert MMM<F64> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("2nd insert MMM<F64> has 3.0 max", (3.0 == m1.getMax()));
+ ensure_approximately_equals("2nd insert MMM<F64> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1);
+
+ // Third insert
+ m1.record(5.0);
+ ensure("3rd insert MMM<F64> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("3rd insert MMM<F64> has 5.0 max", (5.0 == m1.getMax()));
+ ensure_approximately_equals("3rd insert MMM<F64> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1);
+
+ // Fourth insert
+ m1.record(1000000.0);
+ ensure("4th insert MMM<F64> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<F64> has 1.0 min", (1.0 == m1.getMin()));
+ ensure("4th insert MMM<F64> has 1000000.0 max", (1000000.0 == m1.getMax()));
+ ensure_approximately_equals("4th insert MMM<F64> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1);
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<F64> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<F64> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<F64> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<F64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<9>()
+ {
+ LLSimpleStatMMM<F64> m1;
+ typedef LLSimpleStatMMM<F64>::Value lcl_float;
+ lcl_float zero(0);
+
+ // Insert overflowing values
+ const lcl_float bignum(F64_MAX / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<F64> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<F64> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<F64> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<F64> has fetchable mean", (1.0 == m1.getMean() || true));
+ // We should be infinte but not interested in proving the IEEE standard here.
+ LLSD sd1(m1.getMean());
+ // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl;
+ ensure("Overflowed MMM<F64> produces LLSDable Real", (sd1.isReal()));
+ }
+
+ // Testing LLSimpleStatMMM<U64>'s external behavior
+ template<> template<>
+ void stat_counter_index_object_t::test<10>()
+ {
+ LLSimpleStatMMM<U64> m1;
+ typedef LLSimpleStatMMM<U64>::Value lcl_int;
+ lcl_int zero(0);
+
+ // Freshly-constructed
+ ensure("Constructed MMM<U64> has 0 count", (0 == m1.getCount()));
+ ensure("Constructed MMM<U64> has 0 min", (zero == m1.getMin()));
+ ensure("Constructed MMM<U64> has 0 max", (zero == m1.getMax()));
+ ensure("Constructed MMM<U64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+
+ // Single insert
+ m1.record(1);
+ ensure("Single insert MMM<U64> has 1 count", (1 == m1.getCount()));
+ ensure("Single insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("Single insert MMM<U64> has 1 max", (1 == m1.getMax()));
+ ensure("Single insert MMM<U64> has 1 mean", (1 == m1.getMean()));
+
+ // Second insert
+ m1.record(3);
+ ensure("2nd insert MMM<U64> has 2 count", (2 == m1.getCount()));
+ ensure("2nd insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("2nd insert MMM<U64> has 3 max", (3 == m1.getMax()));
+ ensure("2nd insert MMM<U64> has 2 mean", (2 == m1.getMean()));
+
+ // Third insert
+ m1.record(5);
+ ensure("3rd insert MMM<U64> has 3 count", (3 == m1.getCount()));
+ ensure("3rd insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("3rd insert MMM<U64> has 5 max", (5 == m1.getMax()));
+ ensure("3rd insert MMM<U64> has 3 mean", (3 == m1.getMean()));
+
+ // Fourth insert
+ m1.record(U64L(1000000000000));
+ ensure("4th insert MMM<U64> has 4 count", (4 == m1.getCount()));
+ ensure("4th insert MMM<U64> has 1 min", (1 == m1.getMin()));
+ ensure("4th insert MMM<U64> has 1000000000000ULL max", (U64L(1000000000000) == m1.getMax()));
+ ensure("4th insert MMM<U64> has 250000000002ULL mean", (U64L( 250000000002) == m1.getMean()));
+
+ // Reset
+ m1.reset();
+ ensure("Reset MMM<U64> has 0 count", (0 == m1.getCount()));
+ ensure("Reset MMM<U64> has 0 min", (zero == m1.getMin()));
+ ensure("Reset MMM<U64> has 0 max", (zero == m1.getMax()));
+ ensure("Reset MMM<U64> has 0 mean no div-by-zero", (zero == m1.getMean()));
+ }
+
+ // Testing LLSimpleStatMMM's response to large values
+ template<> template<>
+ void stat_counter_index_object_t::test<11>()
+ {
+ LLSimpleStatMMM<U64> m1;
+ typedef LLSimpleStatMMM<U64>::Value lcl_int;
+ lcl_int zero(0);
+
+ // Insert overflowing values
+ const lcl_int bignum(U64L(0xffffffffffffffff) / 2);
+
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(bignum);
+ m1.record(zero);
+
+ ensure("Overflowed MMM<U64> has 8 count", (8 == m1.getCount()));
+ ensure("Overflowed MMM<U64> has 0 min", (zero == m1.getMin()));
+ ensure("Overflowed MMM<U64> has huge max", (bignum == m1.getMax()));
+ ensure("Overflowed MMM<U64> has fetchable mean", (zero == m1.getMean() || true));
+ }
+
+ // Testing LLSimpleStatCounter's merge() method
+ template<> template<>
+ void stat_counter_index_object_t::test<12>()
+ {
+ LLSimpleStatCounter c1;
+ LLSimpleStatCounter c2;
+
+ ++c1;
+ ++c1;
+ ++c1;
+ ++c1;
+
+ ++c2;
+ ++c2;
+ c2.merge(c1);
+
+ ensure_equals("4 merged into 2 results in 6", 6, c2.getCount());
+
+ ensure_equals("Source of merge is undamaged", 4, c1.getCount());
+ }
+
+ // Testing LLSimpleStatMMM's merge() method
+ template<> template<>
+ void stat_counter_index_object_t::test<13>()
+ {
+ LLSimpleStatMMM<> m1;
+ LLSimpleStatMMM<> m2;
+
+ m1.record(3.5);
+ m1.record(4.5);
+ m1.record(5.5);
+ m1.record(6.5);
+
+ m2.record(5.0);
+ m2.record(7.0);
+ m2.record(9.0);
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p1)", 7, m2.getCount());
+ ensure_approximately_equals("Min after merge (p1)", F32(3.5), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p1)", F32(41.000/7.000), m2.getMean(), 22);
+
+
+ ensure_equals("Source count of merge is undamaged (p1)", 4, m1.getCount());
+ ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(3.5), m1.getMin(), 22);
+ ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(6.5), m1.getMax(), 22);
+ ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(5.0), m1.getMean(), 22);
+
+ m2.reset();
+
+ m2.record(-22.0);
+ m2.record(-1.0);
+ m2.record(30.0);
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p2)", 7, m2.getCount());
+ ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p2)", F32(30.0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p2)", F32(27.000/7.000), m2.getMean(), 22);
+
+ }
+
+ // Testing LLSimpleStatMMM's merge() method when src contributes nothing
+ template<> template<>
+ void stat_counter_index_object_t::test<14>()
+ {
+ LLSimpleStatMMM<> m1;
+ LLSimpleStatMMM<> m2;
+
+ m2.record(5.0);
+ m2.record(7.0);
+ m2.record(9.0);
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p1)", 3, m2.getCount());
+ ensure_approximately_equals("Min after merge (p1)", F32(5.0), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p1)", F32(7.000), m2.getMean(), 22);
+
+ ensure_equals("Source count of merge is undamaged (p1)", 0, m1.getCount());
+ ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(0), m1.getMin(), 22);
+ ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(0), m1.getMax(), 22);
+ ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(0), m1.getMean(), 22);
+
+ m2.reset();
+
+ m2.record(-22.0);
+ m2.record(-1.0);
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p2)", 2, m2.getCount());
+ ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p2)", F32(-1.0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p2)", F32(-11.5), m2.getMean(), 22);
+ }
+
+ // Testing LLSimpleStatMMM's merge() method when dst contributes nothing
+ template<> template<>
+ void stat_counter_index_object_t::test<15>()
+ {
+ LLSimpleStatMMM<> m1;
+ LLSimpleStatMMM<> m2;
+
+ m1.record(5.0);
+ m1.record(7.0);
+ m1.record(9.0);
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p1)", 3, m2.getCount());
+ ensure_approximately_equals("Min after merge (p1)", F32(5.0), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p1)", F32(7.000), m2.getMean(), 22);
+
+ ensure_equals("Source count of merge is undamaged (p1)", 3, m1.getCount());
+ ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(5.0), m1.getMin(), 22);
+ ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(9.0), m1.getMax(), 22);
+ ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(7.0), m1.getMean(), 22);
+
+ m1.reset();
+ m2.reset();
+
+ m1.record(-22.0);
+ m1.record(-1.0);
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p2)", 2, m2.getCount());
+ ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p2)", F32(-1.0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p2)", F32(-11.5), m2.getMean(), 22);
+ }
+
+ // Testing LLSimpleStatMMM's merge() method when neither dst nor src contributes
+ template<> template<>
+ void stat_counter_index_object_t::test<16>()
+ {
+ LLSimpleStatMMM<> m1;
+ LLSimpleStatMMM<> m2;
+
+ m2.merge(m1);
+
+ ensure_equals("Count after merge (p1)", 0, m2.getCount());
+ ensure_approximately_equals("Min after merge (p1)", F32(0), m2.getMin(), 22);
+ ensure_approximately_equals("Max after merge (p1)", F32(0), m2.getMax(), 22);
+ ensure_approximately_equals("Mean after merge (p1)", F32(0), m2.getMean(), 22);
+
+ ensure_equals("Source count of merge is undamaged (p1)", 0, m1.getCount());
+ ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(0), m1.getMin(), 22);
+ ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(0), m1.getMax(), 22);
+ ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(0), m1.getMean(), 22);
+ }
+}
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/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
new file mode 100644
index 0000000000..3faddc13c1
--- /dev/null
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -0,0 +1,984 @@
+/**
+ * @file llviewerassetstats_tut.cpp
+ * @date 2010-10-28
+ * @brief Test cases for some of newview/llviewerassetstats.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 <tut/tut.hpp>
+#include <iostream>
+
+#include "lltut.h"
+#include "../llviewerassetstats.h"
+#include "lluuid.h"
+#include "llsdutil.h"
+#include "llregionhandle.h"
+
+static const char * all_keys[] =
+{
+ "duration",
+ "fps",
+ "get_other",
+ "get_texture_temp_http",
+ "get_texture_temp_udp",
+ "get_texture_non_temp_http",
+ "get_texture_non_temp_udp",
+ "get_wearable_udp",
+ "get_sound_udp",
+ "get_gesture_udp"
+};
+
+static const char * resp_keys[] =
+{
+ "get_other",
+ "get_texture_temp_http",
+ "get_texture_temp_udp",
+ "get_texture_non_temp_http",
+ "get_texture_non_temp_udp",
+ "get_wearable_udp",
+ "get_sound_udp",
+ "get_gesture_udp"
+};
+
+static const char * sub_keys[] =
+{
+ "dequeued",
+ "enqueued",
+ "resp_count",
+ "resp_max",
+ "resp_min",
+ "resp_mean"
+};
+
+static const char * mmm_resp_keys[] =
+{
+ "fps"
+};
+
+static const char * mmm_sub_keys[] =
+{
+ "count",
+ "max",
+ "min",
+ "mean"
+};
+
+static const LLUUID region1("4e2d81a3-6263-6ffe-ad5c-8ce04bee07e8");
+static const LLUUID region2("68762cc8-b68b-4e45-854b-e830734f2d4a");
+static const U64 region1_handle(0x0000040000003f00ULL);
+static const U64 region2_handle(0x0000030000004200ULL);
+static const std::string region1_handle_str("0000040000003f00");
+static const std::string region2_handle_str("0000030000004200");
+
+#if 0
+static bool
+is_empty_map(const LLSD & sd)
+{
+ return sd.isMap() && 0 == sd.size();
+}
+
+static bool
+is_single_key_map(const LLSD & sd, const std::string & key)
+{
+ return sd.isMap() && 1 == sd.size() && sd.has(key);
+}
+#endif
+
+static bool
+is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2)
+{
+ return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2);
+}
+
+static bool
+is_no_stats_map(const LLSD & sd)
+{
+ return is_double_key_map(sd, "duration", "regions");
+}
+
+static bool
+is_single_slot_array(const LLSD & sd, U64 region_handle)
+{
+ U32 grid_x(0), grid_y(0);
+ grid_from_region_handle(region_handle, &grid_x, &grid_y);
+
+ return (sd.isArray() &&
+ 1 == sd.size() &&
+ sd[0].has("grid_x") &&
+ sd[0].has("grid_y") &&
+ sd[0]["grid_x"].isInteger() &&
+ sd[0]["grid_y"].isInteger() &&
+ grid_x == sd[0]["grid_x"].asInteger() &&
+ grid_y == sd[0]["grid_y"].asInteger());
+}
+
+static bool
+is_double_slot_array(const LLSD & sd, U64 region_handle1, U64 region_handle2)
+{
+ U32 grid_x1(0), grid_y1(0);
+ U32 grid_x2(0), grid_y2(0);
+ grid_from_region_handle(region_handle1, &grid_x1, &grid_y1);
+ grid_from_region_handle(region_handle2, &grid_x2, &grid_y2);
+
+ return (sd.isArray() &&
+ 2 == sd.size() &&
+ sd[0].has("grid_x") &&
+ sd[0].has("grid_y") &&
+ sd[0]["grid_x"].isInteger() &&
+ sd[0]["grid_y"].isInteger() &&
+ sd[1].has("grid_x") &&
+ sd[1].has("grid_y") &&
+ sd[1]["grid_x"].isInteger() &&
+ sd[1]["grid_y"].isInteger() &&
+ ((grid_x1 == sd[0]["grid_x"].asInteger() &&
+ grid_y1 == sd[0]["grid_y"].asInteger() &&
+ grid_x2 == sd[1]["grid_x"].asInteger() &&
+ grid_y2 == sd[1]["grid_y"].asInteger()) ||
+ (grid_x1 == sd[1]["grid_x"].asInteger() &&
+ grid_y1 == sd[1]["grid_y"].asInteger() &&
+ grid_x2 == sd[0]["grid_x"].asInteger() &&
+ grid_y2 == sd[0]["grid_y"].asInteger())));
+}
+
+static LLSD
+get_region(const LLSD & sd, U64 region_handle1)
+{
+ U32 grid_x(0), grid_y(0);
+ grid_from_region_handle(region_handle1, &grid_x, &grid_y);
+
+ for (LLSD::array_const_iterator it(sd["regions"].beginArray());
+ sd["regions"].endArray() != it;
+ ++it)
+ {
+ if ((*it).has("grid_x") &&
+ (*it).has("grid_y") &&
+ (*it)["grid_x"].isInteger() &&
+ (*it)["grid_y"].isInteger() &&
+ (*it)["grid_x"].asInteger() == grid_x &&
+ (*it)["grid_y"].asInteger() == grid_y)
+ {
+ return *it;
+ }
+ }
+ return LLSD();
+}
+
+namespace tut
+{
+ struct tst_viewerassetstats_index
+ {};
+ typedef test_group<tst_viewerassetstats_index> tst_viewerassetstats_index_t;
+ typedef tst_viewerassetstats_index_t::object tst_viewerassetstats_index_object_t;
+ tut::tst_viewerassetstats_index_t tut_tst_viewerassetstats_index("tst_viewerassetstats_test");
+
+ // Testing free functions without global stats allocated
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<1>()
+ {
+ // Check that helpers aren't bothered by missing global stats
+ ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain));
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12300000ULL);
+ }
+
+ // Create a non-global instance and check the structure
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<2>()
+ {
+ ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain));
+
+ LLViewerAssetStats * it = new LLViewerAssetStats();
+
+ ensure("Global gViewerAssetStatsMain should still be NULL", (NULL == gViewerAssetStatsMain));
+
+ LLSD sd_full = it->asLLSD(false);
+
+ // Default (NULL) region ID doesn't produce LLSD results so should
+ // get an empty map back from output
+ ensure("Stat-less LLSD initially", is_no_stats_map(sd_full));
+
+ // Once the region is set, we will get a response even with no data collection
+ it->setRegion(region1_handle);
+ sd_full = it->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions"));
+ ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle));
+
+ LLSD sd = sd_full["regions"][0];
+
+ delete it;
+
+ // Check the structure of the LLSD
+ for (int i = 0; i < LL_ARRAY_SIZE(all_keys); ++i)
+ {
+ std::string line = llformat("Has '%s' key", all_keys[i]);
+ ensure(line, sd.has(all_keys[i]));
+ }
+
+ for (int i = 0; i < LL_ARRAY_SIZE(resp_keys); ++i)
+ {
+ for (int j = 0; j < LL_ARRAY_SIZE(sub_keys); ++j)
+ {
+ std::string line = llformat("Key '%s' has '%s' key", resp_keys[i], sub_keys[j]);
+ ensure(line, sd[resp_keys[i]].has(sub_keys[j]));
+ }
+ }
+
+ for (int i = 0; i < LL_ARRAY_SIZE(mmm_resp_keys); ++i)
+ {
+ for (int j = 0; j < LL_ARRAY_SIZE(mmm_sub_keys); ++j)
+ {
+ std::string line = llformat("Key '%s' has '%s' key", mmm_resp_keys[i], mmm_sub_keys[j]);
+ ensure(line, sd[mmm_resp_keys[i]].has(mmm_sub_keys[j]));
+ }
+ }
+ }
+
+ // Create a non-global instance and check some content
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<3>()
+ {
+ LLViewerAssetStats * it = new LLViewerAssetStats();
+ it->setRegion(region1_handle);
+
+ LLSD sd = it->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
+ sd = sd[0];
+
+ delete it;
+
+ // Check a few points on the tree for content
+ ensure("sd[get_texture_temp_http][dequeued] is 0", (0 == sd["get_texture_temp_http"]["dequeued"].asInteger()));
+ ensure("sd[get_sound_udp][resp_min] is 0", (0.0 == sd["get_sound_udp"]["resp_min"].asReal()));
+ }
+
+ // Create a global instance and verify free functions do something useful
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<4>()
+ {
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ LLViewerAssetStatsFF::set_region_main(region1_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLSD sd = gViewerAssetStatsMain->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
+ sd = sd["regions"][0];
+
+ // Check a few points on the tree for content
+ ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+
+ ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+ }
+
+ // Create two global instances and verify no interactions
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<5>()
+ {
+ gViewerAssetStatsThread1 = new LLViewerAssetStats();
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ LLViewerAssetStatsFF::set_region_main(region1_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
+ ensure("Other collector is empty", is_no_stats_map(sd));
+ sd = gViewerAssetStatsMain->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
+ sd = sd["regions"][0];
+
+ // Check a few points on the tree for content
+ ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger()));
+ ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD(false)["regions"][0];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+ delete gViewerAssetStatsThread1;
+ gViewerAssetStatsThread1 = NULL;
+
+ ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+ }
+
+ // Check multiple region collection
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<6>()
+ {
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+
+ LLViewerAssetStatsFF::set_region_main(region1_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region2_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+
+ LLSD sd = gViewerAssetStatsMain->asLLSD(false);
+
+ // std::cout << sd << std::endl;
+
+ ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
+ ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
+ LLSD sd1 = get_region(sd, region1_handle);
+ LLSD sd2 = get_region(sd, region2_handle);
+ ensure("Region1 is present in results", sd1.isMap());
+ ensure("Region2 is present in results", sd2.isMap());
+
+ // Check a few points on the tree for content
+ ensure_equals("sd1[get_texture_non_temp_udp][enqueued] is 1", sd1["get_texture_non_temp_udp"]["enqueued"].asInteger(), 1);
+ ensure_equals("sd1[get_texture_temp_udp][enqueued] is 0", sd1["get_texture_temp_udp"]["enqueued"].asInteger(), 0);
+ ensure_equals("sd1[get_texture_non_temp_http][enqueued] is 0", sd1["get_texture_non_temp_http"]["enqueued"].asInteger(), 0);
+ ensure_equals("sd1[get_texture_temp_http][enqueued] is 0", sd1["get_texture_temp_http"]["enqueued"].asInteger(), 0);
+ ensure_equals("sd1[get_gesture_udp][dequeued] is 0", sd1["get_gesture_udp"]["dequeued"].asInteger(), 0);
+
+ // Check a few points on the tree for content
+ ensure("sd2[get_gesture_udp][enqueued] is 4", (4 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger()));
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
+ sd2 = sd["regions"][0];
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ }
+
+ // Check multiple region collection jumping back-and-forth between regions
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<7>()
+ {
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+
+ LLViewerAssetStatsFF::set_region_main(region1_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region2_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region1_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, true, true);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, true, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::set_region_main(region2_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false);
+
+ LLSD sd = gViewerAssetStatsMain->asLLSD(false);
+
+ ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
+ ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle));
+ LLSD sd1 = get_region(sd, region1_handle);
+ LLSD sd2 = get_region(sd, region2_handle);
+ ensure("Region1 is present in results", sd1.isMap());
+ ensure("Region2 is present in results", sd2.isMap());
+
+ // Check a few points on the tree for content
+ ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger()));
+ ensure("sd1[get_texture_temp_http][enqueued] is 1", (1 == sd1["get_texture_temp_http"]["enqueued"].asInteger()));
+ ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger()));
+
+ // Check a few points on the tree for content
+ ensure("sd2[get_gesture_udp][enqueued] is 8", (8 == sd2["get_gesture_udp"]["enqueued"].asInteger()));
+ ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger()));
+ ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = gViewerAssetStatsMain->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions"));
+ ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle));
+ sd2 = get_region(sd, region2_handle);
+ ensure("Region2 is present in results", sd2.isMap());
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+
+ ensure_equals("sd2[get_texture_non_temp_udp][enqueued] is reset", sd2["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0);
+ ensure_equals("sd2[get_gesture_udp][enqueued] is reset", sd2["get_gesture_udp"]["enqueued"].asInteger(), 0);
+ }
+
+ // Non-texture assets ignore transport and persistence flags
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<8>()
+ {
+ gViewerAssetStatsThread1 = new LLViewerAssetStats();
+ gViewerAssetStatsMain = new LLViewerAssetStats();
+ LLViewerAssetStatsFF::set_region_main(region1_handle);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, true);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, false);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, true);
+ LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, true);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, false);
+
+ LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ LLSD sd = gViewerAssetStatsThread1->asLLSD(false);
+ ensure("Other collector is empty", is_no_stats_map(sd));
+ sd = gViewerAssetStatsMain->asLLSD(false);
+ ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration"));
+ ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle));
+ sd = get_region(sd, region1_handle);
+ ensure("Region1 is present in results", sd.isMap());
+
+ // Check a few points on the tree for content
+ ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
+
+ ensure("sd[get_wearable_udp][enqueued] is 4", (4 == sd["get_wearable_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_wearable_udp][dequeued] is 4", (4 == sd["get_wearable_udp"]["dequeued"].asInteger()));
+
+ ensure("sd[get_other][enqueued] is 4", (4 == sd["get_other"]["enqueued"].asInteger()));
+ ensure("sd[get_other][dequeued] is 0", (0 == sd["get_other"]["dequeued"].asInteger()));
+
+ // Reset and check zeros...
+ // Reset leaves current region in place
+ gViewerAssetStatsMain->reset();
+ sd = get_region(gViewerAssetStatsMain->asLLSD(false), region1_handle);
+ ensure("Region1 is present in results", sd.isMap());
+
+ delete gViewerAssetStatsMain;
+ gViewerAssetStatsMain = NULL;
+ delete gViewerAssetStatsThread1;
+ gViewerAssetStatsThread1 = NULL;
+
+ ensure_equals("sd[get_texture_non_temp_udp][enqueued] is reset", sd["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0);
+ ensure_equals("sd[get_gesture_udp][dequeued] is reset", sd["get_gesture_udp"]["dequeued"].asInteger(), 0);
+ }
+
+
+ // LLViewerAssetStats::merge() basic functions work
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<9>()
+ {
+ LLViewerAssetStats s1;
+ LLViewerAssetStats s2;
+
+ s1.setRegion(region1_handle);
+ s2.setRegion(region1_handle);
+
+ s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 5000000);
+ s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 6000000);
+ s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 8000000);
+ s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 7000000);
+ s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 9000000);
+
+ s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 2000000);
+ s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 3000000);
+ s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 4000000);
+
+ s2.merge(s1);
+
+ LLSD s2_llsd = get_region(s2.asLLSD(false), region1_handle);
+ ensure("Region1 is present in results", s2_llsd.isMap());
+
+ ensure_equals("count after merge", s2_llsd["get_texture_temp_http"]["resp_count"].asInteger(), 8);
+ ensure_approximately_equals("min after merge", s2_llsd["get_texture_temp_http"]["resp_min"].asReal(), 2.0, 22);
+ ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_max"].asReal(), 9.0, 22);
+ ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_mean"].asReal(), 5.5, 22);
+ }
+
+ // LLViewerAssetStats::merge() basic functions work without corrupting source data
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<10>()
+ {
+ LLViewerAssetStats s1;
+ LLViewerAssetStats s2;
+
+ s1.setRegion(region1_handle);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900);
+
+
+ s2.setRegion(region2_handle);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000);
+ s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000);
+
+ {
+ s2.merge(s1);
+
+ LLSD src = s1.asLLSD(false);
+ LLSD dst = s2.asLLSD(false);
+
+ ensure_equals("merge src has single region", src["regions"].size(), 1);
+ ensure_equals("merge dst has dual regions", dst["regions"].size(), 2);
+
+ // Remove time stamps, they're a problem
+ src.erase("duration");
+ src["regions"][0].erase("duration");
+ dst.erase("duration");
+ dst["regions"][0].erase("duration");
+ dst["regions"][1].erase("duration");
+
+ LLSD s1_llsd = get_region(src, region1_handle);
+ ensure("Region1 is present in src", s1_llsd.isMap());
+ LLSD s2_llsd = get_region(dst, region1_handle);
+ ensure("Region1 is present in dst", s2_llsd.isMap());
+
+ ensure("result from src is in dst", llsd_equals(s1_llsd, s2_llsd));
+ }
+
+ s1.setRegion(region1_handle);
+ s2.setRegion(region1_handle);
+ s1.reset();
+ s2.reset();
+
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900);
+
+
+ s2.setRegion(region1_handle);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000);
+ s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000);
+
+ {
+ s2.merge(s1);
+
+ LLSD src = s1.asLLSD(false);
+ LLSD dst = s2.asLLSD(false);
+
+ ensure_equals("merge src has single region (p2)", src["regions"].size(), 1);
+ ensure_equals("merge dst has single region (p2)", dst["regions"].size(), 1);
+
+ // Remove time stamps, they're a problem
+ src.erase("duration");
+ src["regions"][0].erase("duration");
+ dst.erase("duration");
+ dst["regions"][0].erase("duration");
+
+ LLSD s1_llsd = get_region(src, region1_handle);
+ ensure("Region1 is present in src", s1_llsd.isMap());
+ LLSD s2_llsd = get_region(dst, region1_handle);
+ ensure("Region1 is present in dst", s2_llsd.isMap());
+
+ ensure_equals("src counts okay (enq)", s1_llsd["get_other"]["enqueued"].asInteger(), 4);
+ ensure_equals("src counts okay (deq)", s1_llsd["get_other"]["dequeued"].asInteger(), 4);
+ ensure_equals("src resp counts okay", s1_llsd["get_other"]["resp_count"].asInteger(), 2);
+ ensure_approximately_equals("src respmin okay", s1_llsd["get_other"]["resp_min"].asReal(), 0.2829, 20);
+ ensure_approximately_equals("src respmax okay", s1_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20);
+
+ ensure_equals("dst counts okay (enq)", s2_llsd["get_other"]["enqueued"].asInteger(), 12);
+ ensure_equals("src counts okay (deq)", s2_llsd["get_other"]["dequeued"].asInteger(), 11);
+ ensure_equals("dst resp counts okay", s2_llsd["get_other"]["resp_count"].asInteger(), 4);
+ ensure_approximately_equals("dst respmin okay", s2_llsd["get_other"]["resp_min"].asReal(), 0.010, 20);
+ ensure_approximately_equals("dst respmax okay", s2_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20);
+ }
+ }
+
+
+ // Maximum merges are interesting when one side contributes nothing
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<11>()
+ {
+ LLViewerAssetStats s1;
+ LLViewerAssetStats s2;
+
+ s1.setRegion(region1_handle);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ // Want to test negative numbers here but have to work in U64
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
+
+ s2.setRegion(region1_handle);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ {
+ s2.merge(s1);
+
+ LLSD src = s1.asLLSD(false);
+ LLSD dst = s2.asLLSD(false);
+
+ ensure_equals("merge src has single region", src["regions"].size(), 1);
+ ensure_equals("merge dst has single region", dst["regions"].size(), 1);
+
+ // Remove time stamps, they're a problem
+ src.erase("duration");
+ src["regions"][0].erase("duration");
+ dst.erase("duration");
+ dst["regions"][0].erase("duration");
+
+ LLSD s2_llsd = get_region(dst, region1_handle);
+ ensure("Region1 is present in dst", s2_llsd.isMap());
+
+ ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
+
+ ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum",
+ s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20);
+ }
+
+ // Other way around
+ s1.setRegion(region1_handle);
+ s2.setRegion(region1_handle);
+ s1.reset();
+ s2.reset();
+
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ // Want to test negative numbers here but have to work in U64
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0);
+
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ {
+ s1.merge(s2);
+
+ LLSD src = s2.asLLSD(false);
+ LLSD dst = s1.asLLSD(false);
+
+ ensure_equals("merge src has single region", src["regions"].size(), 1);
+ ensure_equals("merge dst has single region", dst["regions"].size(), 1);
+
+ // Remove time stamps, they're a problem
+ src.erase("duration");
+ src["regions"][0].erase("duration");
+ dst.erase("duration");
+ dst["regions"][0].erase("duration");
+
+ LLSD s2_llsd = get_region(dst, region1_handle);
+ ensure("Region1 is present in dst", s2_llsd.isMap());
+
+ ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
+
+ ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum (flipped)",
+ s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20);
+ }
+ }
+
+ // Minimum merges are interesting when one side contributes nothing
+ template<> template<>
+ void tst_viewerassetstats_index_object_t::test<12>()
+ {
+ LLViewerAssetStats s1;
+ LLViewerAssetStats s2;
+
+ s1.setRegion(region1_handle);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000);
+
+ s2.setRegion(region1_handle);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ {
+ s2.merge(s1);
+
+ LLSD src = s1.asLLSD(false);
+ LLSD dst = s2.asLLSD(false);
+
+ ensure_equals("merge src has single region", src["regions"].size(), 1);
+ ensure_equals("merge dst has single region", dst["regions"].size(), 1);
+
+ // Remove time stamps, they're a problem
+ src.erase("duration");
+ src["regions"][0].erase("duration");
+ dst.erase("duration");
+ dst["regions"][0].erase("duration");
+
+ LLSD s2_llsd = get_region(dst, region1_handle);
+ ensure("Region1 is present in dst", s2_llsd.isMap());
+
+ ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
+
+ ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum",
+ s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20);
+ }
+
+ // Other way around
+ s1.setRegion(region1_handle);
+ s2.setRegion(region1_handle);
+ s1.reset();
+ s2.reset();
+
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000);
+ s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000);
+
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+ s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true);
+
+ {
+ s1.merge(s2);
+
+ LLSD src = s2.asLLSD(false);
+ LLSD dst = s1.asLLSD(false);
+
+ ensure_equals("merge src has single region", src["regions"].size(), 1);
+ ensure_equals("merge dst has single region", dst["regions"].size(), 1);
+
+ // Remove time stamps, they're a problem
+ src.erase("duration");
+ src["regions"][0].erase("duration");
+ dst.erase("duration");
+ dst["regions"][0].erase("duration");
+
+ LLSD s2_llsd = get_region(dst, region1_handle);
+ ensure("Region1 is present in dst", s2_llsd.isMap());
+
+ ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3);
+
+ ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum (flipped)",
+ s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20);
+ }
+ }
+
+}
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/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp
index b976ac5ea9..acc6e814bc 100644
--- a/indra/newview/tests/llworldmap_test.cpp
+++ b/indra/newview/tests/llworldmap_test.cpp
@@ -25,13 +25,16 @@
* $/LicenseInfo$
*/
-// Precompiled header: almost always required for newview cpp files
-#include "../llviewerprecompiledheaders.h"
-// Class to test
-#include "../llworldmap.h"
// Dependencies
-#include "../llviewerimagelist.h"
+#include "linden_common.h"
+#include "llapr.h"
+#include "llsingleton.h"
+#include "lltrans.h"
+#include "lluistring.h"
+#include "../llviewertexture.h"
#include "../llworldmapmessage.h"
+// Class to test
+#include "../llworldmap.h"
// Tut header
#include "../test/lltut.h"
@@ -44,34 +47,29 @@
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
// Stub image calls
-LLViewerImageList::LLViewerImageList() { }
-LLViewerImageList::~LLViewerImageList() { }
-LLViewerImageList gImageList;
-LLViewerImage* LLViewerImageList::getImage(const LLUUID &image_id,
- BOOL usemipmaps,
- BOOL level_immediate,
- LLGLint internal_format,
- LLGLenum primary_format,
- LLHost request_from_host)
-{ return NULL; }
-void LLViewerImage::setBoostLevel(S32 level) { }
-void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) { }
+void LLViewerTexture::setBoostLevel(S32 ) { }
+void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode ) { }
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLUUID&, BOOL, LLViewerTexture::EBoostLevel, S8,
+ LLGLint, LLGLenum, LLHost ) { return NULL; }
// Stub related map calls
LLWorldMapMessage::LLWorldMapMessage() { }
LLWorldMapMessage::~LLWorldMapMessage() { }
void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle) { }
void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent) { }
+
LLWorldMipmap::LLWorldMipmap() { }
LLWorldMipmap::~LLWorldMipmap() { }
void LLWorldMipmap::reset() { }
void LLWorldMipmap::dropBoostLevels() { }
void LLWorldMipmap::equalizeBoostLevels() { }
-LLPointer<LLViewerImage> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load)
-{ return NULL; }
+LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) { return NULL; }
// Stub other stuff
-BOOL gPacificDaylightTime;
+std::string LLTrans::getString(const std::string &, const LLStringUtil::format_map_t& ) { return std::string("test_trans"); }
+void LLUIString::updateResult() const { }
+void LLUIString::setArg(const std::string& , const std::string& ) { }
+void LLUIString::assign(const std::string& ) { }
// End Stubbing
// -------------------------------------------------------------------------------------------
@@ -237,7 +235,7 @@ namespace tut
// Test 9 : setLandForSaleImage() / getLandForSaleImage()
LLUUID id;
mSim->setLandForSaleImage(id);
- LLPointer<LLViewerImage> image = mSim->getLandForSaleImage();
+ LLPointer<LLViewerFetchedTexture> image = mSim->getLandForSaleImage();
ensure("LLSimInfo::getLandForSaleImage() test failed", image.isNull());
// Test 10 : isPG()
mSim->setAccess(SIM_ACCESS_PG);
@@ -370,7 +368,7 @@ namespace tut
}
// Test 7 : getObjectsTile()
try {
- LLPointer<LLViewerImage> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1);
+ LLPointer<LLViewerFetchedTexture> image = mWorld->getObjectsTile((U32)(X_WORLD_TEST/REGION_WIDTH_METERS), (U32)(Y_WORLD_TEST/REGION_WIDTH_METERS), 1);
ensure("LLWorldMap::getObjectsTile() failed", image.isNull());
} catch (...) {
fail("LLWorldMap::getObjectsTile() test failed with exception");
diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp
index 54887ae219..4c0959d1a9 100644
--- a/indra/newview/tests/llworldmipmap_test.cpp
+++ b/indra/newview/tests/llworldmipmap_test.cpp
@@ -25,12 +25,12 @@
* $/LicenseInfo$
*/
-// Precompiled header: almost always required for newview cpp files
-#include "../llviewerprecompiledheaders.h"
+// Dependencies
+#include "linden_common.h"
+#include "../llviewertexture.h"
+#include "../llviewercontrol.h"
// Class to test
#include "../llworldmipmap.h"
-// Dependencies
-#include "../llviewerimagelist.h"
// Tut header
#include "../test/lltut.h"
@@ -42,19 +42,14 @@
// * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code)
// * A simulator for a class can be implemented here. Please comment and document thoroughly.
-LLViewerImageList::LLViewerImageList() { }
-LLViewerImageList::~LLViewerImageList() { }
-
-LLViewerImageList gImageList;
+void LLViewerTexture::setBoostLevel(S32 ) { }
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, BOOL, LLViewerTexture::EBoostLevel, S8,
+ LLGLint, LLGLenum, const LLUUID& ) { return NULL; }
-LLViewerImage* LLViewerImageList::getImageFromUrl(const std::string& url,
- BOOL usemipmaps,
- BOOL level_immediate,
- LLGLint internal_format,
- LLGLenum primary_format,
- const LLUUID& force_id)
-{ return NULL; }
-void LLViewerImage::setBoostLevel(S32 level) { }
+LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
+LLControlGroup::~LLControlGroup() { }
+std::string LLControlGroup::getString(const std::string& ) { return std::string("test_url"); }
+LLControlGroup gSavedSettings("test_settings");
// End Stubbing
// -------------------------------------------------------------------------------------------
diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py
index aeebb0cfd1..1c7204a6b6 100644
--- a/indra/newview/tests/test_llxmlrpc_peer.py
+++ b/indra/newview/tests/test_llxmlrpc_peer.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
"""\
@file test_llxmlrpc_peer.py
@author Nat Goodspeed
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 6861f02bfb..f0b1973fdf 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1,29 +1,31 @@
-#!/usr/bin/python
-# @file viewer_manifest.py
-# @author Ryan Williams
-# @brief Description of all installer viewer files, and methods for packaging
-# them into installers for all supported platforms.
-#
-# $LicenseInfo:firstyear=2006&license=viewerlgpl$
-# Second Life Viewer Source Code
-# Copyright (C) 2010, Linden Research, Inc.
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation;
-# version 2.1 of the License only.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
-# $/LicenseInfo$
+#!/usr/bin/env python
+"""\
+@file viewer_manifest.py
+@author Ryan Williams
+@brief Description of all installer viewer files, and methods for packaging
+ them into installers for all supported platforms.
+
+$LicenseInfo:firstyear=2006&license=viewerlgpl$
+Second Life Viewer Source Code
+Copyright (C) 2006-2011, Linden Research, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation;
+version 2.1 of the License only.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+$/LicenseInfo$
+"""
import sys
import os.path
import re
@@ -219,22 +221,25 @@ class WindowsManifest(ViewerManifest):
else:
print "Doesn't exist:", src
- def enable_crt_manifest_check(self):
- if self.is_packaging_viewer():
- WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
+ ### DISABLED MANIFEST CHECKING for vs2010. we may need to reenable this
+ # shortly. If this hasn't been reenabled by the 2.9 viewer release then it
+ # should be deleted -brad
+ #def enable_crt_manifest_check(self):
+ # if self.is_packaging_viewer():
+ # WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
- def enable_no_crt_manifest_check(self):
- if self.is_packaging_viewer():
- WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
+ #def enable_no_crt_manifest_check(self):
+ # if self.is_packaging_viewer():
+ # WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
- def disable_manifest_check(self):
- if self.is_packaging_viewer():
- del WindowsManifest.copy_action
+ #def disable_manifest_check(self):
+ # if self.is_packaging_viewer():
+ # del WindowsManifest.copy_action
def construct(self):
super(WindowsManifest, self).construct()
- self.enable_crt_manifest_check()
+ #self.enable_crt_manifest_check()
if self.is_packaging_viewer():
# Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
@@ -245,19 +250,15 @@ class WindowsManifest(ViewerManifest):
'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
"slplugin.exe")
- self.disable_manifest_check()
+ #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=""):
- self.enable_crt_manifest_check()
-
- # Get kdu dll, continue if missing.
- try:
- self.path('llkdu.dll', dst='llkdu.dll')
- except RuntimeError:
- print "Skipping llkdu.dll"
+ #self.enable_crt_manifest_check()
# Get llcommon and deps. If missing assume static linkage and continue.
try:
@@ -269,7 +270,7 @@ class WindowsManifest(ViewerManifest):
print err.message
print "Skipping llcommon.dll (assuming llcommon was linked statically)"
- self.disable_manifest_check()
+ #self.disable_manifest_check()
# Get fmod dll, continue if missing
try:
@@ -286,13 +287,11 @@ class WindowsManifest(ViewerManifest):
# These need to be installed as a SxS assembly, currently a 'private' assembly.
# See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
if self.args['configuration'].lower() == 'debug':
- self.path("msvcr80d.dll")
- self.path("msvcp80d.dll")
- self.path("Microsoft.VC80.DebugCRT.manifest")
+ self.path("msvcr100d.dll")
+ self.path("msvcp100d.dll")
else:
- self.path("msvcr80.dll")
- self.path("msvcp80.dll")
- self.path("Microsoft.VC80.CRT.manifest")
+ self.path("msvcr100.dll")
+ self.path("msvcp100.dll")
# Vivox runtimes
self.path("SLVoice.exe")
@@ -302,6 +301,10 @@ class WindowsManifest(ViewerManifest):
self.path("zlib1.dll")
self.path("vivoxplatform.dll")
self.path("vivoxoal.dll")
+
+ # Security
+ self.path("ssleay32.dll")
+ self.path("libeay32.dll")
# For google-perftools tcmalloc allocator.
try:
@@ -318,10 +321,7 @@ class WindowsManifest(ViewerManifest):
self.path("featuretable.txt")
self.path("featuretable_xp.txt")
- # For use in crash reporting (generates minidumps)
- self.path("dbghelp.dll")
-
- self.enable_no_crt_manifest_check()
+ #self.enable_no_crt_manifest_check()
# Media plugins - QuickTime
if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
@@ -334,13 +334,13 @@ class WindowsManifest(ViewerManifest):
self.end_prefix()
# winmm.dll shim
- if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst="llplugin"):
+ if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
self.path("winmm.dll")
self.end_prefix()
if self.args['configuration'].lower() == 'debug':
- if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'debug'),
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'debug'),
dst="llplugin"):
self.path("libeay32.dll")
self.path("qtcored4.dll")
@@ -371,7 +371,7 @@ class WindowsManifest(ViewerManifest):
self.end_prefix()
else:
- if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'),
+ if self.prefix(src=os.path.join(os.pardir, 'packages', 'lib', 'release'),
dst="llplugin"):
self.path("libeay32.dll")
self.path("qtcore4.dll")
@@ -402,7 +402,7 @@ class WindowsManifest(ViewerManifest):
self.end_prefix()
- self.disable_manifest_check()
+ #self.disable_manifest_check()
# pull in the crash logger and updater from other projects
# tag:"crash-logger" here as a cue to the exporter
@@ -570,7 +570,9 @@ class DarwinManifest(ViewerManifest):
self.path("Info-SecondLife.plist", dst="Info.plist")
# copy additional libs in <bundle>/Contents/MacOS/
- self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib")
+ self.path("../packages/lib/release/libndofdev.dylib", dst="Resources/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"):
@@ -610,41 +612,38 @@ class DarwinManifest(ViewerManifest):
self.path("uk.lproj")
self.path("zh-Hans.lproj")
- # SLVoice and vivox lols
- self.path("vivox-runtime/universal-darwin/libsndfile.dylib", "libsndfile.dylib")
- self.path("vivox-runtime/universal-darwin/libvivoxoal.dylib", "libvivoxoal.dylib")
- self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib")
- self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
- self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib")
- self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
-
- libdir = "../../libraries/universal-darwin/lib_release"
+ libdir = "../packages/lib/release"
dylibs = {}
- # need to get the kdu dll from any of the build directories as well
- for lib in "llkdu", "llcommon":
- libfile = "lib%s.dylib" % lib
- try:
- self.path(self.find_existing_file(os.path.join(os.pardir,
- lib,
- self.args['configuration'],
- libfile),
- os.path.join(libdir, libfile)),
- dst=libfile)
- except RuntimeError:
- print "Skipping %s" % libfile
- dylibs[lib] = False
- else:
- dylibs[lib] = True
+ # Need to get the llcommon dll from any of the build directories as well
+ lib = "llcommon"
+ libfile = "lib%s.dylib" % lib
+ try:
+ self.path(self.find_existing_file(os.path.join(os.pardir,
+ lib,
+ self.args['configuration'],
+ libfile),
+ os.path.join(libdir, libfile)),
+ dst=libfile)
+ except RuntimeError:
+ print "Skipping %s" % libfile
+ dylibs[lib] = False
+ else:
+ dylibs[lib] = True
if dylibs["llcommon"]:
- for libfile in ("libapr-1.0.3.7.dylib",
- "libaprutil-1.0.3.8.dylib",
- "libexpat.0.5.0.dylib",
+ for libfile in ("libapr-1.0.dylib",
+ "libaprutil-1.0.dylib",
+ "libexpat.1.5.2.dylib",
"libexception_handler.dylib",
):
self.path(os.path.join(libdir, libfile), libfile)
+ # SLVoice and vivox lols
+ for libfile in ('libsndfile.dylib', 'libvivoxoal.dylib', 'libortp.dylib', \
+ 'libvivoxsdk.dylib', 'libvivoxplatform.dylib', 'SLVoice') :
+ self.path(os.path.join(libdir, libfile), libfile)
+
try:
# FMOD for sound
self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib")
@@ -664,9 +663,9 @@ class DarwinManifest(ViewerManifest):
mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources")
slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources")
for libfile in ("libllcommon.dylib",
- "libapr-1.0.3.7.dylib",
- "libaprutil-1.0.3.8.dylib",
- "libexpat.0.5.0.dylib",
+ "libapr-1.0.dylib",
+ "libaprutil-1.0.dylib",
+ "libexpat.1.5.2.dylib",
"libexception_handler.dylib",
):
target_lib = os.path.join('../../..', libfile)
@@ -687,7 +686,7 @@ class DarwinManifest(ViewerManifest):
if self.prefix(src="", dst="llplugin"):
self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib")
self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib")
- self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib")
+ self.path("../packages/lib/release/libllqtwebkit.dylib", "libllqtwebkit.dylib")
self.end_prefix("llplugin")
@@ -707,6 +706,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 +747,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():
@@ -793,7 +802,7 @@ class DarwinManifest(ViewerManifest):
self.run_command('SetFile -a V %r' % pathname)
# Create the alias file (which is a resource file) from the .r
- self.run_command('rez %r -o %r' %
+ self.run_command('Rez %r -o %r' %
(self.src_path_of("installers/darwin/release-dmg/Applications-alias.r"),
os.path.join(volpath, "Applications")))
@@ -842,6 +851,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 +866,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 +887,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 +914,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(),
@@ -906,36 +926,36 @@ class Linux_i686Manifest(LinuxManifest):
def construct(self):
super(Linux_i686Manifest, self).construct()
- # install either the libllkdu we just built, or a prebuilt one, in
- # decreasing order of preference. for linux package, this goes to bin/
- try:
- self.path(self.find_existing_file('../llkdu/libllkdu.so',
- '../../libraries/i686-linux/lib_release_client/libllkdu.so'),
- dst='bin/libllkdu.so')
- except:
- print "Skipping libllkdu.so - not found"
-
- if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):
+ if self.prefix("../packages/lib/release", dst="lib"):
+ self.path("libapr-1.so")
self.path("libapr-1.so.0")
+ self.path("libapr-1.so.0.4.2")
+ self.path("libaprutil-1.so")
self.path("libaprutil-1.so.0")
- self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0")
- self.path("libdb-4.2.so")
- self.path("libcrypto.so.0.9.7")
- self.path("libexpat.so.1")
- self.path("libssl.so.0.9.7")
- self.path("libuuid.so.1")
- self.path("libSDL-1.2.so.0")
- self.path("libELFIO.so")
- self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3")
+ self.path("libaprutil-1.so.0.3.10")
+ self.path("libbreakpad_client.so.0.0.0")
+ self.path("libbreakpad_client.so.0")
+ self.path("libbreakpad_client.so")
+ self.path("libdb-5.1.so")
+ self.path("libdb-5.so")
+ self.path("libdb.so")
+ self.path("libcrypto.so.0.9.8")
+ self.path("libexpat.so.1.5.2")
+ self.path("libssl.so.0.9.8")
+ self.path("libuuid.so")
+ self.path("libuuid.so.16")
+ self.path("libuuid.so.16.0.22")
+ self.path("libSDL-1.2.so.0.11.3")
+ self.path("libdirectfb-1.4.so.5.0.4")
+ self.path("libfusion-1.4.so.5.0.4")
+ self.path("libdirect-1.4.so.5.0.4")
+ self.path("libopenjpeg.so.1.4.0")
+ self.path("libopenjpeg.so.1")
+ self.path("libopenjpeg.so")
self.path("libalut.so")
self.path("libopenal.so", "libopenal.so.1")
self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
- try:
- self.path("libkdu.so")
- pass
- except:
- print "Skipping libkdu.so - not found"
- pass
+ self.path("libfontconfig.so.1.4.4")
try:
self.path("libfmod-3.75.so")
pass
@@ -945,10 +965,10 @@ class Linux_i686Manifest(LinuxManifest):
self.end_prefix("lib")
# Vivox runtimes
- if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
+ if self.prefix(src="../packages/lib/release", dst="bin"):
self.path("SLVoice")
self.end_prefix()
- if self.prefix(src="vivox-runtime/i686-linux", dst="lib"):
+ if self.prefix(src="../packages/lib/release", dst="lib"):
self.path("libortp.so")
self.path("libsndfile.so.1")
#self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OpenAL lib