summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennetts <steve@lindenlab.com>2009-10-12 13:22:58 -0700
committerSteve Bennetts <steve@lindenlab.com>2009-10-12 13:22:58 -0700
commit4a1ef20c317897e7e509c7f599e97fcc90ffaefc (patch)
treec496bd8785b94bb60bca33ea59758c5929341451
parent895e8ad446ab383e1211f759e8b55aa0fff2efc1 (diff)
parentd4b2897700c66354413af42ab055bd1aaa47f91c (diff)
merge
-rw-r--r--.hgignore42
-rw-r--r--etc/message.xml11
-rw-r--r--indra/cmake/00-Common.cmake4
-rw-r--r--indra/cmake/GoogleMock.cmake27
-rw-r--r--indra/cmake/LLAddBuildTest.cmake11
-rw-r--r--indra/lib/python/indra/base/llsd.py2
-rw-r--r--indra/lib/python/indra/base/lluuid.py10
-rw-r--r--indra/lib/python/indra/util/llsubprocess.py11
-rw-r--r--indra/lib/python/indra/util/llversion.py39
-rw-r--r--indra/lib/python/indra/util/named_query.py4
-rw-r--r--indra/llcharacter/llkeyframestandmotion.cpp2
-rw-r--r--indra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/llassettype.cpp1
-rw-r--r--indra/llcommon/llassettype.h1
-rw-r--r--indra/llcommon/llcursortypes.cpp6
-rw-r--r--indra/llcommon/llcursortypes.h6
-rw-r--r--indra/llcommon/llfasttimer.h14
-rw-r--r--indra/llcommon/llkeythrottle.h57
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp12
-rw-r--r--indra/llcommon/llstat.cpp51
-rw-r--r--indra/llcommon/llstat.h21
-rw-r--r--indra/llcommon/llstringtable.h10
-rw-r--r--indra/llcommon/llversionserver.h4
-rw-r--r--indra/llcommon/llversionviewer.h2
-rw-r--r--indra/llcommon/metapropertyt.h13
-rw-r--r--indra/llimage/llimagej2c.cpp48
-rw-r--r--indra/llimage/llimagej2c.h4
-rw-r--r--indra/llinventory/llinventory.cpp33
-rw-r--r--indra/llinventory/llinventory.h5
-rw-r--r--indra/llinventory/llparcel.h6
-rw-r--r--indra/llinventory/llpermissions.cpp13
-rw-r--r--indra/llinventory/llpermissions.h4
-rw-r--r--indra/llinventory/lltransactiontypes.h12
-rw-r--r--indra/llmath/llquaternion.cpp6
-rw-r--r--indra/llmath/llquaternion.h34
-rw-r--r--indra/llmessage/CMakeLists.txt4
-rw-r--r--indra/llmessage/llcachename.h1
-rw-r--r--indra/llmessage/llcurl.cpp13
-rw-r--r--indra/llmessage/llcurl.h6
-rw-r--r--indra/llmessage/llhttpclient.cpp5
-rw-r--r--indra/llmessage/llhttpclientadapter.cpp2
-rw-r--r--indra/llmessage/llhttpclientadapter.h2
-rw-r--r--indra/llmessage/llhttpclientinterface.h2
-rw-r--r--indra/llmessage/lliohttpserver.cpp14
-rw-r--r--indra/llmessage/llmail.cpp18
-rw-r--r--indra/llmessage/llmessagesenderinterface.h2
-rw-r--r--indra/llmessage/llregionpresenceverifier.cpp88
-rw-r--r--indra/llmessage/llregionpresenceverifier.h39
-rw-r--r--indra/llmessage/llstoredmessage.cpp2
-rw-r--r--indra/llmessage/llstoredmessage.h2
-rw-r--r--indra/llmessage/llthrottle.cpp25
-rw-r--r--indra/llmessage/llthrottle.h2
-rw-r--r--indra/llmessage/lltransfersourceasset.cpp1
-rw-r--r--indra/llmessage/llurlrequest.cpp54
-rw-r--r--indra/llmessage/llurlrequest.h8
-rw-r--r--indra/llmessage/llxfermanager.cpp36
-rw-r--r--indra/llmessage/tests/llcurl_stub.cpp1
-rw-r--r--indra/llmessage/tests/llmockhttpclient.h61
-rw-r--r--indra/llmessage/tests/llregionpresenceverifier_test.cpp111
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp6
-rw-r--r--indra/llplugin/llpluginclassmedia.h1
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h3
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp59
-rw-r--r--indra/llplugin/llpluginprocessparent.h5
-rw-r--r--indra/llprimitive/llprimitive.cpp191
-rw-r--r--indra/llprimitive/llprimtexturelist.cpp19
-rw-r--r--indra/llprimitive/lltextureentry.cpp6
-rw-r--r--indra/llprimitive/lltextureentry.h4
-rw-r--r--indra/llui/lldockablefloater.cpp10
-rw-r--r--indra/llui/lldockablefloater.h3
-rw-r--r--indra/llui/lldockcontrol.cpp22
-rw-r--r--indra/llui/llfloater.cpp3
-rw-r--r--indra/llui/llfloater.h13
-rw-r--r--indra/llui/llmenubutton.cpp6
-rw-r--r--indra/llui/llmenubutton.h1
-rw-r--r--indra/llui/llpanel.cpp2
-rw-r--r--indra/llui/lltextbase.cpp3
-rw-r--r--indra/llui/lltooltip.cpp14
-rw-r--r--indra/llui/lluictrlfactory.h2
-rwxr-xr-xindra/llvfs/llpidlock.cpp2
-rw-r--r--indra/llwindow/llwindowmacosx.cpp12
-rw-r--r--indra/llwindow/llwindowsdl.cpp4
-rw-r--r--indra/llwindow/llwindowwin32.cpp4
-rw-r--r--indra/lscript/lscript_byteformat.h2
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.cpp12
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.h1
-rw-r--r--indra/lscript/lscript_execute.h3
-rw-r--r--indra/lscript/lscript_execute/lscript_execute.cpp122
-rw-r--r--indra/newview/CMakeLists.txt16
-rw-r--r--indra/newview/English.lproj/InfoPlist.strings4
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/app_settings/logcontrol.xml2
-rw-r--r--indra/newview/app_settings/settings.xml25
-rw-r--r--indra/newview/character/avatar_eye.llmbin0 -> 16011 bytes
-rw-r--r--indra/newview/character/avatar_eye_1.llmbin0 -> 5591 bytes
-rw-r--r--indra/newview/character/avatar_eyelashes.llmbin0 -> 65637 bytes
-rw-r--r--indra/newview/character/avatar_hair.llmbin0 -> 690581 bytes
-rw-r--r--indra/newview/character/avatar_hair_1.llmbin0 -> 5031 bytes
-rw-r--r--indra/newview/character/avatar_hair_2.llmbin0 -> 3261 bytes
-rw-r--r--indra/newview/character/avatar_hair_3.llmbin0 -> 1845 bytes
-rw-r--r--indra/newview/character/avatar_hair_4.llmbin0 -> 927 bytes
-rw-r--r--indra/newview/character/avatar_hair_5.llmbin0 -> 927 bytes
-rw-r--r--indra/newview/character/avatar_head.llmbin0 -> 1665493 bytes
-rw-r--r--indra/newview/character/avatar_head_1.llmbin0 -> 7875 bytes
-rw-r--r--indra/newview/character/avatar_head_2.llmbin0 -> 3675 bytes
-rw-r--r--indra/newview/character/avatar_head_3.llmbin0 -> 1797 bytes
-rw-r--r--indra/newview/character/avatar_head_4.llmbin0 -> 1239 bytes
-rw-r--r--indra/newview/character/avatar_lower_body.llmbin0 -> 337125 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_1.llmbin0 -> 7083 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_2.llmbin0 -> 4107 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_3.llmbin0 -> 2115 bytes
-rw-r--r--indra/newview/character/avatar_lower_body_4.llmbin0 -> 1629 bytes
-rw-r--r--indra/newview/character/avatar_skirt.llmbin0 -> 72497 bytes
-rw-r--r--indra/newview/character/avatar_skirt_1.llmbin0 -> 1899 bytes
-rw-r--r--indra/newview/character/avatar_skirt_2.llmbin0 -> 1551 bytes
-rw-r--r--indra/newview/character/avatar_skirt_3.llmbin0 -> 1191 bytes
-rw-r--r--indra/newview/character/avatar_skirt_4.llmbin0 -> 843 bytes
-rw-r--r--indra/newview/character/avatar_upper_body.llmbin0 -> 929297 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_1.llmbin0 -> 15627 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_2.llmbin0 -> 8991 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_3.llmbin0 -> 4557 bytes
-rw-r--r--indra/newview/character/avatar_upper_body_4.llmbin0 -> 3453 bytes
-rw-r--r--indra/newview/character/blush_alpha.tgabin0 -> 17352 bytes
-rw-r--r--indra/newview/character/body_skingrain.tgabin0 -> 262188 bytes
-rw-r--r--indra/newview/character/bodyfreckles_alpha.tgabin0 -> 257249 bytes
-rw-r--r--indra/newview/character/bump_face_wrinkles.tgabin0 -> 25243 bytes
-rw-r--r--indra/newview/character/bump_head_base.tgabin0 -> 105525 bytes
-rw-r--r--indra/newview/character/bump_lowerbody_base.tgabin0 -> 112782 bytes
-rw-r--r--indra/newview/character/bump_pants_wrinkles.tgabin0 -> 83183 bytes
-rw-r--r--indra/newview/character/bump_shirt_wrinkles.tgabin0 -> 81501 bytes
-rw-r--r--indra/newview/character/bump_upperbody_base.tgabin0 -> 147581 bytes
-rw-r--r--indra/newview/character/eyebrows_alpha.tgabin0 -> 9469 bytes
-rw-r--r--indra/newview/character/eyeliner_alpha.tgabin0 -> 4720 bytes
-rw-r--r--indra/newview/character/eyeshadow_inner_alpha.tgabin0 -> 5466 bytes
-rw-r--r--indra/newview/character/eyeshadow_outer_alpha.tgabin0 -> 7382 bytes
-rw-r--r--indra/newview/character/eyewhite.tgabin0 -> 42353 bytes
-rw-r--r--indra/newview/character/facehair_chincurtains_alpha.tgabin0 -> 34610 bytes
-rw-r--r--indra/newview/character/facehair_moustache_alpha.tgabin0 -> 14017 bytes
-rw-r--r--indra/newview/character/facehair_sideburns_alpha.tgabin0 -> 27328 bytes
-rw-r--r--indra/newview/character/facehair_soulpatch_alpha.tgabin0 -> 11277 bytes
-rw-r--r--indra/newview/character/freckles_alpha.tgabin0 -> 140558 bytes
-rw-r--r--indra/newview/character/glove_length_alpha.tgabin0 -> 49745 bytes
-rw-r--r--indra/newview/character/gloves_fingers_alpha.tgabin0 -> 39616 bytes
-rw-r--r--indra/newview/character/head_alpha.tgabin0 -> 6066 bytes
-rw-r--r--indra/newview/character/head_color.tgabin0 -> 70715 bytes
-rw-r--r--indra/newview/character/head_hair.tgabin0 -> 75600 bytes
-rw-r--r--indra/newview/character/head_highlights_alpha.tgabin0 -> 20503 bytes
-rw-r--r--indra/newview/character/head_shading_alpha.tgabin0 -> 35304 bytes
-rw-r--r--indra/newview/character/head_skingrain.tgabin0 -> 262376 bytes
-rw-r--r--indra/newview/character/jacket_length_lower_alpha.tgabin0 -> 9768 bytes
-rw-r--r--indra/newview/character/jacket_length_upper_alpha.tgabin0 -> 14617 bytes
-rw-r--r--indra/newview/character/jacket_open_lower_alpha.tgabin0 -> 19732 bytes
-rw-r--r--indra/newview/character/jacket_open_upper_alpha.tgabin0 -> 41606 bytes
-rw-r--r--indra/newview/character/lipgloss_alpha.tgabin0 -> 4738 bytes
-rw-r--r--indra/newview/character/lips_mask.tgabin0 -> 6110 bytes
-rw-r--r--indra/newview/character/lipstick_alpha.tgabin0 -> 7966 bytes
-rw-r--r--indra/newview/character/lowerbody_color.tgabin0 -> 135395 bytes
-rw-r--r--indra/newview/character/lowerbody_highlights_alpha.tgabin0 -> 8695 bytes
-rw-r--r--indra/newview/character/lowerbody_shading_alpha.tgabin0 -> 41766 bytes
-rw-r--r--indra/newview/character/nailpolish_alpha.tgabin0 -> 4656 bytes
-rw-r--r--indra/newview/character/pants_length_alpha.tgabin0 -> 26843 bytes
-rw-r--r--indra/newview/character/pants_waist_alpha.tgabin0 -> 10487 bytes
-rw-r--r--indra/newview/character/rosyface_alpha.tgabin0 -> 44382 bytes
-rw-r--r--indra/newview/character/rouge_alpha.tgabin0 -> 44382 bytes
-rw-r--r--indra/newview/character/shirt_bottom_alpha.tgabin0 -> 32242 bytes
-rw-r--r--indra/newview/character/shirt_collar_alpha.tgabin0 -> 14417 bytes
-rw-r--r--indra/newview/character/shirt_collar_back_alpha.tgabin0 -> 12789 bytes
-rw-r--r--indra/newview/character/shirt_sleeve_alpha.tgabin0 -> 72196 bytes
-rw-r--r--indra/newview/character/shoe_height_alpha.tgabin0 -> 24461 bytes
-rw-r--r--indra/newview/character/skirt_length_alpha.tgabin0 -> 4114 bytes
-rw-r--r--indra/newview/character/skirt_slit_back_alpha.tgabin0 -> 90350 bytes
-rw-r--r--indra/newview/character/skirt_slit_front_alpha.tgabin0 -> 90350 bytes
-rw-r--r--indra/newview/character/skirt_slit_left_alpha.tgabin0 -> 82006 bytes
-rw-r--r--indra/newview/character/skirt_slit_right_alpha.tgabin0 -> 91410 bytes
-rw-r--r--indra/newview/character/underpants_trial_female.tgabin0 -> 48063 bytes
-rw-r--r--indra/newview/character/underpants_trial_male.tgabin0 -> 144983 bytes
-rw-r--r--indra/newview/character/undershirt_trial_female.tgabin0 -> 81390 bytes
-rw-r--r--indra/newview/character/upperbody_color.tgabin0 -> 23348 bytes
-rw-r--r--indra/newview/character/upperbody_highlights_alpha.tgabin0 -> 6509 bytes
-rw-r--r--indra/newview/character/upperbody_shading_alpha.tgabin0 -> 25297 bytes
-rw-r--r--indra/newview/character/upperbodyfreckles_alpha.tgabin0 -> 180104 bytes
-rw-r--r--indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tifbin14776 -> 0 bytes
-rw-r--r--indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tifbin15144 -> 0 bytes
-rw-r--r--indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tifbin15176 -> 0 bytes
-rw-r--r--indra/newview/llavataractions.cpp4
-rw-r--r--indra/newview/llexpandabletextbox.cpp37
-rw-r--r--indra/newview/llexpandabletextbox.h15
-rw-r--r--indra/newview/llfloateravatarpicker.cpp60
-rw-r--r--indra/newview/llfloateravatarpicker.h6
-rw-r--r--indra/newview/llfloaterbuy.cpp5
-rw-r--r--indra/newview/llfloaterbuy.h2
-rw-r--r--indra/newview/llfloaterhelpbrowser.cpp7
-rw-r--r--indra/newview/llfloaterhelpbrowser.h2
-rw-r--r--indra/newview/llfloatermediabrowser.cpp2
-rw-r--r--indra/newview/llfloatermediasettings.cpp29
-rw-r--r--indra/newview/llfloatermediasettings.h14
-rw-r--r--indra/newview/llfloateropenobject.h1
-rw-r--r--indra/newview/llfloaterpay.cpp573
-rw-r--r--indra/newview/llfloaterpay.h61
-rw-r--r--indra/newview/llfloaterpreference.cpp5
-rw-r--r--indra/newview/llfloaterpreference.h10
-rw-r--r--indra/newview/llfloatersellland.cpp5
-rw-r--r--indra/newview/llfloatertools.cpp378
-rw-r--r--indra/newview/llfloatertools.h5
-rw-r--r--indra/newview/llfloateruipreview.cpp6
-rw-r--r--indra/newview/llfloateruipreview.h7
-rw-r--r--indra/newview/llfloatervoicedevicesettings.cpp7
-rw-r--r--indra/newview/llfloatervoicedevicesettings.h7
-rw-r--r--indra/newview/llfloaterworldmap.cpp5
-rw-r--r--indra/newview/llfloaterworldmap.h5
-rw-r--r--indra/newview/llimfloater.cpp5
-rw-r--r--indra/newview/llimfloater.h5
-rw-r--r--indra/newview/llimpanel.cpp5
-rw-r--r--indra/newview/llimpanel.h2
-rw-r--r--indra/newview/llinspectavatar.cpp10
-rw-r--r--indra/newview/llinspectobject.cpp10
-rw-r--r--indra/newview/llmediactrl.cpp10
-rw-r--r--indra/newview/llmediadataclient.cpp624
-rw-r--r--indra/newview/llmediadataclient.h309
-rw-r--r--indra/newview/llnearbychat.h6
-rw-r--r--indra/newview/llpanelavatar.h4
-rw-r--r--indra/newview/llpanelface.cpp4
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.cpp109
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.h12
-rw-r--r--indra/newview/llpanelmediasettingspermissions.cpp45
-rw-r--r--indra/newview/llpanelmediasettingspermissions.h4
-rw-r--r--indra/newview/llpanelmediasettingssecurity.cpp30
-rw-r--r--indra/newview/llpanelmediasettingssecurity.h4
-rw-r--r--indra/newview/llpanelpicks.cpp3
-rw-r--r--indra/newview/llpanelpicks.h2
-rw-r--r--indra/newview/llpanelplaceinfo.cpp199
-rw-r--r--indra/newview/llpanelplaceinfo.h15
-rw-r--r--indra/newview/llpanelplaces.cpp437
-rw-r--r--indra/newview/llpanelplaces.h25
-rw-r--r--indra/newview/llpanelprofile.cpp2
-rw-r--r--indra/newview/llpreviewanim.cpp5
-rw-r--r--indra/newview/llpreviewanim.h2
-rw-r--r--indra/newview/llpreviewgesture.cpp8
-rw-r--r--indra/newview/llpreviewgesture.h4
-rw-r--r--indra/newview/llselectmgr.h52
-rw-r--r--indra/newview/llsyswellwindow.cpp4
-rw-r--r--indra/newview/llsyswellwindow.h2
-rw-r--r--indra/newview/lltexturectrl.cpp14
-rw-r--r--indra/newview/lltoastalertpanel.cpp1
-rw-r--r--indra/newview/lltoolpie.cpp26
-rw-r--r--indra/newview/llviewerfloaterreg.cpp5
-rw-r--r--indra/newview/llviewermedia.cpp57
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermediafocus.cpp6
-rw-r--r--indra/newview/llviewermenu.cpp21
-rw-r--r--indra/newview/llviewermessage.cpp17
-rw-r--r--indra/newview/llviewerobject.cpp1
-rw-r--r--indra/newview/llviewerparcelmedia.cpp12
-rw-r--r--indra/newview/llvoiceclient.cpp3
-rw-r--r--indra/newview/llvovolume.cpp217
-rw-r--r--indra/newview/llvovolume.h21
-rw-r--r--indra/newview/res/toolbuy.curbin2238 -> 0 bytes
-rw-r--r--indra/newview/res/toolopen.curbin2238 -> 0 bytes
-rw-r--r--indra/newview/res/toolsit.curbin2238 -> 0 bytes
-rw-r--r--indra/newview/res/viewerRes.rc14
-rw-r--r--indra/newview/skins/default/textures/textures.xml17
-rw-r--r--indra/newview/skins/default/xui/da/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/da/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/de/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_picker.xml40
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_whitelist_entry.xml48
-rw-r--r--indra/newview/skins/default/xui/en/inspect_avatar.xml159
-rw-r--r--indra/newview/skins/default/xui/en/inspect_object.xml89
-rw-r--r--indra/newview/skins/default/xui/en/language_settings.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml54
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_general.xml99
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml156
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml52
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml823
-rw-r--r--indra/newview/skins/default/xui/en/widgets/combo_box.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/expandable_text.xml1
-rw-r--r--indra/newview/skins/default/xui/en/widgets/scroll_list.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/text.xml3
-rw-r--r--indra/newview/skins/default/xui/es/floater_camera.xml20
-rw-r--r--indra/newview/skins/default/xui/es/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/fr/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/it/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/nl/floater_camera.xml18
-rw-r--r--indra/newview/skins/default/xui/nl/floater_color_picker.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_camera.xml18
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_camera.xml20
-rw-r--r--indra/newview/skins/default/xui/pt/floater_color_picker.xml2
-rw-r--r--indra/newview/tests/llmediadataclient_test.cpp481
-rwxr-xr-xindra/newview/viewer_manifest.py8
-rw-r--r--indra/test/CMakeLists.txt17
-rw-r--r--indra/test/test.cpp10
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.cpp4
-rw-r--r--install.xml47
-rwxr-xr-xscripts/install.py10
-rw-r--r--scripts/messages/message_template.msg4
-rwxr-xr-xscripts/update_version_files.py26
304 files changed, 5857 insertions, 1737 deletions
diff --git a/.hgignore b/.hgignore
new file mode 100644
index 0000000000..28c78eb994
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,42 @@
+syntax: glob
+
+*.pyc
+*~
+.*.swp
+LICENSES
+indra/.distcc
+indra/build-darwin-*
+indra/build-vc[0-9]*
+indra/lib/mono/1.0/*.dll
+indra/lib/mono/indra/*.dll
+indra/lib/mono/indra/*.exe
+indra/lib/mono/indra/*.pdb
+indra/llwindow/glh/glh_linear.h
+indra/newview/app_settings/mozilla
+indra/newview/app_settings/mozilla-runtime-*
+indra/newview/app_settings/mozilla_debug
+indra/newview/app_settings/static_*.db2
+indra/newview/character
+indra/newview/fmod.dll
+indra/newview/mozilla-theme
+indra/newview/mozilla-universal-darwin.tgz
+indra/newview/res-sdl
+indra/newview/skins
+indra/newview/vivox-runtime
+indra/server-linux-*
+indra/test/linden_file.dat
+indra/test_apps/llmediatest/dependencies/i686-win32
+indra/test_apps/terrain_mule/*.dll
+indra/viewer-linux-*
+indra/web/doc/asset-upload/plugins/lsl_compiler/lslc
+indra/web/doc/asset-upload/plugins/verify-notecard
+indra/web/doc/asset-upload/plugins/verify-texture
+installed.xml
+libraries
+tarfile_tmp
+^web/locale.*
+^web/secondlife.com.*
+^web/config.*
+^indra/web/dataservice/locale.*
+^indra/web/dataservice/lib/shared/vault.*
+^indra/web/dataservice/vendor.*
diff --git a/etc/message.xml b/etc/message.xml
index d2ba9843e4..da08e12aa1 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -669,11 +669,14 @@
<key>FetchLib</key>
<boolean>true</boolean>
- <key>ObjectMedia</key>
- <boolean>false</boolean>
+ <key>UploadBakedTexture</key>
+ <boolean>true</boolean>
+
+ <key>ObjectMedia</key>
+ <boolean>false</boolean>
- <key>ObjectMediaNavigate</key>
- <boolean>false</boolean>
+ <key>ObjectMediaNavigate</key>
+ <boolean>false</boolean>
</map>
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 2a70263446..c356feb13a 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -192,13 +192,13 @@ endif (DARWIN)
if (LINUX OR DARWIN)
- set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor -Woverloaded-virtual")
+ set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
if (NOT GCC_DISABLE_FATAL_WARNINGS)
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
endif (NOT GCC_DISABLE_FATAL_WARNINGS)
- set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder")
+ set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake
new file mode 100644
index 0000000000..ca5a8034ba
--- /dev/null
+++ b/indra/cmake/GoogleMock.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Prebuilt)
+include(Linking)
+
+use_prebuilt_binary(googlemock)
+
+set(GOOGLEMOCK_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/include)
+
+if (LINUX)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock
+ gtest)
+elseif(WINDOWS)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock)
+ set(GOOGLEMOCK_INCLUDE_DIRS
+ ${LIBS_PREBUILT_DIR}/include
+ ${LIBS_PREBUILT_DIR}/include/gmock
+ ${LIBS_PREBUILT_DIR}/include/gmock/boost/tr1/tr1)
+elseif(DARWIN)
+ set(GOOGLEMOCK_LIBRARIES
+ gmock
+ gtest)
+endif(LINUX)
+
+
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 7d6ef9ab1a..373ad4d4e9 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -13,6 +13,8 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
#
# WARNING: do NOT modify this code without working with poppy or daveh -
# there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
+
IF(LL_TEST_VERBOSE)
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
@@ -32,8 +34,10 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
${LLMATH_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LIBS_OPEN_DIR}/test
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
SET(alltest_LIBRARIES
+ ${GOOGLEMOCK_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
)
@@ -42,6 +46,11 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
${CMAKE_SOURCE_DIR}/test/test.h
)
+ # Use the default flags
+ if (LINUX)
+ SET(CMAKE_EXE_LINKER_FLAGS "")
+ endif (LINUX)
+
# start the source test executable definitions
SET(${project}_TEST_OUTPUT "")
FOREACH (source ${sources})
@@ -84,9 +93,9 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
ENDIF(LL_TEST_VERBOSE)
+
# Setup target
ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
-
#
# Per-codefile additional / external project dep and lib dep property extraction
#
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 1190d88663..4527b115f9 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -238,7 +238,7 @@ class LLSDXMLFormatter(object):
def MAP(self, v):
return self.elt(
'map',
- ''.join(["%s%s" % (self.elt('key', key), self.generate(value))
+ ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
for key, value in v.items()]))
typeof = type
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
index aceea29cd2..1cdd8e915b 100644
--- a/indra/lib/python/indra/base/lluuid.py
+++ b/indra/lib/python/indra/base/lluuid.py
@@ -26,8 +26,14 @@ THE SOFTWARE.
$/LicenseInfo$
"""
-import md5, random, socket, string, time, re
+import random, socket, string, time, re
import uuid
+try:
+ # Python 2.6
+ from hashlib import md5
+except ImportError:
+ # Python 2.5 and earlier
+ from md5 import new as md5
def _int2binstr(i,l):
s=''
@@ -196,7 +202,7 @@ class UUID(object):
from c++ implementation for portability reasons.
Returns self.
"""
- m = md5.new()
+ m = md5()
m.update(uuid.uuid1().bytes)
self._bits = m.digest()
return self
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
index c4c40739ec..7e0e115d14 100644
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ b/indra/lib/python/indra/util/llsubprocess.py
@@ -90,6 +90,17 @@ all the output, and get the result.
child.tochild.close()
result = child.poll()
if result != -1:
+ # At this point, the child process has exited and result
+ # is the return value from the process. Between the time
+ # we called select() and poll() the process may have
+ # exited so read all the data left on the child process
+ # stdout and stderr.
+ last = child.fromchild.read()
+ if last:
+ out.append(last)
+ last = child.childerr.read()
+ if last:
+ err.append(last)
child.tochild.close()
child.fromchild.close()
child.childerr.close()
diff --git a/indra/lib/python/indra/util/llversion.py b/indra/lib/python/indra/util/llversion.py
index 770b861ddc..2718a85f41 100644
--- a/indra/lib/python/indra/util/llversion.py
+++ b/indra/lib/python/indra/util/llversion.py
@@ -1,7 +1,7 @@
"""@file llversion.py
@brief Utility for parsing llcommon/llversion${server}.h
for the version string and channel string
- Utility that parses svn info for branch and revision
+ Utility that parses hg or svn info for branch and revision
$LicenseInfo:firstyear=2006&license=mit$
@@ -79,8 +79,8 @@ def get_svn_status_matching(regular_expression):
status, output = commands.getstatusoutput('svn info %s' % get_src_root())
m = regular_expression.search(output)
if not m:
- print "Failed to parse svn info output, resultfollows:"
- print output
+ print >> sys.stderr, "Failed to parse svn info output, result follows:"
+ print >> sys.stderr, output
raise Exception, "No matching svn status in "+src_root
return m.group(1)
@@ -92,4 +92,35 @@ def get_svn_revision():
last_rev_re = re.compile('Last Changed Rev: (\d+)')
return get_svn_status_matching(last_rev_re)
-
+def get_hg_repo():
+ status, output = commands.getstatusoutput('hg showconfig paths.default')
+ if status:
+ print >> sys.stderr, output
+ sys.exit(1)
+ if not output:
+ print >> sys.stderr, 'ERROR: cannot find repo we cloned from'
+ sys.exit(1)
+ return output
+
+def get_hg_changeset():
+ # The right thing to do:
+ # status, output = commands.getstatusoutput('hg id -i')
+ # if status:
+ # print >> sys.stderr, output
+ # sys.exit(1)
+
+ # The temporary hack:
+ status, output = commands.getstatusoutput('hg parents --template "{rev}"')
+ if status:
+ print >> sys.stderr, output
+ sys.exit(1)
+ lines = output.splitlines()
+ if len(lines) > 1:
+ print >> sys.stderr, 'ERROR: working directory has %d parents' % len(lines)
+ return lines[0]
+
+def using_svn():
+ return os.path.isdir(os.path.join(get_src_root(), '.svn'))
+
+def using_hg():
+ return os.path.isdir(os.path.join(get_src_root(), '.hg'))
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
index 693b483f79..5c19368240 100644
--- a/indra/lib/python/indra/util/named_query.py
+++ b/indra/lib/python/indra/util/named_query.py
@@ -48,8 +48,8 @@ from indra.base import llsd
from indra.base import config
DEBUG = False
-NQ_FILE_SUFFIX = None
-NQ_FILE_SUFFIX_LEN = None
+NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
+NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
_g_named_manager = None
diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp
index 1d42298f4d..1ae0ddeea0 100644
--- a/indra/llcharacter/llkeyframestandmotion.cpp
+++ b/indra/llcharacter/llkeyframestandmotion.cpp
@@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
{
mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
- mLastGoodPelvisRotation.normQuat();
+ mLastGoodPelvisRotation.normalize();
mTrackAnkles = TRUE;
}
else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index bc4e44d7e6..138dc85459 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -240,7 +240,7 @@ SET(llcommon_TEST_SOURCE_FILES
LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on)
-set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
# Have to treat lllazy test as an integration test until this issue is resolved:
# https://jira.lindenlab.com/jira/browse/DEV-29456
LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}")
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 5d7672b378..78aa6f4f37 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -289,6 +289,7 @@ bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type)
asset_type <= AT_FOLDER_ENSEMBLE_END);
}
+
// static. Generate a good default description
void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
std::string& description)
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 5e51188541..880b7a19b5 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -150,6 +150,7 @@ public:
AT_COUNT = 49,
+
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
// +*********************************************************+
diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp
index 7444115aa1..23ede97af3 100644
--- a/indra/llcommon/llcursortypes.cpp
+++ b/indra/llcommon/llcursortypes.cpp
@@ -30,6 +30,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llcursortypes.h"
ECursorType getCursorFromString(const std::string& cursor_string)
@@ -66,10 +68,6 @@ ECursorType getCursorFromString(const std::string& cursor_string)
cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
- cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT;
- cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY;
- cursor_string_table["UI_CURSOR_TOOLPAY"] = UI_CURSOR_TOOLPAY;
- cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN;
cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;
cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN;
diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h
index bea70351b7..35dbeaf16e 100644
--- a/indra/llcommon/llcursortypes.h
+++ b/indra/llcommon/llcursortypes.h
@@ -33,8 +33,6 @@
#ifndef LL_LLCURSORTYPES_H
#define LL_LLCURSORTYPES_H
-#include "linden_common.h"
-
// If you add types here, add them in LLCursor::getCursorFromString
enum ECursorType {
UI_CURSOR_ARROW,
@@ -66,10 +64,6 @@ enum ECursorType {
UI_CURSOR_TOOLPAN,
UI_CURSOR_TOOLZOOMIN,
UI_CURSOR_TOOLPICKOBJECT3,
- UI_CURSOR_TOOLSIT,
- UI_CURSOR_TOOLBUY,
- UI_CURSOR_TOOLPAY,
- UI_CURSOR_TOOLOPEN,
UI_CURSOR_TOOLPLAY,
UI_CURSOR_TOOLPAUSE,
UI_CURSOR_TOOLMEDIAOPEN,
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 0d89353dee..c2f23f6ff6 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -114,8 +114,9 @@ public:
// recursive call to gather total time from children
static void accumulateTimings();
- // called once per frame by LLFastTimer
- static void processFrame();
+ // updates cumulative times and hierarchy,
+ // can be called multiple times in a frame, at any point
+ static void processTimes();
static void buildHierarchy();
static void resetFrame();
@@ -178,8 +179,9 @@ public:
{
#if FAST_TIMER_ON
NamedTimer::FrameState* frame_state = mFrameState;
- frame_state->mLastStartTime = get_cpu_clock_count();
- mStartSelfTime = frame_state->mLastStartTime;
+ U64 cur_time = get_cpu_clock_count();
+ frame_state->mLastStartTime = cur_time;
+ mStartSelfTime = cur_time;
frame_state->mActiveCount++;
frame_state->mCalls++;
@@ -215,6 +217,10 @@ public:
// call this once a frame to reset timers
static void nextFrame();
+ // dumps current cumulative frame stats to log
+ // call nextFrame() to reset timers
+ static void dumpCurTimes();
+
// call this to reset timer hierarchy, averages, etc.
static void reset();
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 873f50a65e..7544ab1d11 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -118,6 +118,63 @@ public:
THROTTLE_BLOCKED, // rate exceed, block key
};
+ F64 getActionCount(const T& id)
+ {
+ U64 now = 0;
+ if ( mIsRealtime )
+ {
+ now = LLKeyThrottleImpl<T>::getTime();
+ }
+ else
+ {
+ now = LLKeyThrottleImpl<T>::getFrame();
+ }
+
+ if (now >= (m.startTime + m.intervalLength))
+ {
+ if (now < (m.startTime + 2 * m.intervalLength))
+ {
+ // prune old data
+ delete m.prevMap;
+ m.prevMap = m.currMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime += m.intervalLength;
+ }
+ else
+ {
+ // lots of time has passed, all data is stale
+ delete m.prevMap;
+ delete m.currMap;
+ m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+ m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+ m.startTime = now;
+ }
+ }
+
+ U32 prevCount = 0;
+
+ typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+ if (prev != m.prevMap->end())
+ {
+ prevCount = prev->second.count;
+ }
+
+ typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+ // curr.count is the number of keys in
+ // this current 'time slice' from the beginning of it until now
+ // prevCount is the number of keys in the previous
+ // time slice scaled to be one full time slice back from the current
+ // (now) time.
+
+ // compute current, windowed rate
+ F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+ F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+ return averageCount;
+ }
+
// call each time the key wants use
State noteAction(const T& id, S32 weight = 1)
{
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index c12ca350de..7e1c2e35e0 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -37,6 +37,7 @@
#include <deque>
#include "apr_base64.h"
+#include <boost/regex.hpp>
extern "C"
{
@@ -777,10 +778,17 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
case ELEMENT_BINARY:
{
- S32 len = apr_base64_decode_len(mCurrentContent.c_str());
+ // Regex is expensive, but only fix for whitespace in base64,
+ // created by python and other non-linden systems - DEV-39358
+ // Fortunately we have very little binary passing now,
+ // so performance impact shold be negligible. + poppy 2009-09-04
+ boost::regex r;
+ r.assign("\\s");
+ std::string stripped = boost::regex_replace(mCurrentContent, r, "");
+ S32 len = apr_base64_decode_len(stripped.c_str());
std::vector<U8> data;
data.resize(len);
- len = apr_base64_decode_binary(&data[0], mCurrentContent.c_str());
+ len = apr_base64_decode_binary(&data[0], stripped.c_str());
data.resize(len);
value = data;
break;
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 90dae11793..0bd2609f4a 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,7 +43,7 @@
// statics
-BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information
+S32 LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS; // Control what is being recorded
LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects
std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step"
LLStat::stat_map_t LLStat::sStatList;
@@ -130,6 +130,7 @@ bool LLStatsConfigFile::loadFile()
F32 duration = 0.f;
F32 interval = 0.f;
+ S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
const char * w = "duration";
if (stats_config.has(w))
@@ -141,8 +142,18 @@ bool LLStatsConfigFile::loadFile()
{
interval = (F32)stats_config[w].asReal();
}
+ w = "flags";
+ if (stats_config.has(w))
+ {
+ flags = (S32)stats_config[w].asInteger();
+ if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
+ duration > 0)
+ { // No flags passed in, but have a duration, so reset to basic stats
+ flags = LLPerfBlock::LLSTATS_BASIC_STATS;
+ }
+ }
- mStatsp->setReportPerformanceDuration( duration );
+ mStatsp->setReportPerformanceDuration( duration, flags );
mStatsp->setReportPerformanceInterval( interval );
if ( duration > 0 )
@@ -254,13 +265,14 @@ void LLPerfStats::dumpIntervalPerformanceStats()
}
}
-// Set length of performance stat recording
-void LLPerfStats::setReportPerformanceDuration( F32 seconds )
+// Set length of performance stat recording.
+// If turning stats on, caller must provide flags
+void LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
{
if ( seconds <= 0.f )
{
mReportPerformanceStatEnd = 0.0;
- LLPerfBlock::setStatsEnabled( FALSE );
+ LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS); // Make sure all recording is off
mFrameStatsFile.close();
LLPerfBlock::clearDynamicStats();
}
@@ -269,8 +281,8 @@ void LLPerfStats::setReportPerformanceDuration( F32 seconds )
mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
// Clear failure flag to try and create the log file once
mFrameStatsFileFailure = FALSE;
- LLPerfBlock::setStatsEnabled( TRUE );
mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame)
+ LLPerfBlock::setStatsFlags(flags);
}
}
@@ -612,11 +624,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta
}
}
-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
-// These are also turned on or off via the switch passed in
-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+// Use this constructor for normal, optional LLPerfBlock time slices
+LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
{
- if (!sStatsEnabled) return;
+ if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
+ { // These are off unless the base set is enabled
+ return;
+ }
+
+ initDynamicStat(key);
+}
+
+
+// Use this constructor for dynamically created LLPerfBlock time slices
+// that are only enabled by specific control flags
+LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+{
+ if ((sStatsFlags & flags) == 0)
+ {
+ return;
+ }
if (NULL == key2 || strlen(key2) == 0)
{
@@ -630,10 +657,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat
}
}
+// Set up the result data map if dynamic stats are enabled
void LLPerfBlock::initDynamicStat(const std::string& key)
{
// Early exit if dynamic stats aren't enabled.
- if (!sStatsEnabled) return;
+ if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS)
+ return;
mLastPath = sCurrentStatPath; // Save and restore current path
sCurrentStatPath += "/" + key; // Add key to current path
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index bad18f46a0..76aa3963f4 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -192,14 +192,23 @@ public:
// Use this constructor for pre-defined LLStatTime objects
LLPerfBlock(LLStatTime* stat);
- // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
- LLPerfBlock( const char* key1, const char* key2 = NULL);
+ // Use this constructor for normal, optional LLPerfBlock time slices
+ LLPerfBlock( const char* key );
+ // Use this constructor for dynamically created LLPerfBlock time slices
+ // that are only enabled by specific control flags
+ LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
~LLPerfBlock();
- static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; };
- static S32 getStatsEnabled() { return sStatsEnabled; };
+ enum
+ { // Stats bitfield flags
+ LLSTATS_NO_OPTIONAL_STATS = 0x00, // No optional stats gathering, just pre-defined LLStatTime objects
+ LLSTATS_BASIC_STATS = 0x01, // Gather basic optional runtime stats
+ LLSTATS_SCRIPT_FUNCTIONS = 0x02, // Include LSL function calls
+ };
+ static void setStatsFlags( S32 flags ) { sStatsFlags = flags; };
+ static S32 getStatsFlags() { return sStatsFlags; };
static void clearDynamicStats(); // Reset maps to clear out dynamic objects
static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin
@@ -213,7 +222,7 @@ private:
LLStatTime * mPredefinedStat; // LLStatTime object to get data
StatEntry * mDynamicStat; // StatEntryobject to get data
- static BOOL sStatsEnabled; // Normally FALSE
+ static S32 sStatsFlags; // Control what is being recorded
static stat_map_t sStatMap; // Map full path string to LLStatTime objects
static std::string sCurrentStatPath; // Something like "frame/physics/physics step"
};
@@ -236,7 +245,7 @@ public:
BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); };
F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; };
void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; };
- void setReportPerformanceDuration( F32 seconds );
+ void setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
void setProcessName(const std::string& process_name) { mProcessName = process_name; }
void setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 888361b0b9..5c4831cc2b 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -48,10 +48,12 @@
//# define STRING_TABLE_HASH_MAP 1
#endif
-#if LL_WINDOWS
-#include <hash_map>
-#else
-#include <ext/hash_map>
+#if STRING_TABLE_HASH_MAP
+# if LL_WINDOWS
+# include <hash_map>
+# else
+# include <ext/hash_map>
+# endif
#endif
const U32 MAX_STRINGS_LENGTH = 256;
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index 23e39ceb08..77a03879bf 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -34,9 +34,9 @@
#define LL_LLVERSIONSERVER_H
const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 29;
+const S32 LL_VERSION_MINOR = 31;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 2639;
const char * const LL_CHANNEL = "Second Life Server";
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 2c3e9c7333..e69ca7eec5 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -36,7 +36,7 @@
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 0;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 2639;
const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
index 79a536a224..5ad230d1d5 100644
--- a/indra/llcommon/metapropertyt.h
+++ b/indra/llcommon/metapropertyt.h
@@ -94,6 +94,13 @@ inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* obje
}
template <>
+inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
+{
+ checkObjectClass(object);
+ return NULL;
+}
+
+template <>
inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
{
return *(getProperty(object));
@@ -111,6 +118,12 @@ inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
return *(getProperty(object));
}
+template <>
+inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
+{
+ return *(getProperty(object));
+}
+
template<class TObject, class TProperty>
class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
{
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 363486fb9c..2352c8edd7 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -178,8 +178,8 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
mMaxBytes(0),
mRawDiscardLevel(-1),
mRate(0.0f),
- mReversible(FALSE)
-
+ mReversible(FALSE),
+ mAreaUsedForDataSizeCalcs(0)
{
//We assume here that if we wanted to create via
//a dynamic library that the approriate open calls were made
@@ -195,6 +195,12 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
}
mImpl = j2cimpl_create_func();
+
+ // Clear data size table
+ for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
+ { // Array size is MAX_DISCARD_LEVEL+1
+ mDataSizes[i] = 0;
+ }
}
// virtual
@@ -367,9 +373,45 @@ S32 LLImageJ2C::calcHeaderSize()
return calcHeaderSizeJ2C();
}
+
+// calcDataSize() returns how many bytes to read
+// to load discard_level (including header and higher discard levels)
S32 LLImageJ2C::calcDataSize(S32 discard_level)
{
- return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
+ discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
+
+ if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth())
+ || mDataSizes[0] == 0)
+ {
+ mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
+
+ S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
+ while ( level >= 0 )
+ {
+ mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+ level--;
+ }
+
+ /* This is technically a more correct way to calculate the size required
+ for each discard level, since they should include the size needed for
+ lower levels. Unfortunately, this doesn't work well and will lead to
+ download stalls. The true correct way is to parse the header. This will
+ all go away with http textures at some point.
+
+ // Calculate the size for each discard level. Lower levels (higher quality)
+ // contain the cumulative size of higher levels
+ S32 total_size = calcHeaderSizeJ2C();
+
+ S32 level = MAX_DISCARD_LEVEL; // Start at the highest discard
+ while ( level >= 0 )
+ { // Add in this discard level and all before it
+ total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+ mDataSizes[level] = total_size;
+ level--;
+ }
+ */
+ }
+ return mDataSizes[discard_level];
}
S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 23f6ef5fd1..55df7f4429 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -87,6 +87,10 @@ protected:
void updateRawDiscardLevel();
S32 mMaxBytes; // Maximum number of bytes of data to use...
+
+ S32 mDataSizes[MAX_DISCARD_LEVEL+1]; // Size of data required to reach a given level
+ U32 mAreaUsedForDataSizeCalcs; // Height * width used to calculate mDataSizes
+
S8 mRawDiscardLevel;
F32 mRate;
BOOL mReversible;
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index e2a77f1d1e..5d3fbe5128 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -458,6 +458,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc)
mCreationDate = creation_date_utc;
}
+void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
+{
+ // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags
+ // because we now detect when they should be set.
+ setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) );
+
+ // Enforce the PERM_OVERWRITE flags for any masks that are different
+ // but only for AT_OBJECT's since that is the only asset type that can
+ // exist in-world (instead of only in-inventory or in-object-contents).
+ if (LLAssetType::AT_OBJECT == getType())
+ {
+ LLPermissions old_permissions = old_item.getPermissions();
+ U32 flags_to_be_set = 0;
+ if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ }
+ if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ }
+ if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+ LLSaleInfo old_sale_info = old_item.getSaleInfo();
+ if(old_sale_info != getSaleInfo())
+ {
+ flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+ }
+ setFlags(getFlags() | flags_to_be_set);
+ }
+}
const LLSaleInfo& LLInventoryItem::getSaleInfo() const
{
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 64af6c94f5..bd581e860f 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -93,7 +93,6 @@ public:
virtual const LLUUID& getUUID() const;
const LLUUID& getParentUUID() const;
virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID
-
virtual const std::string& getName() const;
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@@ -263,6 +262,10 @@ public:
void setInventoryType(LLInventoryType::EType inv_type);
void setFlags(U32 flags);
void setCreationDate(time_t creation_date_utc);
+
+ // Check for changes in permissions masks and sale info
+ // and set the corresponding bits in mFlags
+ void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
// This is currently only used in the Viewer to handle calling cards
// where the creator is actually used to store the target.
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index aa8391230c..2a9a596912 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -136,9 +136,9 @@ class LLSD;
class LLAccessEntry
{
public:
- LLUUID mID;
- S32 mTime;
- U32 mFlags;
+ LLUUID mID; // Agent ID
+ S32 mTime; // Time (unix seconds) when entry expires
+ U32 mFlags; // Not used - currently should always be zero
};
typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 0babf26457..d2e5034734 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -288,6 +288,17 @@ BOOL LLPermissions::setOwnerAndGroup(
return allowed;
}
+//Fix for DEV-33917, last owner isn't used much and has little impact on
+//permissions so it's reasonably safe to do this, however, for now,
+//limiting the functionality of this routine to objects which are
+//group owned.
+void LLPermissions::setLastOwner(const LLUUID& last_owner)
+{
+ if (isGroupOwned())
+ mLastOwner = last_owner;
+}
+
+
// only call this if you know what you're doing
// there are usually perm-bit consequences when the
// ownerhsip changes
@@ -895,6 +906,8 @@ void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class)
{
reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator);
reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner);
+ reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup);
+ reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned);
}
// virtual
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 864088148f..d5a0881c8f 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -232,6 +232,10 @@ public:
// ownerhsip changes
void yesReallySetOwner(const LLUUID& owner, bool group_owned);
+ // Last owner doesn't have much in the way of permissions so it's
+ //not too dangerous to do this.
+ void setLastOwner(const LLUUID& last_owner);
+
// saves last owner, sets owner to uuid null, sets group
// owned. group_id must be the group of the object (that's who it
// is being deeded to) and the object must be group
diff --git a/indra/llinventory/lltransactiontypes.h b/indra/llinventory/lltransactiontypes.h
index 1cb7308bd4..2c699bcb87 100644
--- a/indra/llinventory/lltransactiontypes.h
+++ b/indra/llinventory/lltransactiontypes.h
@@ -69,6 +69,12 @@ const S32 TRANS_PARCEL_DIR_FEE = 2003;
const S32 TRANS_GROUP_TAX = 2004; // Taxes incurred as part of group membership
const S32 TRANS_CLASSIFIED_RENEW = 2005;
+// Codes 2100-2999 reserved for recurring billing services
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC = 2100;
+
// Codes 3000-3999 reserved for inventory transactions
const S32 TRANS_GIVE_INVENTORY = 3000;
@@ -84,6 +90,12 @@ const S32 TRANS_DWELL_BONUS = 5007;
const S32 TRANS_PAY_OBJECT = 5008;
const S32 TRANS_OBJECT_PAYS = 5009;
+// Codes 5100-5999 reserved for recurring billing transfers between users
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC_USER = 5100;
+
// Codes 6000-6999 reserved for group transactions
//const S32 TRANS_GROUP_JOIN = 6000; //reserved for future use
const S32 TRANS_GROUP_LAND_DEED = 6001;
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index cfd6183ec4..fdcc19d657 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -121,7 +121,7 @@ void LLQuaternion::quantize16(F32 lower, F32 upper)
mQ[VZ] = z;
mQ[VS] = s;
- normQuat();
+ normalize();
}
void LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -131,7 +131,7 @@ void LLQuaternion::quantize8(F32 lower, F32 upper)
mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
- normQuat();
+ normalize();
}
// LLVector3 Magnitude and Normalization Functions
@@ -346,7 +346,7 @@ const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
// mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
//#endif
//
-// normQuat();
+// normalize();
// return (*this);
}
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 5db9c5be2e..0769f29f23 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -469,20 +469,30 @@ inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b)
return a;
}
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
inline F32 LLQuaternion::normalize()
{
F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ // Floating point error can prevent some quaternions from achieving
+ // exact unity length. When trying to renormalize such quaternions we
+ // can oscillate between multiple quantized states. To prevent such
+ // drifts we only renomalize if the length is far enough from unity.
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
+ // we were given a very bad quaternion so we set it to identity
mQ[VX] = 0.f;
mQ[VY] = 0.f;
mQ[VZ] = 0.f;
@@ -499,11 +509,15 @@ inline F32 LLQuaternion::normQuat()
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ // only renormalize if length not close enough to 1.0 already
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1e8b5517e4..453286b83d 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,6 +3,7 @@
project(llmessage)
include(00-Common)
+include(GoogleMock)
include(LLAddBuildTest)
include(LLCommon)
include(LLMath)
@@ -221,6 +222,7 @@ IF (NOT LINUX AND VIEWER)
# llhttpclientadapter.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp
+ llregionpresenceverifier.cpp
)
# set(TEST_DEBUG on)
set(test_libs
@@ -229,6 +231,7 @@ IF (NOT LINUX AND VIEWER)
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(
@@ -241,3 +244,4 @@ IF (NOT LINUX AND VIEWER)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
ENDIF (NOT LINUX AND VIEWER)
+
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 47d49076f4..c044b3d80d 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -100,7 +100,6 @@ public:
// LEGACY
boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
-
// This method needs to be called from time to time to send out
// requests.
void processPending();
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index a4af8e989b..5ff41322b7 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -131,7 +131,7 @@ void LLCurl::Responder::errorWithContent(
// virtual
void LLCurl::Responder::error(U32 status, const std::string& reason)
{
- llinfos << status << ": " << reason << llendl;
+ llinfos << mURL << " [" << status << "]: " << reason << llendl;
}
// virtual
@@ -139,6 +139,11 @@ void LLCurl::Responder::result(const LLSD& content)
{
}
+void LLCurl::Responder::setURL(const std::string& url)
+{
+ mURL = url;
+}
+
// virtual
void LLCurl::Responder::completedRaw(
U32 status,
@@ -148,7 +153,11 @@ void LLCurl::Responder::completedRaw(
{
LLSD content;
LLBufferStream istr(channels, buffer.get());
- LLSDSerialize::fromXML(content, istr);
+ if (!LLSDSerialize::fromXML(content, istr))
+ {
+ llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
+ }
+
completed(status, reason, content);
}
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fbd3077cbf..0b58e7c4a5 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -120,8 +120,14 @@ public:
// of the header can be parsed. In the ::completed call above only the body is contained in the LLSD.
virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
+ // Used internally to set the url for debugging later.
+ void setURL(const std::string& url);
+
public: /* but not really -- don't touch this */
U32 mReferenceCount;
+
+ private:
+ std::string mURL;
};
typedef boost::intrusive_ptr<Responder> ResponderPtr;
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 8b90a4c5ca..12ecbb36eb 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -265,6 +265,11 @@ static void request(
}
}
+ if (responder)
+ {
+ responder->setURL(url);
+ }
+
req->setCallback(new LLHTTPClientURLAdaptor(responder));
if (method == LLURLRequest::HTTP_POST && gMessageSystem)
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index b6988224ce..9d3c83f828 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadapter.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index 7f76390d0c..a205a2f260 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadepter.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 42a8e5cd0a..085a59cf27 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index a00dbd1809..97134bd336 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -521,7 +521,7 @@ protected:
* seek orfor string assignment.
* @returns Returns true if a line was found.
*/
- bool readLine(
+ bool readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -592,7 +592,7 @@ LLHTTPResponder::~LLHTTPResponder()
//lldebugs << "destroying LLHTTPResponder" << llendl;
}
-bool LLHTTPResponder::readLine(
+bool LLHTTPResponder::readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -670,7 +670,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
#endif
PUMP_DEBUG;
- if(readLine(channels, buffer, (U8*)buf, len))
+ if(readHeaderLine(channels, buffer, (U8*)buf, len))
{
bool read_next_line = false;
bool parse_all = true;
@@ -734,7 +734,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
if(read_next_line)
{
len = HEADER_BUFFER_SIZE;
- readLine(channels, buffer, (U8*)buf, len);
+ if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ // Failed to read the header line, probably too long.
+ // readHeaderLine already marked the channel/buffer as bad.
+ keep_parsing = false;
+ break;
+ }
}
if(0 == len)
{
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index d52ff6c7e8..ce206d8d7d 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction(
// static
bool LLMail::send(
const std::string& header,
- const std::string& message,
+ const std::string& raw_message,
const char* from_address,
const char* to_address)
{
@@ -276,8 +276,20 @@ bool LLMail::send(
return false;
}
- // *FIX: this translation doesn't deal with a single period on a
- // line by itself.
+ // remove any "." SMTP commands to prevent injection (DEV-35777)
+ // we don't need to worry about "\r\n.\r\n" because of the
+ // "\n" --> "\n\n" conversion going into rfc2822_msg below
+ std::string message = raw_message;
+ std::string bad_string = "\n.\n";
+ std::string good_string = "\n..\n";
+ while (1)
+ {
+ int index = message.find(bad_string);
+ if (index == std::string::npos) break;
+ message.replace(index, bad_string.size(), good_string);
+ }
+
+ // convert all "\n" into "\r\n"
std::ostringstream rfc2822_msg;
for(U32 i = 0; i < message.size(); ++i)
{
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 119eb1d7f7..af6733fa05 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llmessagesenderinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 0527d5cb8d..e02c735ce7 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -36,11 +36,40 @@
#include "net.h"
#include "message.h"
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+ {
+ ++p->mReferenceCount;
+ }
+
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+ {
+ if(p && 0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
+};
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
{
}
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+ uri,
+ ResponsePtr data,
+ S32 retry_count) :
+ mUri(uri),
+ mSharedData(data),
+ mRetryCount(retry_count)
+{
+}
+
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
{
@@ -49,30 +78,36 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
LLHost destination(host, port);
LLUUID id = content["region_id"];
- llinfos << "Verifying " << destination.getString() << " is region " << id << llendl;
+ lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl;
std::stringstream uri;
uri << "http://" << destination.getString() << "/state/basic/";
- mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+ mSharedData->getHttpClient().get(
+ uri.str(),
+ new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
}
-void LLRegionPresenceVerifier::RegionResponder::completed(
- U32 status,
- const std::string& reason,
- const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+ const std::string& reason)
{
- LLHTTPClient::Responder::completed(status, reason, content);
-
- mSharedData->onCompletedRegionRequest();
+ // TODO: babbage: distinguish between region presence service and
+ // region verification errors?
+ mSharedData->onRegionVerificationFailed();
}
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+ S32 retry_count):
+ mUri(uri),
+ mSharedData(data),
+ mContent(content),
+ mRetryCount(retry_count)
{
}
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
{
@@ -87,13 +122,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
{
mSharedData->onRegionVerified(mContent);
}
- else if (mSharedData->shouldRetry())
+ else if (mRetryCount > 0)
{
retry();
}
else
{
- llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+ llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
}
}
@@ -101,13 +137,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
{
LLSD headers;
headers["Cache-Control"] = "no-cache, max-age=0";
- llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
- mSharedData->decrementRetries();
- mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+ llinfos << "Requesting region information, get uncached for region "
+ << mUri << llendl;
+ --mRetryCount;
+ mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
}
void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
{
- retry();
+ if(mRetryCount > 0)
+ {
+ retry();
+ }
+ else
+ {
+ llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+ mSharedData->onRegionVerificationFailed();
+ }
}
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index 54ad6226d6..f57a62a731 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -37,7 +37,7 @@
#include "llhttpclient.h"
#include <string>
#include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
class LLHTTPClientInterface;
@@ -47,49 +47,58 @@ public:
class Response
{
public:
- virtual ~Response() {}
+ virtual ~Response() = 0;
virtual bool checkValidity(const LLSD& content) const = 0;
virtual void onRegionVerified(const LLSD& region_details) = 0;
-
- virtual void decrementRetries() = 0;
+ virtual void onRegionVerificationFailed() = 0;
virtual LLHTTPClientInterface& getHttpClient() = 0;
- virtual std::string getRegionUri() const = 0;
- virtual bool shouldRetry() const = 0;
- virtual void onCompletedRegionRequest() {}
+ public: /* but not really -- don't touch this */
+ U32 mReferenceCount;
};
- typedef boost::shared_ptr<Response> ResponsePtr;
+ typedef boost::intrusive_ptr<Response> ResponsePtr;
class RegionResponder : public LLHTTPClient::Responder
{
public:
- RegionResponder(ResponsePtr data);
+ RegionResponder(const std::string& uri, ResponsePtr data,
+ S32 retry_count);
+ virtual ~RegionResponder();
virtual void result(const LLSD& content);
- virtual void completed(
- U32 status,
- const std::string& reason,
- const LLSD& content);
+ virtual void error(U32 status, const std::string& reason);
private:
ResponsePtr mSharedData;
+ std::string mUri;
+ S32 mRetryCount;
};
class VerifiedDestinationResponder : public LLHTTPClient::Responder
{
public:
- VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+ VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+ const LLSD& content, S32 retry_count);
+ virtual ~VerifiedDestinationResponder();
virtual void result(const LLSD& content);
virtual void error(U32 status, const std::string& reason);
+
private:
void retry();
ResponsePtr mSharedData;
LLSD mContent;
+ std::string mUri;
+ S32 mRetryCount;
};
};
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+ void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
#endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 32cbb15cb3..d6b2f45d04 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index 5069c2cb2e..359e4c5aea 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.h
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62..0872efba50 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
return changed;
}
+// Return bits available in the channel
+S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+ S32 retval = 0;
+
+ F32 category_bps = mCurrentBPS[throttle_cat];
+ F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+ F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+ if (bits_available >= lookahead_bits)
+ {
+ retval = (S32) gThrottleMaximumBPS[throttle_cat];
+ }
+ else
+ {
+ retval = (S32) bits_available;
+ }
+
+ return retval;
+}
+
BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
{
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb2..47a7c653b2 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ public:
BOOL dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
BOOL setNominalBPS(F32* throttle_vec); // TRUE if any value was different, resets adjustment system if was different
+ S32 getAvailable(S32 throttle_cat); // Return bits available in the channel
+
void packThrottle(LLDataPacker &dp) const;
void unpackThrottle(LLDataPacker &dp);
public:
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 5a1cd95ffc..41f3f3f607 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -270,7 +270,6 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_GESTURE:
- case LLAssetType::AT_FAVORITE:
rv = true;
break;
default:
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb..81b7761ed5 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
* String constants
*/
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
//llinfos << "LLURLRequest::process_impl()" << llendl;
- if(!buffer) return STATUS_ERROR;
+ if (!buffer) return STATUS_ERROR;
+
+ // we're still waiting or prcessing, check how many
+ // bytes we have accumulated.
+ const S32 MIN_ACCUMULATION = 100000;
+ if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+ {
+ // This is a pretty sloppy calculation, but this
+ // tries to make the gross assumption that if data
+ // is coming in at 56kb/s, then this transfer will
+ // probably succeed. So, if we're accumlated
+ // 100,000 bytes (MIN_ACCUMULATION) then let's
+ // give this client another 2s to complete.
+ const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+ mDetail->mByteAccumulator = 0;
+ pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+ lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+ if (mState == STATE_INITIALIZED)
+ {
+ llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+ }
+ }
+
switch(mState)
{
case STATE_INITIALIZED:
@@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
bool newmsg = mDetail->mCurlRequest->getResult(&result);
if(!newmsg)
{
- // we're still waiting or prcessing, check how many
- // bytes we have accumulated.
- const S32 MIN_ACCUMULATION = 100000;
- if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
- {
- // This is a pretty sloppy calculation, but this
- // tries to make the gross assumption that if data
- // is coming in at 56kb/s, then this transfer will
- // probably succeed. So, if we're accumlated
- // 100,000 bytes (MIN_ACCUMULATION) then let's
- // give this client another 2s to complete.
- const F32 TIMEOUT_ADJUSTMENT = 2.0f;
- mDetail->mByteAccumulator = 0;
- pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
- }
-
// keep processing
break;
}
mState = STATE_HAVE_RESPONSE;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
switch(result)
{
case CURLE_OK:
@@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
// we already stuffed everything into channel in in the curl
// callback, so we are done.
eos = true;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_DONE;
default:
PUMP_DEBUG;
+ context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+ context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+ lldebugs << this << "Setting context to " << context << llendl;
return STATUS_ERROR;
}
}
@@ -369,6 +385,8 @@ void LLURLRequest::initialize()
mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+ mRequestTransferedBytes = 0;
+ mResponseTransferedBytes = 0;
}
bool LLURLRequest::configure()
@@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(
req->mDetail->mChannels.out(),
(U8*)data,
bytes);
+ req->mResponseTransferedBytes += bytes;
req->mDetail->mByteAccumulator += bytes;
return bytes;
}
@@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(
req->mDetail->mLastRead,
(U8*)data,
bytes);
+ req->mRequestTransferedBytes += bytes;
return bytes;
}
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085..cb3c466440 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
#include "llchainio.h"
#include "llerror.h"
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
class LLURLRequestDetail;
class LLURLRequestComplete;
@@ -208,6 +214,8 @@ protected:
ERequestAction mAction;
LLURLRequestDetail* mDetail;
LLIOPipe::ptr_t mCompletionCallback;
+ S32 mRequestTransferedBytes;
+ S32 mResponseTransferedBytes;
private:
/**
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 08c9192c9f..209bdb2249 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix)
static bool verify_cache_filename(const std::string& filename)
{
//NOTE: This routine is only used to check file names that our own
- // code places in the cache directory. As such, it can be limited
- // to this very restrictive file name pattern. It does not need to
- // handle other characters.
-
+ // code places in the cache directory. As such, it can be limited
+ // to this very restrictive file name pattern. It does not need to
+ // handle other characters. The only known uses of this are (with examples):
+ // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp
+ // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
+ // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
+
+ //IMPORTANT: Do not broaden the filenames accepted by this routine
+ // without careful analysis. Anything allowed by this function can
+ // be downloaded by the viewer.
+
size_t len = filename.size();
- //const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>");
- if (len < 1 || len > 50)
- {
+ //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
+ if (len < 5 || len > 50)
+ {
return false;
}
- for(unsigned i=0; i<len; ++i)
- {
+ for(size_t i=0; i<(len-4); ++i)
+ {
char c = filename[i];
- bool ok = isalnum(c);
- if (!ok && i > 0)
- {
- ok = '_'==c || '-'==c || '.'==c;
- }
+ bool ok = isalnum(c) || '_'==c || '-'==c;
if (!ok)
{
return false;
}
}
- return true;
+ return filename[len-4] == '.'
+ && filename[len-3] == 't'
+ && filename[len-2] == 'm'
+ && filename[len-1] == 'p';
}
void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 5dc5932fde..e6a5ad9946 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -22,6 +22,7 @@
#include "linden_common.h"
LLCurl::Responder::Responder()
+ : mReferenceCount(0)
{
}
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
new file mode 100644
index 0000000000..2f55e97fcc
--- /dev/null
+++ b/indra/llmessage/tests/llmockhttpclient.h
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement 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$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLMOCKHTTPCLIENT_H
+#define LL_LLMOCKHTTPCLIENT_H
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+#include <gmock/gmock.h>
+
+class LLMockHTTPClient : public LLHTTPClientInterface
+{
+public:
+ MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
+ MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
+ MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
+};
+
+// A helper to match responder types
+template<typename T>
+struct ResponderType
+{
+ bool operator()(LLCurl::ResponderPtr ptr) const
+ {
+ T* p = dynamic_cast<T*>(ptr.get());
+ return p != NULL;
+ }
+};
+
+inline bool operator==(const LLSD& l, const LLSD& r)
+{
+ std::ostringstream ls, rs;
+ ls << l;
+ rs << r;
+ return ls.str() == rs.str();
+
+}
+
+
+#endif //LL_LLMOCKHTTPCLIENT_H
+
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000..b7602ef15c
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,111 @@
+/**
+ * @file
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+ virtual bool checkValidity(const LLSD& content) const
+ {
+ return true;
+ }
+
+ virtual void onRegionVerified(const LLSD& region_details)
+ {
+ }
+
+ virtual void onRegionVerificationFailed()
+ {
+ }
+
+ virtual LLHTTPClientInterface& getHttpClient()
+ {
+ return mHttpInterface;
+ }
+
+ LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+ struct LLRegionPresenceVerifierData
+ {
+ LLRegionPresenceVerifierData() :
+ mResponse(new LLTestResponse()),
+ mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+ LLSD(), 3)
+ {
+ }
+
+ LLTestResponse* mResponse;
+ LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+ };
+
+ typedef test_group<LLRegionPresenceVerifierData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+ // Test that VerifiedDestinationResponder does retry
+ // on error when shouldRetry returns true.
+ template<> template<>
+ void object::test<1>()
+ {
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+ }
+
+ // Test that VerifiedDestinationResponder only retries
+ // on error until shouldRetry returns false.
+ template<> template<>
+ void object::test<2>()
+ {
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ mResponder.error(500, "Internal server error");
+ ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+ }
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 7299ede22d..e019cdcf21 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -884,6 +884,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
}
/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
void LLPluginClassMedia::pluginDied()
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 331ca5f6dc..97f2a11ef2 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -135,6 +135,7 @@ public:
// Inherited from LLPluginProcessParentOwner
/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+ /* virtual */ void pluginLaunchFailed();
/* virtual */ void pluginDied();
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index df6de0925e..cfee847080 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -56,7 +56,8 @@ public:
MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are
MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
- MEDIA_EVENT_PLUGIN_FAILED // The plugin failed to launch or died unexpectedly
+ MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
+ MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly
} EMediaEvent;
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 41784a713c..f3b4c6bdc6 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -83,6 +83,14 @@ void LLPluginProcessParent::killSockets(void)
mSocket.reset();
}
+void LLPluginProcessParent::errorState(void)
+{
+ if(mState < STATE_RUNNING)
+ setState(STATE_LAUNCH_FAILURE);
+ else
+ setState(STATE_ERROR);
+}
+
void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename)
{
mProcess.setExecutable(launcher_filename);
@@ -132,7 +140,7 @@ bool LLPluginProcessParent::accept()
ll_apr_warn_status(status);
// Some other error.
- setState(STATE_ERROR);
+ errorState();
}
return result;
@@ -150,15 +158,15 @@ void LLPluginProcessParent::idle(void)
if(!mMessagePipe->pump())
{
// LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
}
- if((mSocketError != APR_SUCCESS) && (mState < STATE_ERROR))
+ if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING))
{
// The socket is in an error state -- the plugin is gone.
LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
// If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
@@ -191,7 +199,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -202,7 +210,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -212,7 +220,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
mBoundPort = bound_addr->port;
@@ -222,7 +230,7 @@ void LLPluginProcessParent::idle(void)
LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
}
@@ -234,7 +242,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -242,7 +250,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -255,7 +263,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -274,7 +282,7 @@ void LLPluginProcessParent::idle(void)
mProcess.addArgument(stream.str());
if(mProcess.launch() != 0)
{
- setState(STATE_ERROR);
+ errorState();
}
else
{
@@ -290,7 +298,7 @@ void LLPluginProcessParent::idle(void)
// waiting for the plugin to connect
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
else
{
@@ -309,7 +317,7 @@ void LLPluginProcessParent::idle(void)
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
break;
@@ -330,14 +338,14 @@ void LLPluginProcessParent::idle(void)
// The load_plugin_response message will kick us from here into STATE_RUNNING
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
break;
case STATE_RUNNING:
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
break;
@@ -349,8 +357,16 @@ void LLPluginProcessParent::idle(void)
else if(pluginLockedUp())
{
LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl;
- setState(STATE_ERROR);
+ errorState();
+ }
+ break;
+
+ case STATE_LAUNCH_FAILURE:
+ if(mOwner != NULL)
+ {
+ mOwner->pluginLaunchFailed();
}
+ setState(STATE_CLEANUP);
break;
case STATE_ERROR:
@@ -467,7 +483,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
else
{
LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
}
@@ -477,6 +493,9 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
{
// Plugin has been loaded.
+ mPluginVersionString = message.getValue("plugin_version");
+ LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL;
+
// Check which message classes/versions the plugin supports.
// TODO: check against current versions
// TODO: kill plugin on major mismatches?
@@ -487,8 +506,6 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
}
- mPluginVersionString = message.getValue("plugin_version");
-
// Send initial sleep time
setSleepTime(mSleepTime, true);
@@ -497,7 +514,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
else
{
LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
}
else if(message_name == "heartbeat")
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 0d0b047c88..754ebeb946 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -45,6 +45,7 @@ public:
virtual ~LLPluginProcessParentOwner();
virtual void receivePluginMessage(const LLPluginMessage &message) = 0;
// This will only be called when the plugin has died unexpectedly
+ virtual void pluginLaunchFailed() {};
virtual void pluginDied() {};
};
@@ -68,6 +69,9 @@ public:
bool isDone(void);
void killSockets(void);
+
+ // Go to the proper error state
+ void errorState(void);
void setSleepTime(F64 sleep_time, bool force_send = false);
F64 getSleepTime(void) const { return mSleepTime; };
@@ -110,6 +114,7 @@ private:
STATE_HELLO, // first message from the plugin process has been received
STATE_LOADING, // process has been asked to load the plugin
STATE_RUNNING, //
+ STATE_LAUNCH_FAILURE, // Failure before plugin loaded
STATE_ERROR, // generic bailout state
STATE_CLEANUP, // clean everything up
STATE_EXITING, // Tried to kill process, waiting for it to exit
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index b102254b62..d307d4bbfb 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -746,16 +746,201 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
U32 old_face_mask = mVolumep->mFaceMask;
+ S32 face_bit = 0;
+ S32 cur_mask = 0;
+
+ // Grab copies of the old faces from the original shape, ordered by type.
+ // We will use these to figure out what old texture info gets mapped to new
+ // faces in the new shape.
+ std::vector<LLProfile::Face> old_faces;
+ for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
+ {
+ old_faces.push_back(mVolumep->getProfile().mFaces[face]);
+ }
+
+ // Copy the old texture info off to the side, but not in the order in which
+ // they live in the mTextureList, rather in order of ther "face id" which
+ // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
+ //
+ // Hence, some elements of old_tes::mEntryList will be invalid. It is
+ // initialized to a size of 9 (max number of possible faces on a volume?)
+ // and only the ones with valid types are filled in.
+ LLPrimTextureList old_tes;
+ old_tes.setSize(9);
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ cur_mask = 0x1 << face_bit;
+ if (old_face_mask & cur_mask)
+ {
+ S32 te_index = face_index_from_id(cur_mask, old_faces);
+ old_tes.copyTexture(face_bit, *(getTE(te_index)));
+ //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
+ }
+ }
+
+
// build the new object
sVolumeManager->unrefVolume(mVolumep);
mVolumep = volumep;
U32 new_face_mask = mVolumep->mFaceMask;
- if (old_face_mask != new_face_mask)
+ S32 i;
+
+ if (old_face_mask == new_face_mask)
{
+ // nothing to do
+ return TRUE;
+ }
+
+ if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
+ {
+ llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
setNumTEs(mVolumep->getNumFaces());
+ return TRUE;
+ }
+
+ // initialize face_mapping
+ S32 face_mapping[9];
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ face_mapping[face_bit] = face_bit;
+ }
+
+ // The new shape may have more faces than the original, but we can't just
+ // add them to the end -- the ordering matters and it may be that we must
+ // insert the new faces in the middle of the list. When we add a face it
+ // will pick up the texture/color info of one of the old faces an so we
+ // now figure out which old face info gets mapped to each new face, and
+ // store in the face_mapping lookup table.
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ cur_mask = 0x1 << face_bit;
+ if (!(new_face_mask & cur_mask))
+ {
+ // Face doesn't exist in new map.
+ face_mapping[face_bit] = -1;
+ continue;
+ }
+ else if (old_face_mask & cur_mask)
+ {
+ // Face exists in new and old map.
+ face_mapping[face_bit] = face_bit;
+ continue;
+ }
+
+ // OK, how we've got a mismatch, where we have to fill a new face with one from
+ // the old face.
+ if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
+ {
+ // It's a top/bottom/hollow interior face.
+ if (old_face_mask & LL_FACE_PATH_END)
+ {
+ face_mapping[face_bit] = 1;
+ continue;
+ }
+ else
+ {
+ S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & cur_outer_mask)
+ {
+ face_mapping[face_bit] = 5 + i;
+ break;
+ }
+ cur_outer_mask <<= 1;
+ }
+ if (i == 4)
+ {
+ llwarns << "No path end or outer face in volume!" << llendl;
+ }
+ continue;
+ }
+ }
+
+ if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
+ {
+ // A cut slice. Use the hollow interior if we have it.
+ if (old_face_mask & LL_FACE_INNER_SIDE)
+ {
+ face_mapping[face_bit] = 2;
+ continue;
+ }
+
+ // No interior, use the bottom face.
+ // Could figure out which of the outer faces was nearest, but that would be harder.
+ if (old_face_mask & LL_FACE_PATH_END)
+ {
+ face_mapping[face_bit] = 1;
+ continue;
+ }
+ else
+ {
+ S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & cur_outer_mask)
+ {
+ face_mapping[face_bit] = 5 + i;
+ break;
+ }
+ cur_outer_mask <<= 1;
+ }
+ if (i == 4)
+ {
+ llwarns << "No path end or outer face in volume!" << llendl;
+ }
+ continue;
+ }
+ }
+
+ // OK, the face that's missing is an outer face...
+ // Pull from the nearest adjacent outer face (there's always guaranteed to be one...
+ S32 cur_outer = face_bit - 5;
+ S32 min_dist = 5;
+ S32 min_outer_bit = -1;
+ S32 i;
+ for (i = 0; i < 4; i++)
+ {
+ if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
+ {
+ S32 dist = abs(i - cur_outer);
+ if (dist < min_dist)
+ {
+ min_dist = dist;
+ min_outer_bit = i + 5;
+ }
+ }
+ }
+ if (-1 == min_outer_bit)
+ {
+ llinfos << (LLVolume *)mVolumep << llendl;
+ llwarns << "Bad! No outer faces, impossible!" << llendl;
+ }
+ face_mapping[face_bit] = min_outer_bit;
}
+
+ setNumTEs(mVolumep->getNumFaces());
+ for (face_bit = 0; face_bit < 9; face_bit++)
+ {
+ // For each possible face type on the new shape we check to see if that
+ // face exists and if it does we create a texture entry that is a copy
+ // of one of the originals. Since the originals might not have a
+ // matching face, we use the face_mapping lookup table to figure out
+ // which face information to copy.
+ cur_mask = 0x1 << face_bit;
+ if (new_face_mask & cur_mask)
+ {
+ if (-1 == face_mapping[face_bit])
+ {
+ llwarns << "No mapping from old face to new face!" << llendl;
+ }
+
+ S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
+ setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
+ }
+ }
return TRUE;
}
@@ -1715,10 +1900,10 @@ LLSD LLLightImageParams::asLLSD() const
bool LLLightImageParams::fromLLSD(LLSD& sd)
{
- if (sd.has("texture") && sd.has("params") && sd["params"].size() == 3)
+ if (sd.has("texture"))
{
setLightTexture( sd["texture"] );
- setParams( LLVector3(sd["params"][0].asReal(), sd["params"][1].asReal(), sd["params"][2].asReal()) );
+ setParams( LLVector3( sd["params"] ) );
return true;
}
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index d03150fc78..1c7de95975 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -135,13 +135,12 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te)
{
if (S32(index) >= mEntryList.size())
{
- // TODO -- assert here
S32 current_size = mEntryList.size();
- llerrs << "index = " << S32(index) << " current_size = " << current_size << llendl;
+ llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl;
return TEM_CHANGE_NONE;
}
- // we're changing an existing entry
+ // we're changing an existing entry
llassert(mEntryList[index]);
delete (mEntryList[index]);
if (&te)
@@ -387,8 +386,18 @@ void LLPrimTextureList::setSize(S32 new_size)
mEntryList.resize(new_size);
for (S32 index = current_size; index < new_size; ++index)
{
- LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
- mEntryList[index] = new_entry;
+ if (current_size > 0
+ && mEntryList[current_size - 1])
+ {
+ // copy the last valid entry for the new one
+ mEntryList[index] = mEntryList[current_size - 1]->newCopy();
+ }
+ else
+ {
+ // no valid enries to copy, so we new one up
+ LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
+ mEntryList[index] = new_entry;
+ }
}
}
else if (new_size < current_size)
diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index b534939dfc..8f7cd68834 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -646,3 +646,9 @@ LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &versi
}
return id;
}
+
+//static
+bool LLTextureEntry::isMediaVersionString(const std::string &version_string)
+{
+ return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX);
+}
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index 8d2834f78c..d6366b9bb2 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -171,7 +171,9 @@ public:
static U32 getVersionFromMediaVersionString(const std::string &version_string);
// Given a media version string, return the UUID of the agent
static LLUUID getAgentIDFromMediaVersionString(const std::string &version_string);
-
+ // Return whether or not the given string is actually a media version
+ static bool isMediaVersionString(const std::string &version_string);
+
// Media flags
enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 };
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 4525f0a45b..c512ef25be 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -91,6 +91,16 @@ void LLDockableFloater::setVisible(BOOL visible)
LLFloater::setVisible(visible);
}
+void LLDockableFloater::onDockHidden()
+{
+ setCanDock(FALSE);
+}
+
+void LLDockableFloater::onDockShown()
+{
+ setCanDock(TRUE);
+}
+
void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
{
if (mDockControl.get() != NULL && mDockControl.get()->isDockVisible())
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index ed90567ad3..7d91d007ee 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -68,6 +68,9 @@ public:
*/
/*virtual*/ void setVisible(BOOL visible);
+ virtual void onDockHidden();
+ virtual void onDockShown();
+
private:
/**
* Provides unique of dockable floater.
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 146c7a969a..cdcd823b1c 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -33,6 +33,7 @@
#include "linden_common.h"
#include "lldockcontrol.h"
+#include "lldockablefloater.h"
LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
@@ -91,8 +92,8 @@ void LLDockControl::repositionDockable()
// recalculate dockable position if dock position changed, dock visibility changed,
// root view rect changed or recalculation is forced
- if (mEnabled && (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible()
- || mRootRect != rootRect || mRecalculateDocablePosition))
+ if (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible()
+ || mRootRect != rootRect || mRecalculateDocablePosition)
{
// undock dockable and off() if dock not visible
if (!isDockVisible())
@@ -100,10 +101,25 @@ void LLDockControl::repositionDockable()
mDockableFloater->setDocked(false);
// force off() since dockable may not have dockControll at this time
off();
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if(dockable_floater != NULL)
+ {
+ dockable_floater->onDockHidden();
+ }
}
else
{
- moveDockable();
+ if(mEnabled)
+ {
+ moveDockable();
+ }
+ LLDockableFloater* dockable_floater =
+ dynamic_cast<LLDockableFloater*> (mDockableFloater);
+ if(dockable_floater != NULL)
+ {
+ dockable_floater->onDockShown();
+ }
}
mPrevDockRect = dockRect;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 564e4d748f..b7a15a2b33 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -664,7 +664,8 @@ void LLFloater::closeFloater(bool app_quitting)
dirtyRect();
- // Close callback
+ // Close callbacks
+ onClose(app_quitting);
mCloseSignal(this, LLSD(app_quitting));
// Hide or Destroy
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 1dc5177f81..17ffc94014 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -208,8 +208,8 @@ public:
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
virtual void draw();
- // *TODO: Eliminate this in favor of mOpenSignal
virtual void onOpen(const LLSD& key) {}
+ virtual void onClose(bool app_quitting) {}
// This cannot be "const" until all derived floater canClose()
// methods are const as well. JC
@@ -293,11 +293,18 @@ private:
void addResizeCtrls();
void addDragHandle();
+public:
+ // Called when floater is opened, passes mKey
+ // Public so external views or floaters can watch for this floater opening
+ commit_signal_t mOpenSignal;
+
+ // Called when floater is closed, passes app_qitting as LLSD()
+ // Public so external views or floaters can watch for this floater closing
+ commit_signal_t mCloseSignal;
+
protected:
std::string mRectControl;
std::string mVisibilityControl;
- commit_signal_t mOpenSignal; // Called when floater is opened, passes mKey
- commit_signal_t mCloseSignal; // Called when floater is closed, passes app_qitting as LLSD()
LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg
LLDragHandle* mDragHandle;
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 2bb6749c83..8dbcd6e229 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -83,6 +83,12 @@ void LLMenuButton::toggleMenu()
}
+void LLMenuButton::hideMenu()
+{
+ mMenu->setVisible(FALSE);
+}
+
+
BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
{
if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h
index 94b0e4355d..02eb9d3806 100644
--- a/indra/llui/llmenubutton.h
+++ b/indra/llui/llmenubutton.h
@@ -54,6 +54,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
+ void hideMenu();
protected:
friend class LLUICtrlFactory;
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 1695aee2b8..69ff3dddc3 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -522,7 +522,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
// be built/added. JC
if (parent)
{
- S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1;
+ S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : parent->getLastTabGroup();
parent->addChild(this, tab_group);
}
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 62f03f47e6..3dacf979c7 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -807,6 +807,9 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
++cur_seg_iter;
}
}
+
+ // layout potentially changed
+ needsReflow();
}
BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 8f5c029816..c55273cacf 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -38,6 +38,7 @@
// Library includes
#include "lltextbox.h"
#include "lliconctrl.h"
+#include "llmenugl.h" // hideMenus()
#include "llui.h" // positionViewNearMouse()
#include "llwindow.h"
@@ -94,7 +95,16 @@ BOOL LLToolTipView::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolTipView::handleMouseDown(S32 x, S32 y, MASK mask)
{
LLToolTipMgr::instance().blockToolTips();
- return LLView::handleMouseDown(x, y, mask);
+
+ if (LLView::handleMouseDown(x, y, mask))
+ {
+ // If we are handling the mouse event menu holder
+ // won't get a chance to close menus so do this here
+ LLMenuGL::sMenuContainer->hideMenus();
+ return TRUE;
+ }
+
+ return FALSE;
}
BOOL LLToolTipView::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
@@ -189,7 +199,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params));
// move text over to fit image in
- mTextBox->translate(TOOLTIP_ICON_SIZE,0);
+ mTextBox->translate(TOOLTIP_ICON_SIZE + mPadding, 0);
}
if (p.click_callback.isProvided())
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index e47010c316..3c77c655b8 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -321,7 +321,7 @@ fail:
static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
private:
- //static void setCtrlValue(LLView* view, LLXMLNodePtr node);
+ // this exists to get around dependency on llview
static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group);
// Avoid directly using LLUI and LLDir in the template code
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 93ac120302..315baa001d 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -62,7 +62,7 @@ class LLPidLockFile
mSaving(FALSE), mWaiting(FALSE),
mClean(TRUE), mPID(getpid())
{
- mLockName = gDirUtilp->getTempDir() + "/savelock";
+ mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
}
bool requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index d2760e3d59..7137c93476 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -2763,10 +2763,6 @@ const char* cursorIDToName(int id)
case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN";
case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN";
case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3";
- case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT";
- case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY";
- case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY";
- case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN";
case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY";
case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE";
case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN";
@@ -2862,10 +2858,6 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
case UI_CURSOR_TOOLPAN:
case UI_CURSOR_TOOLZOOMIN:
case UI_CURSOR_TOOLPICKOBJECT3:
- case UI_CURSOR_TOOLSIT:
- case UI_CURSOR_TOOLBUY:
- case UI_CURSOR_TOOLPAY:
- case UI_CURSOR_TOOLOPEN:
case UI_CURSOR_TOOLPLAY:
case UI_CURSOR_TOOLPAUSE:
case UI_CURSOR_TOOLMEDIAOPEN:
@@ -2907,10 +2899,6 @@ void LLWindowMacOSX::initCursors()
initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6);
initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1);
- initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1);
initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1);
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index ecda880c1f..00a8d429ba 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -1981,10 +1981,6 @@ void LLWindowSDL::initCursors()
mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5);
mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLPAY] = makeSDLCursorFromBMP("toolpay.BMP",0,0);
- mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0);
mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0);
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 0faa3e93ff..c608c21d05 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1527,10 +1527,6 @@ void LLWindowWin32::initCursors()
mCursor[ UI_CURSOR_PIPETTE ] = LoadCursor(module, TEXT("TOOLPIPETTE"));
// Color cursors
- mCursor[UI_CURSOR_TOOLSIT] = loadColorCursor(TEXT("TOOLSIT"));
- mCursor[UI_CURSOR_TOOLBUY] = loadColorCursor(TEXT("TOOLBUY"));
- mCursor[UI_CURSOR_TOOLPAY] = loadColorCursor(TEXT("TOOLPAY"));
- mCursor[UI_CURSOR_TOOLOPEN] = loadColorCursor(TEXT("TOOLOPEN"));
mCursor[UI_CURSOR_TOOLPLAY] = loadColorCursor(TEXT("TOOLPLAY"));
mCursor[UI_CURSOR_TOOLPAUSE] = loadColorCursor(TEXT("TOOLPAUSE"));
mCursor[UI_CURSOR_TOOLMEDIAOPEN] = loadColorCursor(TEXT("TOOLMEDIAOPEN"));
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index ba2c46bef2..a54ebd5831 100644
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -556,7 +556,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
// http_request string constants
extern const char* URL_REQUEST_GRANTED;
extern const char* URL_REQUEST_DENIED;
-extern const U64 LSL_HTTP_REQUEST_TIMEOUT;
+extern const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC;
#endif
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index 98146d6f2b..3b8bbbe805 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -631,9 +631,7 @@ static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetTy
switch(targetType)
{
case LST_INTEGER:
- //fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
- fprintf(fp, "conv.i4\n"); // TODO replace this line with the above
- // we the entire grid is > 1.25.1
+ fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
break;
case LST_STRING:
fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
@@ -8375,10 +8373,18 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp
chunk->addInteger(mIdentifier->mScopeEntry->mCount);
}
break;
+ case LSCP_TYPE:
+ mReturnType = basetype;
+ break;
case LSCP_EMIT_CIL_ASSEMBLY:
fprintf(fp, "ldarg.0\n");
fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName);
fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n");
+ // We are doing a state change. In the LSL interpreter, this is basically a longjmp. We emulate it
+ // here using a call to the ChangeState followed by a short cut return of the current method. To
+ // maintain type safety we need to push an arbitrary variable of the current method's return type
+ // onto the stack before returning. This will be ignored and discarded.
+ print_cil_init_variable(fp, mReturnType);
fprintf(fp, "ret\n");
break;
default:
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 12c16908af..a667e1eb5b 100644
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -1888,6 +1888,7 @@ public:
S32 getSize();
LLScriptIdentifier *mIdentifier;
+ LSCRIPTType mReturnType;
};
class LLScriptJump : public LLScriptStatement
diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h
index 245fc320d1..96855abea0 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -371,8 +371,7 @@ class LLScriptExecute
{
public:
LLScriptExecute();
- virtual ~LLScriptExecute() {;}
-
+ virtual ~LLScriptExecute() = 0;
virtual S32 getVersion() const = 0;
virtual void deleteAllEvents() = 0;
virtual void addEvent(LLScriptDataCollection* event) = 0;
diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp
index 2fd81210c0..e849fa9a6e 100644
--- a/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -41,6 +41,8 @@
#include "lscript_library.h"
#include "lscript_heapruntime.h"
#include "lscript_alloc.h"
+#include "llstat.h"
+
// Static
const S32 DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
@@ -72,7 +74,7 @@ const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
// HTTP Requests to LSL scripts will time out after 25 seconds.
-const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC;
+const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC;
LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
{
@@ -110,6 +112,7 @@ LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
init();
}
+LLScriptExecute::~LLScriptExecute() {}
LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
{
delete[] mBuffer;
@@ -4234,19 +4237,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
return 4;
}
-BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+
+// Shared code for run_calllib() and run_calllib_two_byte()
+BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg)
{
- if (b_print)
- printf("[0x%X]\tCALLLIB ", offset);
- offset++;
- U8 arg = safe_instruction_bytestream2byte(buffer, offset);
- if (arg >= (U8)gScriptLibrary.mFunctions.size())
+ if (arg >= gScriptLibrary.mFunctions.size())
{
set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
return FALSE;
}
- if (b_print)
- printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
// pull out the arguments and the return values
LLScriptLibData *arguments = NULL;
@@ -4254,14 +4254,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
S32 i, number;
- if (gScriptLibrary.mFunctions[arg].mReturnType)
+ if (function.mReturnType)
{
returnvalue = new LLScriptLibData;
}
- if (gScriptLibrary.mFunctions[arg].mArgs)
+ if (function.mArgs)
{
- number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs); /*Flawfinder: ignore*/
+ number = (S32)strlen(function.mArgs); //Flawfinder: ignore
arguments = new LLScriptLibData[number];
}
else
@@ -4271,23 +4271,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
for (i = number - 1; i >= 0; i--)
{
- lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
+ lscript_pop_variable(&arguments[i], buffer, function.mArgs[i]);
}
- if (b_print)
- {
- printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
- }
+ // Actually execute the function call
+ function.mExecFunc(returnvalue, arguments, id);
- {
- gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
- }
- add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
- add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+ add_register_fp(buffer, LREG_ESR, -(function.mEnergyUse));
+ add_register_fp(buffer, LREG_SLR, function.mSleepTime);
if (returnvalue)
{
- returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
+ returnvalue->mType = char2type(*function.mReturnType);
lscript_push_return_variable(returnvalue, buffer);
}
@@ -4304,71 +4299,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
}
-BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
{
- if (b_print)
- printf("[0x%X]\tCALLLIB ", offset);
offset++;
- U16 arg = safe_instruction_bytestream2u16(buffer, offset);
- if (arg >= (U16)gScriptLibrary.mFunctions.size())
+ U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset);
+ if (b_print &&
+ arg < gScriptLibrary.mFunctions.size())
{
- set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
- return FALSE;
- }
- if (b_print)
- printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
-
- // pull out the arguments and the return values
- LLScriptLibData *arguments = NULL;
- LLScriptLibData *returnvalue = NULL;
-
- S32 i, number;
-
- if (gScriptLibrary.mFunctions[arg].mReturnType)
- {
- returnvalue = new LLScriptLibData;
- }
-
- if (gScriptLibrary.mFunctions[arg].mArgs)
- {
- number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs); /*Flawfinder: ignore*/
- arguments = new LLScriptLibData[number];
- }
- else
- {
- number = 0;
- }
-
- for (i = number - 1; i >= 0; i--)
- {
- lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
- }
-
- if (b_print)
- {
- printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
- }
-
- {
- gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
+ printf("[0x%X]\tCALLLIB ", offset);
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+ printf("%d (%s)\n", (U32)arg, function.mName);
+ //printf("%s\n", function.mDesc);
}
- add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
- add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+ return run_calllib_common(buffer, offset, id, arg);
+}
- if (returnvalue)
+BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+{
+ offset++;
+ U16 arg = safe_instruction_bytestream2u16(buffer, offset);
+ if (b_print &&
+ arg < gScriptLibrary.mFunctions.size())
{
- returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
- lscript_push_return_variable(returnvalue, buffer);
+ printf("[0x%X]\tCALLLIB ", (offset-1));
+ LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+ printf("%d (%s)\n", (U32)arg, function.mName);
+ //printf("%s\n", function.mDesc);
}
-
- delete [] arguments;
- delete returnvalue;
-
- // reset the BP after calling the library files
- S32 bp = lscript_pop_int(buffer);
- set_bp(buffer, bp);
-
- // pop off the spot for the instruction pointer
- lscript_poparg(buffer, 4);
- return FALSE;
+ return run_calllib_common(buffer, offset, id, arg);
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 14a37981a6..e0ca0a760f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -187,6 +187,7 @@ set(viewer_SOURCE_FILES
llfloaternotificationsconsole.cpp
llfloateropenobject.cpp
llfloaterparcel.cpp
+ llfloaterpay.cpp
llfloaterperms.cpp
llfloaterpostcard.cpp
llfloaterpostprocess.cpp
@@ -218,7 +219,6 @@ set(viewer_SOURCE_FILES
llfollowcam.cpp
llfriendcard.cpp
llgesturemgr.cpp
- llgivemoney.cpp
llglsandbox.cpp
llgroupactions.cpp
llgrouplist.cpp
@@ -264,8 +264,7 @@ set(viewer_SOURCE_FILES
llmaniptranslate.cpp
llmapresponders.cpp
llmediactrl.cpp
- llmediadataresponder.cpp
- llmediadatafetcher.cpp
+ llmediadataclient.cpp
llmediaremotectrl.cpp
llmemoryview.cpp
llmenucommands.cpp
@@ -659,6 +658,7 @@ set(viewer_HEADER_FILES
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
+ llfloaterpay.h
llfloaterpostcard.h
llfloaterpostprocess.h
llfloaterpreference.h
@@ -691,7 +691,6 @@ set(viewer_HEADER_FILES
llfollowcam.h
llfriendcard.h
llgesturemgr.h
- llgivemoney.h
llgroupactions.h
llgrouplist.h
llgroupmgr.h
@@ -735,8 +734,7 @@ set(viewer_HEADER_FILES
llmanipscale.h
llmaniptranslate.h
llmapresponders.h
- llmediadataresponder.h
- llmediadatafetcher.h
+ llmediadataclient.h
llmediaremotectrl.h
llmemoryview.h
llmenucommands.h
@@ -1105,14 +1103,10 @@ if (WINDOWS)
res/ll_icon.BMP
res/ll_icon.ico
res/resource.h
- res/toolbuy.cur
- res/toolopen.cur
- res/toolpay.cur
res/toolpickobject.cur
res/toolpickobject2.cur
res/toolpickobject3.cur
res/toolpipette.cur
- res/toolsit.cur
)
set_source_files_properties(${viewer_RESOURCE_FILES}
@@ -1546,6 +1540,7 @@ include(LLAddBuildTest)
SET(viewer_TEST_SOURCE_FILES
llagentaccess.cpp
lldateutil.cpp
+ llmediadataclient.cpp
llviewerhelputil.cpp
)
set_source_files_properties(
@@ -1563,6 +1558,7 @@ set(test_libs
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(llcapabilitylistener
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 735424c647..0e685c818a 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -2,6 +2,6 @@
CFBundleName = "Second Life";
-CFBundleShortVersionString = "Second Life version 2.0.0.0";
-CFBundleGetInfoString = "Second Life version 2.0.0.0, Copyright 2004-2009 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 2.0.0.2639";
+CFBundleGetInfoString = "Second Life version 2.0.0.2639, Copyright 2004-2009 Linden Research, Inc.";
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 7264044d37..0c1d6ea105 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
- <string>2.0.0.0</string>
+ <string>2.0.0.2639</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index a49ccb77b4..0524834747 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -25,6 +25,7 @@
<string>AppCache</string>
<string>Window</string>
<string>RenderInit</string>
+ <string>MediaOnAPrim</string>
</array>
</map>
<map>
@@ -40,7 +41,6 @@
</array>
<key>tags</key>
<array>
- <string>ShaderLoading</string>
</array>
</map>
</array>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 94a5f5c52b..dc0e5ffa1d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5294,7 +5294,18 @@
<key>Value</key>
<integer>13</integer>
</map>
- <key>PrimMediaFetchQueueDelay</key>
+ <key>PrimMediaMaxRetries</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum number of retries for media queries.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>4</integer>
+ </map>
+ <key>PrimMediaRequestQueueDelay</key>
<map>
<key>Comment</key>
<string>Timer delay for fetching media from the queue (in seconds).</string>
@@ -6117,6 +6128,18 @@
<real>1.0</real>
</map>
+ <key>RenderHighlightEnable</key>
+ <map>
+ <key>Comment</key>
+ <string>Show glow effect when hovering on interactive objects.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+
<key>RenderHighlightFadeTime</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/character/avatar_eye.llm b/indra/newview/character/avatar_eye.llm
new file mode 100644
index 0000000000..8c6e74e1de
--- /dev/null
+++ b/indra/newview/character/avatar_eye.llm
Binary files differ
diff --git a/indra/newview/character/avatar_eye_1.llm b/indra/newview/character/avatar_eye_1.llm
new file mode 100644
index 0000000000..7a3b0d6f28
--- /dev/null
+++ b/indra/newview/character/avatar_eye_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_eyelashes.llm b/indra/newview/character/avatar_eyelashes.llm
new file mode 100644
index 0000000000..99995b5758
--- /dev/null
+++ b/indra/newview/character/avatar_eyelashes.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair.llm b/indra/newview/character/avatar_hair.llm
new file mode 100644
index 0000000000..df99de8db7
--- /dev/null
+++ b/indra/newview/character/avatar_hair.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_1.llm b/indra/newview/character/avatar_hair_1.llm
new file mode 100644
index 0000000000..6de31fdc23
--- /dev/null
+++ b/indra/newview/character/avatar_hair_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_2.llm b/indra/newview/character/avatar_hair_2.llm
new file mode 100644
index 0000000000..47d02ba9ce
--- /dev/null
+++ b/indra/newview/character/avatar_hair_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_3.llm b/indra/newview/character/avatar_hair_3.llm
new file mode 100644
index 0000000000..107f9e2a53
--- /dev/null
+++ b/indra/newview/character/avatar_hair_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_4.llm b/indra/newview/character/avatar_hair_4.llm
new file mode 100644
index 0000000000..1b9a12a0ca
--- /dev/null
+++ b/indra/newview/character/avatar_hair_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_hair_5.llm b/indra/newview/character/avatar_hair_5.llm
new file mode 100644
index 0000000000..1b9a12a0ca
--- /dev/null
+++ b/indra/newview/character/avatar_hair_5.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head.llm b/indra/newview/character/avatar_head.llm
new file mode 100644
index 0000000000..8d8b5e0442
--- /dev/null
+++ b/indra/newview/character/avatar_head.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_1.llm b/indra/newview/character/avatar_head_1.llm
new file mode 100644
index 0000000000..26291e6584
--- /dev/null
+++ b/indra/newview/character/avatar_head_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_2.llm b/indra/newview/character/avatar_head_2.llm
new file mode 100644
index 0000000000..c2b808b1a6
--- /dev/null
+++ b/indra/newview/character/avatar_head_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_3.llm b/indra/newview/character/avatar_head_3.llm
new file mode 100644
index 0000000000..a0676b1f1c
--- /dev/null
+++ b/indra/newview/character/avatar_head_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_head_4.llm b/indra/newview/character/avatar_head_4.llm
new file mode 100644
index 0000000000..5035585770
--- /dev/null
+++ b/indra/newview/character/avatar_head_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body.llm b/indra/newview/character/avatar_lower_body.llm
new file mode 100644
index 0000000000..0420899739
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_1.llm b/indra/newview/character/avatar_lower_body_1.llm
new file mode 100644
index 0000000000..1394eb848b
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_2.llm b/indra/newview/character/avatar_lower_body_2.llm
new file mode 100644
index 0000000000..0da9c1249e
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_3.llm b/indra/newview/character/avatar_lower_body_3.llm
new file mode 100644
index 0000000000..f3c49a1568
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_lower_body_4.llm b/indra/newview/character/avatar_lower_body_4.llm
new file mode 100644
index 0000000000..e71721063e
--- /dev/null
+++ b/indra/newview/character/avatar_lower_body_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt.llm b/indra/newview/character/avatar_skirt.llm
new file mode 100644
index 0000000000..08ce3d1700
--- /dev/null
+++ b/indra/newview/character/avatar_skirt.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_1.llm b/indra/newview/character/avatar_skirt_1.llm
new file mode 100644
index 0000000000..88076c321f
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_2.llm b/indra/newview/character/avatar_skirt_2.llm
new file mode 100644
index 0000000000..73b3effbc6
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_3.llm b/indra/newview/character/avatar_skirt_3.llm
new file mode 100644
index 0000000000..ded546fdea
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_skirt_4.llm b/indra/newview/character/avatar_skirt_4.llm
new file mode 100644
index 0000000000..b9d5cb945e
--- /dev/null
+++ b/indra/newview/character/avatar_skirt_4.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body.llm b/indra/newview/character/avatar_upper_body.llm
new file mode 100644
index 0000000000..da7d990540
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_1.llm b/indra/newview/character/avatar_upper_body_1.llm
new file mode 100644
index 0000000000..31e104cc20
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_1.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_2.llm b/indra/newview/character/avatar_upper_body_2.llm
new file mode 100644
index 0000000000..c1f4199b9c
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_2.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_3.llm b/indra/newview/character/avatar_upper_body_3.llm
new file mode 100644
index 0000000000..9e89ed8b3e
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_3.llm
Binary files differ
diff --git a/indra/newview/character/avatar_upper_body_4.llm b/indra/newview/character/avatar_upper_body_4.llm
new file mode 100644
index 0000000000..ec836d1dc3
--- /dev/null
+++ b/indra/newview/character/avatar_upper_body_4.llm
Binary files differ
diff --git a/indra/newview/character/blush_alpha.tga b/indra/newview/character/blush_alpha.tga
new file mode 100644
index 0000000000..05be7e7e3d
--- /dev/null
+++ b/indra/newview/character/blush_alpha.tga
Binary files differ
diff --git a/indra/newview/character/body_skingrain.tga b/indra/newview/character/body_skingrain.tga
new file mode 100644
index 0000000000..7264baac14
--- /dev/null
+++ b/indra/newview/character/body_skingrain.tga
Binary files differ
diff --git a/indra/newview/character/bodyfreckles_alpha.tga b/indra/newview/character/bodyfreckles_alpha.tga
new file mode 100644
index 0000000000..d30ab3d122
--- /dev/null
+++ b/indra/newview/character/bodyfreckles_alpha.tga
Binary files differ
diff --git a/indra/newview/character/bump_face_wrinkles.tga b/indra/newview/character/bump_face_wrinkles.tga
new file mode 100644
index 0000000000..54bf7a55be
--- /dev/null
+++ b/indra/newview/character/bump_face_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_head_base.tga b/indra/newview/character/bump_head_base.tga
new file mode 100644
index 0000000000..fa3568573a
--- /dev/null
+++ b/indra/newview/character/bump_head_base.tga
Binary files differ
diff --git a/indra/newview/character/bump_lowerbody_base.tga b/indra/newview/character/bump_lowerbody_base.tga
new file mode 100644
index 0000000000..498ea3c721
--- /dev/null
+++ b/indra/newview/character/bump_lowerbody_base.tga
Binary files differ
diff --git a/indra/newview/character/bump_pants_wrinkles.tga b/indra/newview/character/bump_pants_wrinkles.tga
new file mode 100644
index 0000000000..cca72415e8
--- /dev/null
+++ b/indra/newview/character/bump_pants_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_shirt_wrinkles.tga b/indra/newview/character/bump_shirt_wrinkles.tga
new file mode 100644
index 0000000000..9e0d757a48
--- /dev/null
+++ b/indra/newview/character/bump_shirt_wrinkles.tga
Binary files differ
diff --git a/indra/newview/character/bump_upperbody_base.tga b/indra/newview/character/bump_upperbody_base.tga
new file mode 100644
index 0000000000..e57d6352e6
--- /dev/null
+++ b/indra/newview/character/bump_upperbody_base.tga
Binary files differ
diff --git a/indra/newview/character/eyebrows_alpha.tga b/indra/newview/character/eyebrows_alpha.tga
new file mode 100644
index 0000000000..c363e482e1
--- /dev/null
+++ b/indra/newview/character/eyebrows_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeliner_alpha.tga b/indra/newview/character/eyeliner_alpha.tga
new file mode 100644
index 0000000000..1611eb3355
--- /dev/null
+++ b/indra/newview/character/eyeliner_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeshadow_inner_alpha.tga b/indra/newview/character/eyeshadow_inner_alpha.tga
new file mode 100644
index 0000000000..37d7919395
--- /dev/null
+++ b/indra/newview/character/eyeshadow_inner_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyeshadow_outer_alpha.tga b/indra/newview/character/eyeshadow_outer_alpha.tga
new file mode 100644
index 0000000000..00eef9d9f7
--- /dev/null
+++ b/indra/newview/character/eyeshadow_outer_alpha.tga
Binary files differ
diff --git a/indra/newview/character/eyewhite.tga b/indra/newview/character/eyewhite.tga
new file mode 100644
index 0000000000..a720496988
--- /dev/null
+++ b/indra/newview/character/eyewhite.tga
Binary files differ
diff --git a/indra/newview/character/facehair_chincurtains_alpha.tga b/indra/newview/character/facehair_chincurtains_alpha.tga
new file mode 100644
index 0000000000..b10397063c
--- /dev/null
+++ b/indra/newview/character/facehair_chincurtains_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_moustache_alpha.tga b/indra/newview/character/facehair_moustache_alpha.tga
new file mode 100644
index 0000000000..4068c4f2b1
--- /dev/null
+++ b/indra/newview/character/facehair_moustache_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_sideburns_alpha.tga b/indra/newview/character/facehair_sideburns_alpha.tga
new file mode 100644
index 0000000000..acddc2d9bd
--- /dev/null
+++ b/indra/newview/character/facehair_sideburns_alpha.tga
Binary files differ
diff --git a/indra/newview/character/facehair_soulpatch_alpha.tga b/indra/newview/character/facehair_soulpatch_alpha.tga
new file mode 100644
index 0000000000..687091a29f
--- /dev/null
+++ b/indra/newview/character/facehair_soulpatch_alpha.tga
Binary files differ
diff --git a/indra/newview/character/freckles_alpha.tga b/indra/newview/character/freckles_alpha.tga
new file mode 100644
index 0000000000..a9a4ec0735
--- /dev/null
+++ b/indra/newview/character/freckles_alpha.tga
Binary files differ
diff --git a/indra/newview/character/glove_length_alpha.tga b/indra/newview/character/glove_length_alpha.tga
new file mode 100644
index 0000000000..db89ad57e7
--- /dev/null
+++ b/indra/newview/character/glove_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/gloves_fingers_alpha.tga b/indra/newview/character/gloves_fingers_alpha.tga
new file mode 100644
index 0000000000..dba2eec277
--- /dev/null
+++ b/indra/newview/character/gloves_fingers_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_alpha.tga b/indra/newview/character/head_alpha.tga
new file mode 100644
index 0000000000..8164525353
--- /dev/null
+++ b/indra/newview/character/head_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_color.tga b/indra/newview/character/head_color.tga
new file mode 100644
index 0000000000..74b1b3078b
--- /dev/null
+++ b/indra/newview/character/head_color.tga
Binary files differ
diff --git a/indra/newview/character/head_hair.tga b/indra/newview/character/head_hair.tga
new file mode 100644
index 0000000000..5321f35204
--- /dev/null
+++ b/indra/newview/character/head_hair.tga
Binary files differ
diff --git a/indra/newview/character/head_highlights_alpha.tga b/indra/newview/character/head_highlights_alpha.tga
new file mode 100644
index 0000000000..8dc5239f97
--- /dev/null
+++ b/indra/newview/character/head_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_shading_alpha.tga b/indra/newview/character/head_shading_alpha.tga
new file mode 100644
index 0000000000..e8ea490109
--- /dev/null
+++ b/indra/newview/character/head_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/head_skingrain.tga b/indra/newview/character/head_skingrain.tga
new file mode 100644
index 0000000000..b42dee0809
--- /dev/null
+++ b/indra/newview/character/head_skingrain.tga
Binary files differ
diff --git a/indra/newview/character/jacket_length_lower_alpha.tga b/indra/newview/character/jacket_length_lower_alpha.tga
new file mode 100644
index 0000000000..722bc192a8
--- /dev/null
+++ b/indra/newview/character/jacket_length_lower_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_length_upper_alpha.tga b/indra/newview/character/jacket_length_upper_alpha.tga
new file mode 100644
index 0000000000..e9db7e7b1f
--- /dev/null
+++ b/indra/newview/character/jacket_length_upper_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_open_lower_alpha.tga b/indra/newview/character/jacket_open_lower_alpha.tga
new file mode 100644
index 0000000000..db0c2fb0e3
--- /dev/null
+++ b/indra/newview/character/jacket_open_lower_alpha.tga
Binary files differ
diff --git a/indra/newview/character/jacket_open_upper_alpha.tga b/indra/newview/character/jacket_open_upper_alpha.tga
new file mode 100644
index 0000000000..71b8a0b805
--- /dev/null
+++ b/indra/newview/character/jacket_open_upper_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lipgloss_alpha.tga b/indra/newview/character/lipgloss_alpha.tga
new file mode 100644
index 0000000000..78ceecaf85
--- /dev/null
+++ b/indra/newview/character/lipgloss_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lips_mask.tga b/indra/newview/character/lips_mask.tga
new file mode 100644
index 0000000000..ae1401c006
--- /dev/null
+++ b/indra/newview/character/lips_mask.tga
Binary files differ
diff --git a/indra/newview/character/lipstick_alpha.tga b/indra/newview/character/lipstick_alpha.tga
new file mode 100644
index 0000000000..2795f1bd40
--- /dev/null
+++ b/indra/newview/character/lipstick_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_color.tga b/indra/newview/character/lowerbody_color.tga
new file mode 100644
index 0000000000..a63aa12fca
--- /dev/null
+++ b/indra/newview/character/lowerbody_color.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_highlights_alpha.tga b/indra/newview/character/lowerbody_highlights_alpha.tga
new file mode 100644
index 0000000000..ae3413ac8b
--- /dev/null
+++ b/indra/newview/character/lowerbody_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/lowerbody_shading_alpha.tga b/indra/newview/character/lowerbody_shading_alpha.tga
new file mode 100644
index 0000000000..0242663a7d
--- /dev/null
+++ b/indra/newview/character/lowerbody_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/nailpolish_alpha.tga b/indra/newview/character/nailpolish_alpha.tga
new file mode 100644
index 0000000000..91af762902
--- /dev/null
+++ b/indra/newview/character/nailpolish_alpha.tga
Binary files differ
diff --git a/indra/newview/character/pants_length_alpha.tga b/indra/newview/character/pants_length_alpha.tga
new file mode 100644
index 0000000000..3c4f21c0f2
--- /dev/null
+++ b/indra/newview/character/pants_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/pants_waist_alpha.tga b/indra/newview/character/pants_waist_alpha.tga
new file mode 100644
index 0000000000..35658c0896
--- /dev/null
+++ b/indra/newview/character/pants_waist_alpha.tga
Binary files differ
diff --git a/indra/newview/character/rosyface_alpha.tga b/indra/newview/character/rosyface_alpha.tga
new file mode 100644
index 0000000000..a0c8513da2
--- /dev/null
+++ b/indra/newview/character/rosyface_alpha.tga
Binary files differ
diff --git a/indra/newview/character/rouge_alpha.tga b/indra/newview/character/rouge_alpha.tga
new file mode 100644
index 0000000000..a0c8513da2
--- /dev/null
+++ b/indra/newview/character/rouge_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_bottom_alpha.tga b/indra/newview/character/shirt_bottom_alpha.tga
new file mode 100644
index 0000000000..7cce03dbe0
--- /dev/null
+++ b/indra/newview/character/shirt_bottom_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_collar_alpha.tga b/indra/newview/character/shirt_collar_alpha.tga
new file mode 100644
index 0000000000..f55f635473
--- /dev/null
+++ b/indra/newview/character/shirt_collar_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_collar_back_alpha.tga b/indra/newview/character/shirt_collar_back_alpha.tga
new file mode 100644
index 0000000000..43a6453107
--- /dev/null
+++ b/indra/newview/character/shirt_collar_back_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shirt_sleeve_alpha.tga b/indra/newview/character/shirt_sleeve_alpha.tga
new file mode 100644
index 0000000000..e3b18f4fc6
--- /dev/null
+++ b/indra/newview/character/shirt_sleeve_alpha.tga
Binary files differ
diff --git a/indra/newview/character/shoe_height_alpha.tga b/indra/newview/character/shoe_height_alpha.tga
new file mode 100644
index 0000000000..d08dd750f3
--- /dev/null
+++ b/indra/newview/character/shoe_height_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_length_alpha.tga b/indra/newview/character/skirt_length_alpha.tga
new file mode 100644
index 0000000000..c86799469d
--- /dev/null
+++ b/indra/newview/character/skirt_length_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_back_alpha.tga b/indra/newview/character/skirt_slit_back_alpha.tga
new file mode 100644
index 0000000000..0e49688b14
--- /dev/null
+++ b/indra/newview/character/skirt_slit_back_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_front_alpha.tga b/indra/newview/character/skirt_slit_front_alpha.tga
new file mode 100644
index 0000000000..888bbf71a1
--- /dev/null
+++ b/indra/newview/character/skirt_slit_front_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_left_alpha.tga b/indra/newview/character/skirt_slit_left_alpha.tga
new file mode 100644
index 0000000000..210feac1ea
--- /dev/null
+++ b/indra/newview/character/skirt_slit_left_alpha.tga
Binary files differ
diff --git a/indra/newview/character/skirt_slit_right_alpha.tga b/indra/newview/character/skirt_slit_right_alpha.tga
new file mode 100644
index 0000000000..ce11c64bf6
--- /dev/null
+++ b/indra/newview/character/skirt_slit_right_alpha.tga
Binary files differ
diff --git a/indra/newview/character/underpants_trial_female.tga b/indra/newview/character/underpants_trial_female.tga
new file mode 100644
index 0000000000..96bf732351
--- /dev/null
+++ b/indra/newview/character/underpants_trial_female.tga
Binary files differ
diff --git a/indra/newview/character/underpants_trial_male.tga b/indra/newview/character/underpants_trial_male.tga
new file mode 100644
index 0000000000..095695ca1c
--- /dev/null
+++ b/indra/newview/character/underpants_trial_male.tga
Binary files differ
diff --git a/indra/newview/character/undershirt_trial_female.tga b/indra/newview/character/undershirt_trial_female.tga
new file mode 100644
index 0000000000..e17a309531
--- /dev/null
+++ b/indra/newview/character/undershirt_trial_female.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_color.tga b/indra/newview/character/upperbody_color.tga
new file mode 100644
index 0000000000..85fcc41142
--- /dev/null
+++ b/indra/newview/character/upperbody_color.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_highlights_alpha.tga b/indra/newview/character/upperbody_highlights_alpha.tga
new file mode 100644
index 0000000000..2d8102b583
--- /dev/null
+++ b/indra/newview/character/upperbody_highlights_alpha.tga
Binary files differ
diff --git a/indra/newview/character/upperbody_shading_alpha.tga b/indra/newview/character/upperbody_shading_alpha.tga
new file mode 100644
index 0000000000..b420506b3e
--- /dev/null
+++ b/indra/newview/character/upperbody_shading_alpha.tga
Binary files differ
diff --git a/indra/newview/character/upperbodyfreckles_alpha.tga b/indra/newview/character/upperbodyfreckles_alpha.tga
new file mode 100644
index 0000000000..76c7ce8849
--- /dev/null
+++ b/indra/newview/character/upperbodyfreckles_alpha.tga
Binary files differ
diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tif
deleted file mode 100644
index 39d89987aa..0000000000
--- a/indra/newview/cursors_mac/UI_CURSOR_TOOLBUY.tif
+++ /dev/null
Binary files differ
diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tif
deleted file mode 100644
index 864c8dee7a..0000000000
--- a/indra/newview/cursors_mac/UI_CURSOR_TOOLOPEN.tif
+++ /dev/null
Binary files differ
diff --git a/indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tif b/indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tif
deleted file mode 100644
index d6d835a90b..0000000000
--- a/indra/newview/cursors_mac/UI_CURSOR_TOOLSIT.tif
+++ /dev/null
Binary files differ
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 92b2768f39..2b5e2369bb 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -48,7 +48,7 @@
#include "llfloatergroupinvite.h"
#include "llfloatergroups.h"
#include "llfloaterreg.h"
-#include "llgivemoney.h"
+#include "llfloaterpay.h"
#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
#include "llimview.h" // for gIMMgr
#include "llmutelist.h"
@@ -306,7 +306,7 @@ bool LLAvatarActions::handlePay(const LLSD& notification, const LLSD& response,
gAgent.clearBusy();
}
- LLFloaterPay::payDirectly(&give_money, avatar_id, /*is_group=*/FALSE);
+ LLFloaterPayUtil::payDirectly(&give_money, avatar_id, /*is_group=*/false);
return false;
}
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 28c124d1c6..2467356018 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -45,7 +45,7 @@ public:
: LLTextSegment(start, end),
mEditor(editor),
mStyle(style),
- mMoreText(more_text)
+ mExpanderLabel(more_text)
{}
/*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const
@@ -61,7 +61,15 @@ public:
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
{
F32 right_x;
- mStyle->getFont()->renderUTF8(mMoreText, start, draw_rect.mRight, draw_rect.mTop, mStyle->getColor(), LLFontGL::RIGHT, LLFontGL::TOP, 0, mStyle->getShadowType(), end - start, draw_rect.getWidth(), &right_x, mEditor.getUseEllipses());
+ mStyle->getFont()->renderUTF8(mExpanderLabel, start,
+ draw_rect.mRight, draw_rect.mTop,
+ mStyle->getColor(),
+ LLFontGL::RIGHT, LLFontGL::TOP,
+ 0,
+ mStyle->getShadowType(),
+ end - start, draw_rect.getWidth(),
+ &right_x,
+ mEditor.getUseEllipses());
return right_x;
}
/*virtual*/ S32 getMaxHeight() const { return llceil(mStyle->getFont()->getLineHeight()); }
@@ -75,14 +83,17 @@ public:
private:
LLTextBase& mEditor;
LLStyleSP mStyle;
- std::string mMoreText;
+ std::string mExpanderLabel;
};
-
+LLExpandableTextBox::LLTextBoxEx::Params::Params()
+: more_label("more_label")
+{}
LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p)
: LLTextBox(p),
- mExpanded(false)
+ mExpanderLabel(p.more_label),
+ mExpanderVisible(false)
{
setIsChrome(TRUE);
@@ -106,6 +117,9 @@ void LLExpandableTextBox::LLTextBoxEx::setValue(const LLSD& value)
{
LLTextBox::setValue(value);
+ // text contents have changed, segments are cleared out
+ // so hide the expander and determine if we need it
+ //mExpanderVisible = false;
if (getTextPixelHeight() > getRect().getHeight())
{
showExpandText();
@@ -119,7 +133,7 @@ void LLExpandableTextBox::LLTextBoxEx::setValue(const LLSD& value)
void LLExpandableTextBox::LLTextBoxEx::showExpandText()
{
- if (!mExpanded)
+ if (!mExpanderVisible)
{
// get fully visible lines
std::pair<S32, S32> visible_lines = getVisibleLines(true);
@@ -129,9 +143,9 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText()
expander_style.font.name.setIfNotProvided(LLFontGL::nameFromFont(expander_style.font));
expander_style.font.style = "UNDERLINE";
expander_style.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
- LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, "More", *this);
+ LLExpanderSegment* expanderp = new LLExpanderSegment(new LLStyle(expander_style), getLineStart(last_line), getLength() + 1, mExpanderLabel, *this);
insertSegment(expanderp);
- mExpanded = true;
+ mExpanderVisible = true;
}
}
@@ -139,14 +153,14 @@ void LLExpandableTextBox::LLTextBoxEx::showExpandText()
//NOTE: obliterates existing styles (including hyperlinks)
void LLExpandableTextBox::LLTextBoxEx::hideExpandText()
{
- if (mExpanded)
+ if (mExpanderVisible)
{
// this will overwrite the expander segment and all text styling with a single style
LLNormalTextSegment* segmentp = new LLNormalTextSegment(
new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this);
insertSegment(segmentp);
- mExpanded = false;
+ mExpanderVisible = false;
}
}
@@ -275,6 +289,9 @@ S32 LLExpandableTextBox::recalculateTextDelta(S32 text_delta)
void LLExpandableTextBox::expandTextBox()
{
+ // hide "more" link, and show full text contents
+ mTextBox->hideExpandText();
+
S32 text_delta = mTextBox->getVerticalTextDelta();
text_delta += mTextBox->getVPad() * 2 + mScroll->getBorderWidth() * 2;
// no need to expand
diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h
index b78a4dc674..d6401e224f 100644
--- a/indra/newview/llexpandabletextbox.h
+++ b/indra/newview/llexpandabletextbox.h
@@ -54,6 +54,8 @@ protected:
public:
struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
{
+ Mandatory<std::string> more_label;
+ Params();
};
// adds or removes "More" link as needed
@@ -76,11 +78,6 @@ protected:
*/
virtual S32 getHPad() { return mHPad; }
- protected:
-
- LLTextBoxEx(const Params& p);
- friend class LLUICtrlFactory;
-
/**
* Shows "More" link
*/
@@ -91,9 +88,15 @@ protected:
*/
void hideExpandText();
+ protected:
+
+ LLTextBoxEx(const Params& p);
+ friend class LLUICtrlFactory;
+
private:
+ std::string mExpanderLabel;
- bool mExpanded;
+ bool mExpanderVisible;
};
public:
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 91b9bcfe72..890d863db7 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -37,20 +37,15 @@
#include "llagent.h"
#include "llfocusmgr.h"
#include "llfloaterreg.h"
-#include "llfloaterinventory.h"
-#include "llfoldervieweventlistener.h"
-#include "llinventorymodel.h"
#include "llviewercontrol.h"
#include "llworld.h"
// Linden libraries
-#include "llbutton.h"
#include "lllineeditor.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llscrolllistcell.h"
#include "lltabcontainer.h"
-#include "lltextbox.h"
#include "lluictrlfactory.h"
#include "message.h"
@@ -117,13 +112,6 @@ BOOL LLFloaterAvatarPicker::postBuild()
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("no_results"));
- LLInventoryPanel* inventory_panel = getChild<LLInventoryPanel>("InventoryPanel");
- inventory_panel->setFilterTypes(0x1 << LLInventoryType::IT_CALLINGCARD);
- inventory_panel->setFollowsAll();
- inventory_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- inventory_panel->openDefaultFolderForType(LLAssetType::AT_CALLINGCARD);
- inventory_panel->setSelectCallback(boost::bind(&LLFloaterAvatarPicker::doCallingCardSelectionChange, this, _1, _2));
-
getChild<LLTabContainer>("ResidentChooserTabs")->setCommitCallback(
boost::bind(&LLFloaterAvatarPicker::onTabChanged, this));
@@ -173,11 +161,7 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata)
{
LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs");
- if(active_panel == self->getChild<LLPanel>("CallingCardsPanel"))
- {
- self->mCallback(self->mSelectedInventoryAvatarNames, self->mSelectedInventoryAvatarIDs, self->mCallbackUserdata);
- }
- else if(active_panel == self->getChild<LLPanel>("SearchPanel"))
+ if(active_panel == self->getChild<LLPanel>("SearchPanel"))
{
std::vector<std::string> avatar_names;
std::vector<LLUUID> avatar_ids;
@@ -192,7 +176,6 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata)
self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
}
}
- self->getChild<LLInventoryPanel>("InventoryPanel")->setSelection(LLUUID::null, FALSE);
self->getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
self->getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
if(self->mCloseOnSelect)
@@ -235,40 +218,6 @@ void LLFloaterAvatarPicker::onList(LLUICtrl* ctrl, void* userdata)
}
}
-// Callback for inventory picker (select from calling cards)
-void LLFloaterAvatarPicker::doCallingCardSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
-{
- bool panel_active = (childGetVisibleTab("ResidentChooserTabs") == getChild<LLPanel>("CallingCardsPanel"));
-
- mSelectedInventoryAvatarIDs.clear();
- mSelectedInventoryAvatarNames.clear();
-
- if (panel_active)
- {
- childSetEnabled("Select", FALSE);
- }
-
- std::deque<LLFolderViewItem*>::const_iterator item_it;
- for (item_it = items.begin(); item_it != items.end(); ++item_it)
- {
- LLFolderViewEventListener* listenerp = (*item_it)->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
- {
- LLInventoryItem* item = gInventory.getItem(listenerp->getUUID());
- if (item)
- {
- mSelectedInventoryAvatarIDs.push_back(item->getCreatorUUID());
- mSelectedInventoryAvatarNames.push_back(listenerp->getName());
- }
- }
- }
-
- if (panel_active)
- {
- childSetEnabled("Select", visibleItemsSelected());
- }
-}
-
void LLFloaterAvatarPicker::populateNearMe()
{
BOOL all_loaded = TRUE;
@@ -336,10 +285,6 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
{
return getChild<LLScrollListCtrl>("SearchResults")->getFirstSelectedIndex() >= 0;
}
- else if(active_panel == getChild<LLPanel>("CallingCardsPanel"))
- {
- return mSelectedInventoryAvatarIDs.size() > 0;
- }
else if(active_panel == getChild<LLPanel>("NearMePanel"))
{
return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
@@ -349,7 +294,7 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
void LLFloaterAvatarPicker::find()
{
- const std::string& text = childGetValue("Edit").asString();
+ std::string text = childGetValue("Edit").asString();
mQueryID.generate();
@@ -375,7 +320,6 @@ void LLFloaterAvatarPicker::find()
void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
{
getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
- getChild<LLInventoryPanel>("InventoryPanel")->setAllowMultiSelect(allow_multiple);
getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
}
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index 63896bef9f..f3b9aefb9c 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -37,7 +37,6 @@
#include <vector>
-
class LLFloaterAvatarPicker : public LLFloater
{
public:
@@ -57,7 +56,6 @@ public:
static void processAvatarPickerReply(class LLMessageSystem* msg, void**);
private:
-
static void editKeystroke(class LLLineEditor* caller, void* user_data);
static void onBtnFind(void* userdata);
@@ -68,8 +66,6 @@ private:
static void onList(class LLUICtrl* ctrl, void* userdata);
void onTabChanged();
- void doCallingCardSelectionChange(const std::deque<class LLFolderViewItem*> &items, BOOL user_action);
-
void populateNearMe();
BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected.
@@ -79,8 +75,6 @@ private:
virtual void draw();
virtual BOOL handleKeyHere(KEY key, MASK mask);
- std::vector<LLUUID> mSelectedInventoryAvatarIDs;
- std::vector<std::string> mSelectedInventoryAvatarNames;
LLUUID mQueryID;
BOOL mResultsReturned;
BOOL mNearMeListComplete;
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index 473d5ce827..9d07362edc 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -74,8 +74,6 @@ BOOL LLFloaterBuy::postBuild()
// mid-session and the saved rect is off-center.
center();
- mCloseSignal.connect(boost::bind(&LLFloaterBuy::onClose, this));
-
return TRUE;
}
@@ -310,7 +308,8 @@ void LLFloaterBuy::onClickCancel()
closeFloater();
}
-void LLFloaterBuy::onClose()
+// virtual
+void LLFloaterBuy::onClose(bool app_quitting)
{
mObjectSelection.clear();
}
diff --git a/indra/newview/llfloaterbuy.h b/indra/newview/llfloaterbuy.h
index 2ec66136b2..ab38e082dc 100644
--- a/indra/newview/llfloaterbuy.h
+++ b/indra/newview/llfloaterbuy.h
@@ -56,6 +56,7 @@ public:
~LLFloaterBuy();
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
static void show(const LLSaleInfo& sale_info);
@@ -70,7 +71,6 @@ protected:
void onClickBuy();
void onClickCancel();
- void onClose();
private:
LLSafeHandle<LLObjectSelection> mObjectSelection;
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index 6b0b5ed5e0..2e0ae3265e 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -50,9 +50,6 @@
LLFloaterHelpBrowser::LLFloaterHelpBrowser(const LLSD& key)
: LLFloater(key)
{
- // really really destroy the help browser when it's closed, it'll be recreated.
- // *TODO: when onClose() is resurrected as a virtual, this bind can go away.
- mCloseSignal.connect(boost::bind(&LLFloaterHelpBrowser::onClose, this));
}
BOOL LLFloaterHelpBrowser::postBuild()
@@ -79,8 +76,10 @@ void LLFloaterHelpBrowser::buildURLHistory()
}
}
-void LLFloaterHelpBrowser::onClose()
+//virtual
+void LLFloaterHelpBrowser::onClose(bool app_quitting)
{
+ // really really destroy the help browser when it's closed, it'll be recreated.
destroy(); // really destroy this dialog on closure, it's relatively heavyweight.
}
diff --git a/indra/newview/llfloaterhelpbrowser.h b/indra/newview/llfloaterhelpbrowser.h
index 14a276b428..b66a67c4d6 100644
--- a/indra/newview/llfloaterhelpbrowser.h
+++ b/indra/newview/llfloaterhelpbrowser.h
@@ -47,7 +47,7 @@ class LLFloaterHelpBrowser :
LLFloaterHelpBrowser(const LLSD& key);
/*virtual*/ BOOL postBuild();
- void onClose();
+ /*virtual*/ void onClose(bool app_quitting);
// inherited from LLViewerMediaObserver
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp
index 9b7f3305e5..5673550fbe 100644
--- a/indra/newview/llfloatermediabrowser.cpp
+++ b/indra/newview/llfloatermediabrowser.cpp
@@ -156,6 +156,8 @@ std::string LLFloaterMediaBrowser::getSupportURL()
{
return getString("support_page_url");
}
+
+//virtual
void LLFloaterMediaBrowser::onClose(bool app_quitting)
{
//setVisible(FALSE);
diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
index 811cc26efb..aa457de2d8 100644
--- a/indra/newview/llfloatermediasettings.cpp
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -52,7 +52,10 @@ LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD& key)
mPanelMediaSettingsGeneral(NULL),
mPanelMediaSettingsSecurity(NULL),
mPanelMediaSettingsPermissions(NULL),
- mWaitingToClose( false )
+ mWaitingToClose( false ),
+ mIdenticalHasMediaInfo( true ),
+ mMultipleMedia(false),
+ mMultipleValidMedia(false)
{
// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_settings.xml");
}
@@ -86,8 +89,6 @@ LLFloaterMediaSettings::~LLFloaterMediaSettings()
//
BOOL LLFloaterMediaSettings::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterMediaSettings::onClose, this));
-
mApplyBtn = getChild<LLButton>("Apply");
mApplyBtn->setClickedCallback(onBtnApply, this);
@@ -153,29 +154,29 @@ void LLFloaterMediaSettings::apply()
}
////////////////////////////////////////////////////////////////////////////////
-void LLFloaterMediaSettings::onClose()
+void LLFloaterMediaSettings::onClose(bool app_quitting)
{
if(mPanelMediaSettingsGeneral)
{
- mPanelMediaSettingsGeneral->onClose();
+ mPanelMediaSettingsGeneral->onClose(app_quitting);
}
LLFloaterReg::hideInstance("whitelist_entry");
}
////////////////////////////////////////////////////////////////////////////////
//static
-void LLFloaterMediaSettings::initValues( const LLSD& media_settings )
+void LLFloaterMediaSettings::initValues( const LLSD& media_settings, bool editable )
{
- sInstance->clearValues();
+ sInstance->clearValues(editable);
// update all panels with values from simulator
sInstance->mPanelMediaSettingsGeneral->
- initValues( sInstance->mPanelMediaSettingsGeneral, media_settings );
+ initValues( sInstance->mPanelMediaSettingsGeneral, media_settings, editable );
sInstance->mPanelMediaSettingsSecurity->
- initValues( sInstance->mPanelMediaSettingsSecurity, media_settings );
+ initValues( sInstance->mPanelMediaSettingsSecurity, media_settings, editable );
sInstance->mPanelMediaSettingsPermissions->
- initValues( sInstance->mPanelMediaSettingsPermissions, media_settings );
+ initValues( sInstance->mPanelMediaSettingsPermissions, media_settings, editable );
}
@@ -195,12 +196,12 @@ void LLFloaterMediaSettings::commitFields()
////////////////////////////////////////////////////////////////////////////////
//static
-void LLFloaterMediaSettings::clearValues()
+void LLFloaterMediaSettings::clearValues( bool editable)
{
// clean up all panels before updating
- sInstance->mPanelMediaSettingsGeneral->clearValues(sInstance->mPanelMediaSettingsGeneral);
- sInstance->mPanelMediaSettingsSecurity->clearValues(sInstance->mPanelMediaSettingsSecurity);
- sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions);
+ sInstance->mPanelMediaSettingsGeneral ->clearValues(sInstance->mPanelMediaSettingsGeneral, editable);
+ sInstance->mPanelMediaSettingsSecurity ->clearValues(sInstance->mPanelMediaSettingsSecurity, editable);
+ sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions, editable);
}
diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h
index b95c590346..e2683039cc 100644
--- a/indra/newview/llfloatermediasettings.h
+++ b/indra/newview/llfloatermediasettings.h
@@ -47,14 +47,20 @@ public:
LLFloaterMediaSettings(const LLSD& key);
~LLFloaterMediaSettings();
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
static LLFloaterMediaSettings* getInstance();
static void apply();
- static void initValues( const LLSD& media_settings );
- static void clearValues();
+ static void initValues( const LLSD& media_settings , bool editable);
+ static void clearValues( bool editable);
void enableOkApplyBtns( bool enable );
LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;};
+ bool mIdenticalHasMediaInfo;
+ bool mMultipleMedia;
+ bool mMultipleValidMedia;
+
protected:
LLButton *mOKBtn;
LLButton *mCancelBtn;
@@ -65,7 +71,7 @@ protected:
LLPanelMediaSettingsSecurity* mPanelMediaSettingsSecurity;
LLPanelMediaSettingsPermissions* mPanelMediaSettingsPermissions;
- void onClose();
+
static void onBtnOK(void*);
static void onBtnCancel(void*);
static void onBtnApply(void*);
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 0df3780ac4..a61cc04941 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -63,7 +63,6 @@ protected:
void refresh();
void draw();
virtual void onOpen(const LLSD& key);
-// virtual void onClose();
void moveToInventory(bool wear);
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
new file mode 100644
index 0000000000..88811d06fe
--- /dev/null
+++ b/indra/newview/llfloaterpay.cpp
@@ -0,0 +1,573 @@
+/**
+ * @file llfloaterpay.cpp
+ * @author Aaron Brashears, Kelly Washington, James Cook
+ * @brief Implementation of the LLFloaterPay class.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterpay.h"
+
+#include "message.h"
+#include "llfloater.h"
+#include "lllslconstants.h" // MAX_PAY_BUTTONS
+#include "lluuid.h"
+
+#include "llagent.h"
+#include "llfloaterreg.h"
+#include "llresmgr.h"
+#include "lltextbox.h"
+#include "lllineeditor.h"
+#include "llmutelist.h"
+#include "llfloaterreporter.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llbutton.h"
+#include "llselectmgr.h"
+#include "lltransactiontypes.h"
+#include "lluictrlfactory.h"
+
+///----------------------------------------------------------------------------
+/// Local function declarations, constants, enums, and typedefs
+///----------------------------------------------------------------------------
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLGiveMoneyInfo
+//
+// A small class used to track callback information
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFloaterPay;
+
+struct LLGiveMoneyInfo
+{
+ LLFloaterPay* mFloater;
+ S32 mAmount;
+ LLGiveMoneyInfo(LLFloaterPay* floater, S32 amount) :
+ mFloater(floater), mAmount(amount){}
+};
+
+///----------------------------------------------------------------------------
+/// Class LLFloaterPay
+///----------------------------------------------------------------------------
+
+class LLFloaterPay : public LLFloater
+{
+public:
+ LLFloaterPay(const LLSD& key);
+ virtual ~LLFloaterPay();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
+ void setCallback(money_callback callback) { mCallback = callback; }
+
+
+ static void payViaObject(money_callback callback, LLSafeHandle<LLObjectSelection> selection);
+
+ static void payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group);
+
+private:
+ static void onCancel(void* data);
+ static void onKeystroke(LLLineEditor* editor, void* data);
+ static void onGive(void* data);
+ void give(S32 amount);
+ static void processPayPriceReply(LLMessageSystem* msg, void **userdata);
+ void onCacheOwnerName(const LLUUID& owner_id,
+ const std::string& firstname,
+ const std::string& lastname,
+ BOOL is_group);
+ void finishPayUI(const LLUUID& target_id, BOOL is_group);
+
+protected:
+ std::vector<LLGiveMoneyInfo*> mCallbackData;
+ money_callback mCallback;
+ LLTextBox* mObjectNameText;
+ LLUUID mTargetUUID;
+ BOOL mTargetIsGroup;
+ BOOL mHaveName;
+
+ LLButton* mQuickPayButton[MAX_PAY_BUTTONS];
+ LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS];
+
+ LLSafeHandle<LLObjectSelection> mObjectSelection;
+
+ static S32 sLastAmount;
+};
+
+
+S32 LLFloaterPay::sLastAmount = 0;
+const S32 MAX_AMOUNT_LENGTH = 10;
+const S32 FASTPAY_BUTTON_WIDTH = 80;
+
+LLFloaterPay::LLFloaterPay(const LLSD& key)
+ : LLFloater(key),
+ mCallbackData(),
+ mCallback(NULL),
+ mObjectNameText(NULL),
+ mTargetUUID(key.asUUID()),
+ mTargetIsGroup(FALSE)
+{
+}
+
+// Destroys the object
+LLFloaterPay::~LLFloaterPay()
+{
+ std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer());
+ // Name callbacks will be automatically disconnected since LLFloater is trackable
+}
+
+BOOL LLFloaterPay::postBuild()
+{
+ S32 i = 0;
+
+ LLGiveMoneyInfo* info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_0);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 1",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 1", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 1");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+ info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_1);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 5",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 5", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 5");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+ info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_2);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 10",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 10", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 10");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+ info = new LLGiveMoneyInfo(this, PAY_BUTTON_DEFAULT_3);
+ mCallbackData.push_back(info);
+
+ childSetAction("fastpay 20",&LLFloaterPay::onGive,info);
+ childSetVisible("fastpay 20", FALSE);
+
+ mQuickPayButton[i] = getChild<LLButton>("fastpay 20");
+ mQuickPayInfo[i] = info;
+ ++i;
+
+
+ childSetVisible("amount text", FALSE);
+
+ std::string last_amount;
+ if(sLastAmount > 0)
+ {
+ last_amount = llformat("%d", sLastAmount);
+ }
+
+ childSetVisible("amount", FALSE);
+
+ getChild<LLLineEditor>("amount")->setKeystrokeCallback(&LLFloaterPay::onKeystroke, this);
+ childSetText("amount", last_amount);
+ childSetPrevalidate("amount", LLLineEditor::prevalidateNonNegativeS32);
+
+ info = new LLGiveMoneyInfo(this, 0);
+ mCallbackData.push_back(info);
+
+ childSetAction("pay btn",&LLFloaterPay::onGive,info);
+ setDefaultBtn("pay btn");
+ childSetVisible("pay btn", FALSE);
+ childSetEnabled("pay btn", (sLastAmount > 0));
+
+ childSetAction("cancel btn",&LLFloaterPay::onCancel,this);
+
+ return TRUE;
+}
+
+// virtual
+void LLFloaterPay::onClose(bool app_quitting)
+{
+ // Deselect the objects
+ mObjectSelection = NULL;
+}
+
+// static
+void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata)
+{
+ LLFloaterPay* self = (LLFloaterPay*)userdata;
+ if (self)
+ {
+ S32 price;
+ LLUUID target;
+
+ msg->getUUIDFast(_PREHASH_ObjectData,_PREHASH_ObjectID,target);
+ if (target != self->mTargetUUID)
+ {
+ // This is a message for a different object's pay info
+ return;
+ }
+
+ msg->getS32Fast(_PREHASH_ObjectData,_PREHASH_DefaultPayPrice,price);
+
+ if (PAY_PRICE_HIDE == price)
+ {
+ self->childSetVisible("amount", FALSE);
+ self->childSetVisible("pay btn", FALSE);
+ self->childSetVisible("amount text", FALSE);
+ }
+ else if (PAY_PRICE_DEFAULT == price)
+ {
+ self->childSetVisible("amount", TRUE);
+ self->childSetVisible("pay btn", TRUE);
+ self->childSetVisible("amount text", TRUE);
+ }
+ else
+ {
+ // PAY_PRICE_HIDE and PAY_PRICE_DEFAULT are negative values
+ // So we take the absolute value here after we have checked for those cases
+
+ self->childSetVisible("amount", TRUE);
+ self->childSetVisible("pay btn", TRUE);
+ self->childSetEnabled("pay btn", TRUE);
+ self->childSetVisible("amount text", TRUE);
+
+ self->childSetText("amount", llformat("%d", llabs(price)));
+ }
+
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_ButtonData);
+ S32 i = 0;
+ if (num_blocks > MAX_PAY_BUTTONS) num_blocks = MAX_PAY_BUTTONS;
+
+ S32 max_pay_amount = 0;
+ S32 padding_required = 0;
+
+ for (i=0;i<num_blocks;++i)
+ {
+ S32 pay_button;
+ msg->getS32Fast(_PREHASH_ButtonData,_PREHASH_PayButton,pay_button,i);
+ if (pay_button > 0)
+ {
+ std::string button_str = "L$";
+ button_str += LLResMgr::getInstance()->getMonetaryString( pay_button );
+
+ self->mQuickPayButton[i]->setLabelSelected(button_str);
+ self->mQuickPayButton[i]->setLabelUnselected(button_str);
+ self->mQuickPayButton[i]->setVisible(TRUE);
+ self->mQuickPayInfo[i]->mAmount = pay_button;
+ self->childSetVisible("fastpay text",TRUE);
+
+ if ( pay_button > max_pay_amount )
+ {
+ max_pay_amount = pay_button;
+ }
+ }
+ else
+ {
+ self->mQuickPayButton[i]->setVisible(FALSE);
+ }
+ }
+
+ // build a string containing the maximum value and calc nerw button width from it.
+ std::string balance_str = "L$";
+ balance_str += LLResMgr::getInstance()->getMonetaryString( max_pay_amount );
+ const LLFontGL* font = LLFontGL::getFontSansSerif();
+ S32 new_button_width = font->getWidth( std::string(balance_str));
+ new_button_width += ( 12 + 12 ); // padding
+
+ // dialong is sized for 2 digit pay amounts - larger pay values need to be scaled
+ const S32 threshold = 100000;
+ if ( max_pay_amount >= threshold )
+ {
+ S32 num_digits_threshold = (S32)log10((double)threshold) + 1;
+ S32 num_digits_max = (S32)log10((double)max_pay_amount) + 1;
+
+ // calculate the extra width required by 2 buttons with max amount and some commas
+ padding_required = ( num_digits_max - num_digits_threshold + ( num_digits_max / 3 ) ) * font->getWidth( std::string("0") );
+ };
+
+ // change in button width
+ S32 button_delta = new_button_width - FASTPAY_BUTTON_WIDTH;
+ if ( button_delta < 0 )
+ button_delta = 0;
+
+ // now we know the maximum amount, we can resize all the buttons to be
+ for (i=0;i<num_blocks;++i)
+ {
+ LLRect r;
+ r = self->mQuickPayButton[i]->getRect();
+
+ // RHS button colum needs to move further because LHS changed too
+ if ( i % 2 )
+ {
+ r.setCenterAndSize( r.getCenterX() + ( button_delta * 3 ) / 2 ,
+ r.getCenterY(),
+ r.getWidth() + button_delta,
+ r.getHeight() );
+ }
+ else
+ {
+ r.setCenterAndSize( r.getCenterX() + button_delta / 2,
+ r.getCenterY(),
+ r.getWidth() + button_delta,
+ r.getHeight() );
+ }
+ self->mQuickPayButton[i]->setRect( r );
+ }
+
+ for (i=num_blocks;i<MAX_PAY_BUTTONS;++i)
+ {
+ self->mQuickPayButton[i]->setVisible(FALSE);
+ }
+
+ self->reshape( self->getRect().getWidth() + padding_required, self->getRect().getHeight(), FALSE );
+ }
+ msg->setHandlerFunc("PayPriceReply",NULL,NULL);
+}
+
+// static
+void LLFloaterPay::payViaObject(money_callback callback, LLSafeHandle<LLObjectSelection> selection)
+{
+ // Object that lead to the selection, may be child
+ LLViewerObject* object = selection->getPrimaryObject();
+ if (!object)
+ return;
+
+ LLFloaterPay *floater = LLFloaterReg::showTypedInstance<LLFloaterPay>("pay_object", LLSD(object->getID()));
+ if (!floater)
+ return;
+
+ floater->setCallback(callback);
+ // Hold onto the selection until we close
+ floater->mObjectSelection = selection;
+
+ LLSelectNode* node = selection->getFirstRootNode();
+ if (!node)
+ {
+ //FIXME: notify user object no longer exists
+ floater->closeFloater();
+ return;
+ }
+
+ LLHost target_region = object->getRegion()->getHost();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RequestPayPrice);
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+ msg->sendReliable(target_region);
+ msg->setHandlerFuncFast(_PREHASH_PayPriceReply, processPayPriceReply,(void **)floater);
+
+ LLUUID owner_id;
+ BOOL is_group = FALSE;
+ node->mPermissions->getOwnership(owner_id, is_group);
+
+ floater->childSetText("object_name_text",node->mName);
+
+ floater->finishPayUI(owner_id, is_group);
+}
+
+void LLFloaterPay::payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group)
+{
+ LLFloaterPay *floater = LLFloaterReg::showTypedInstance<LLFloaterPay>("pay_resident", LLSD(target_id));
+ if (!floater)
+ return;
+
+ floater->setCallback(callback);
+ floater->mObjectSelection = NULL;
+
+ floater->childSetVisible("amount", TRUE);
+ floater->childSetVisible("pay btn", TRUE);
+ floater->childSetVisible("amount text", TRUE);
+
+ floater->childSetVisible("fastpay text",TRUE);
+ for(S32 i=0;i<MAX_PAY_BUTTONS;++i)
+ {
+ floater->mQuickPayButton[i]->setVisible(TRUE);
+ }
+
+ floater->finishPayUI(target_id, is_group);
+}
+
+void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group)
+{
+ gCacheName->get(target_id, is_group, boost::bind(&LLFloaterPay::onCacheOwnerName, this, _1, _2, _3, _4));
+
+ // Make sure the amount field has focus
+
+ childSetFocus("amount", TRUE);
+
+ LLLineEditor* amount = getChild<LLLineEditor>("amount");
+ amount->selectAll();
+ mTargetIsGroup = is_group;
+}
+
+void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id,
+ const std::string& firstname,
+ const std::string& lastname,
+ BOOL is_group)
+{
+ if (is_group)
+ {
+ childSetVisible("payee_group",true);
+ childSetVisible("payee_resident",false);
+ }
+ else
+ {
+ childSetVisible("payee_group",false);
+ childSetVisible("payee_resident",true);
+ }
+
+ childSetTextArg("payee_name", "[FIRST]", firstname);
+ childSetTextArg("payee_name", "[LAST]", lastname);
+}
+
+// static
+void LLFloaterPay::onCancel(void* data)
+{
+ LLFloaterPay* self = reinterpret_cast<LLFloaterPay*>(data);
+ if(self)
+ {
+ self->closeFloater();
+ }
+}
+
+// static
+void LLFloaterPay::onKeystroke(LLLineEditor*, void* data)
+{
+ LLFloaterPay* self = reinterpret_cast<LLFloaterPay*>(data);
+ if(self)
+ {
+ // enable the Pay button when amount is non-empty and positive, disable otherwise
+ std::string amtstr = self->childGetText("amount");
+ self->childSetEnabled("pay btn", !amtstr.empty() && atoi(amtstr.c_str()) > 0);
+ }
+}
+
+// static
+void LLFloaterPay::onGive(void* data)
+{
+ LLGiveMoneyInfo* info = reinterpret_cast<LLGiveMoneyInfo*>(data);
+ if(info && info->mFloater)
+ {
+ info->mFloater->give(info->mAmount);
+ info->mFloater->closeFloater();
+ }
+}
+
+void LLFloaterPay::give(S32 amount)
+{
+ if(mCallback)
+ {
+ // if the amount is 0, that menas that we should use the
+ // text field.
+ if(amount == 0)
+ {
+ amount = atoi(childGetText("amount").c_str());
+ }
+ sLastAmount = amount;
+
+ // Try to pay an object.
+ if (mObjectSelection.notNull())
+ {
+ LLViewerObject* dest_object = gObjectList.findObject(mTargetUUID);
+ if(dest_object)
+ {
+ LLViewerRegion* region = dest_object->getRegion();
+ if (region)
+ {
+ // Find the name of the root object
+ LLSelectNode* node = mObjectSelection->getFirstRootNode();
+ std::string object_name;
+ if (node)
+ {
+ object_name = node->mName;
+ }
+ S32 tx_type = TRANS_PAY_OBJECT;
+ if(dest_object->isAvatar()) tx_type = TRANS_GIFT;
+ mCallback(mTargetUUID, region, amount, FALSE, tx_type, object_name);
+ mObjectSelection = NULL;
+
+ // request the object owner in order to check if the owner needs to be unmuted
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU32Fast(_PREHASH_RequestFlags, OBJECT_PAY_REQUEST );
+ msg->addUUIDFast(_PREHASH_ObjectID, mTargetUUID);
+ msg->sendReliable( region->getHost() );
+ }
+ }
+ }
+ else
+ {
+ // just transfer the L$
+ mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, LLStringUtil::null);
+
+ // check if the payee needs to be unmuted
+ LLMuteList::getInstance()->autoRemove(mTargetUUID, LLMuteList::AR_MONEY);
+ }
+ }
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Namespace LLFloaterPayUtil
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void LLFloaterPayUtil::registerFloater()
+{
+ // Sneaky, use same code but different XML for dialogs
+ LLFloaterReg::add("pay_resident", "floater_pay.xml",
+ &LLFloaterReg::build<LLFloaterPay>);
+ LLFloaterReg::add("pay_object", "floater_pay_object.xml",
+ &LLFloaterReg::build<LLFloaterPay>);
+}
+
+void LLFloaterPayUtil::payViaObject(money_callback callback,
+ LLSafeHandle<LLObjectSelection> selection)
+{
+ LLFloaterPay::payViaObject(callback, selection);
+}
+
+void LLFloaterPayUtil::payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group)
+{
+ LLFloaterPay::payDirectly(callback, target_id, is_group);
+}
diff --git a/indra/newview/llfloaterpay.h b/indra/newview/llfloaterpay.h
new file mode 100644
index 0000000000..161ed78acb
--- /dev/null
+++ b/indra/newview/llfloaterpay.h
@@ -0,0 +1,61 @@
+/**
+ * @file llfloaterpay.h
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-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 LLFLOATERPAY_H
+#define LLFLOATERPAY_H
+
+#include "llsafehandle.h"
+
+class LLObjectSelection;
+class LLUUID;
+class LLViewerRegion;
+
+typedef void (*money_callback)(const LLUUID&, LLViewerRegion*,S32,BOOL,S32,const std::string&);
+
+namespace LLFloaterPayUtil
+{
+ /// Register with LLFloaterReg
+ void registerFloater();
+
+ /// Pay into an in-world object, which will trigger scripts and eventually
+ /// transfer the L$ to the resident or group that owns the object.
+ /// Objects must be selected. Recipient (primary) object may be a child.
+ void payViaObject(money_callback callback,
+ LLSafeHandle<LLObjectSelection> selection);
+
+ /// Pay an avatar or group directly, not via an object in the world.
+ /// Scripts are not notified, L$ can be direcly transferred.
+ void payDirectly(money_callback callback,
+ const LLUUID& target_id,
+ bool is_group);
+}
+
+#endif // LLFLOATERPAY_H
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 57c043a1e0..dbee9ea309 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -357,8 +357,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
BOOL LLFloaterPreference::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterPreference::onClose, this));
-
LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core");
if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
tabcontainer->selectFirstTab();
@@ -566,7 +564,8 @@ void LLFloaterPreference::setHardwareDefaults()
refreshEnabledGraphics();
}
-void LLFloaterPreference::onClose()
+//virtual
+void LLFloaterPreference::onClose(bool app_quitting)
{
gSavedSettings.setS32("LastPrefTab", getChild<LLTabContainer>("pref core")->getCurrentPanelIndex());
LLPanelLogin::setAlwaysRefresh(false);
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index ce31abcd9e..34723b8c7e 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -70,8 +70,9 @@ public:
void apply();
void cancel();
/*virtual*/ void draw();
- virtual BOOL postBuild();
- virtual void onOpen(const LLSD& key);
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
// static data update, called from message handler
static void updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email);
@@ -79,10 +80,7 @@ public:
// refresh all the graphics preferences menus
static void refreshEnabledGraphics();
-protected:
-
- void onClose();
-
+protected:
void onBtnOK();
void onBtnCancel();
void onBtnApply();
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 9e203c4269..43d31aa30a 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -58,7 +58,7 @@ class LLFloaterSellLandUI
public:
LLFloaterSellLandUI(const LLSD& key);
virtual ~LLFloaterSellLandUI();
- void onClose();
+ /*virtual*/ void onClose(bool app_quitting);
private:
class SelectionObserver : public LLParcelObserver
@@ -131,7 +131,6 @@ LLFloaterSellLandUI::LLFloaterSellLandUI(const LLSD& key)
mRegion(0)
{
LLViewerParcelMgr::getInstance()->addObserver(&mParcelSelectionObserver);
- mCloseSignal.connect(boost::bind(&LLFloaterSellLandUI::onClose, this));
}
LLFloaterSellLandUI::~LLFloaterSellLandUI()
@@ -140,7 +139,7 @@ LLFloaterSellLandUI::~LLFloaterSellLandUI()
}
// Because we are single_instance, we are not destroyed on close.
-void LLFloaterSellLandUI::onClose()
+void LLFloaterSellLandUI::onClose(bool app_quitting)
{
// Must release parcel selection to allow land to deselect, see EXT-803
mParcelSelection = NULL;
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index c08996cc26..320647ff1a 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -77,12 +77,14 @@
#include "lltoolpipette.h"
#include "lltoolplacer.h"
#include "lltoolselectland.h"
+#include "lltrans.h"
#include "llui.h"
+#include "llviewercontrol.h"
+#include "llviewerjoystick.h"
+#include "llviewerregion.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
-#include "llviewercontrol.h"
-#include "llviewerjoystick.h"
#include "lluictrlfactory.h"
// Globals
@@ -198,9 +200,7 @@ LLPCode toolData[]={
LL_PCODE_LEGACY_GRASS};
BOOL LLFloaterTools::postBuild()
-{
- mCloseSignal.connect(boost::bind(&LLFloaterTools::onClose, this));
-
+{
// Hide until tool selected
setVisible(FALSE);
@@ -724,7 +724,8 @@ void LLFloaterTools::onOpen(const LLSD& key)
//gMenuBarView->setItemVisible("BuildTools", TRUE);
}
-void LLFloaterTools::onClose()
+// virtual
+void LLFloaterTools::onClose(bool app_quitting)
{
mTab->setVisible(FALSE);
@@ -980,27 +981,86 @@ void LLFloaterTools::onFocusReceived()
void LLFloaterTools::refreshMedia()
{
getMediaState();
- LLFloaterMediaSettings::getInstance();
- LLFloaterMediaSettings::initValues(mMediaSettings );
}
-
+bool LLFloaterTools::selectedMediaEditable()
+{
+ U32 owner_mask_on;
+ U32 owner_mask_off;
+ U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_OWNER,
+ &owner_mask_on, &owner_mask_off );
+ U32 group_mask_on;
+ U32 group_mask_off;
+ U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_GROUP,
+ &group_mask_on, &group_mask_off );
+ U32 everyone_mask_on;
+ U32 everyone_mask_off;
+ S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_EVERYONE,
+ &everyone_mask_on, &everyone_mask_off );
+
+ bool selected_Media_editable = false;
+
+ // if perms we got back are valid
+ if ( valid_owner_perms &&
+ valid_group_perms &&
+ valid_everyone_perms )
+ {
+
+ if ( ( owner_mask_on & PERM_MODIFY ) ||
+ ( group_mask_on & PERM_MODIFY ) ||
+ ( group_mask_on & PERM_MODIFY ) )
+ {
+ selected_Media_editable = true;
+ }
+ else
+ // user is NOT allowed to press the RESET button
+ {
+ selected_Media_editable = false;
+ };
+ };
+
+ return selected_Media_editable;
+}
void LLFloaterTools::getMediaState()
{
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
+ LLViewerObject* first_object = selected_objects->getFirstObject();
+ LLLineEditor* media_info = getChild<LLLineEditor>("media_info");
+
+ if( !(first_object
+ && first_object->getPCode() == LL_PCODE_VOLUME
+ &&first_object->permModify()
+ ))
+ {
+ childSetEnabled("media_tex", FALSE);
+ childSetEnabled("add_media", FALSE);
+ childSetEnabled("delete_media", FALSE);
+ childSetEnabled("edit_media", FALSE);
+ childSetEnabled("media_info", FALSE);
+ media_info->setEnabled(FALSE);
+ media_info->clear();
+ clearMediaSettings();
+ return;
+ }
- if( !objectp )
+ std::string url = first_object->getRegion()->getCapability("ObjectMedia");
+ bool has_media_capability = (!url.empty());
+
+ if(!has_media_capability)
{
childSetEnabled("media_tex", FALSE);
childSetEnabled("add_media", FALSE);
childSetEnabled("delete_media", FALSE);
childSetEnabled("edit_media", FALSE);
- updateMediaSettings();
+ childSetEnabled("media_info", FALSE);
+ media_info->setEnabled(FALSE);
+ media_info->clear();
+ clearMediaSettings();
return;
}
- bool editable = gAgent.isGodlike() || (objectp->permModify() && objectp->getPCode() == LL_PCODE_VOLUME);
+ bool editable = (first_object->permModify());// && selectedMediaEditable());
// Media settings
U8 has_media = (U8)0;
@@ -1011,24 +1071,104 @@ void LLFloaterTools::getMediaState()
return (object->getTE(face)->getMediaTexGen());
}
} func;
- bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, has_media );
+ // check if all faces have media(or, all dont have media)
+ LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, has_media );
+ bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA);
+
+ const LLMediaEntry default_media_data;
+
+ struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry>
+ {
+ functor_getter_media_data(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
+ LLMediaEntry get( LLViewerObject* object, S32 face )
+ {
+ if ( object )
+ if ( object->getTE(face) )
+ if ( object->getTE(face)->getMediaData() )
+ return *(object->getTE(face)->getMediaData());
+ return mMediaEntry;
+ };
+
+ const LLMediaEntry& mMediaEntry;
+
+ } func_media_data(default_media_data);
+
+ LLMediaEntry media_data_get;
+ LLFloaterMediaSettings::getInstance()->mMultipleMedia = !(selected_objects->getSelectedTEValue( &func_media_data, media_data_get ));
+
+ std::string multi_media_info_str = LLTrans::getString("Multiple Media");
+ std::string media_title = "";
// update UI depending on whether "object" (prim or face) has media
// and whether or not you are allowed to edit it.
- bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA);
- childSetEnabled("media_tex", bool_has_media & editable);
- childSetEnabled( "edit_media", bool_has_media & editable );
- childSetEnabled( "delete_media", bool_has_media & editable );
- childSetEnabled( "add_media", ( ! bool_has_media ) & editable );
+
+ // IF all the faces have media (or all dont have media)
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ // TODO: get media title and set it.
+ media_info->clear();
+ // if identical is set, all faces are same (whether all empty or has the same media)
+ if(!(LLFloaterMediaSettings::getInstance()->mMultipleMedia) )
+ {
+ // Media data is valid
+ if(media_data_get!=default_media_data)
+ {
+ //TODO: get Meida title
+ //media_title = media_data_get->getTile();
+ //LLFloaterMediaSettings::getInstance()->mIdenticalValidMedia = true;
+ media_title = media_data_get.getHomeURL();
+ }
+ // else all faces might be empty.
+
+
+ }
+ else // there' re Different Medias' been set on on the faces.
+ {
+ media_title = multi_media_info_str;
+ }
+
+ childSetEnabled("media_tex", bool_has_media & editable);
+ childSetEnabled( "edit_media", bool_has_media & editable );
+ childSetEnabled( "delete_media", bool_has_media & editable );
+ childSetEnabled( "add_media", ( ! bool_has_media ) & editable );
+ media_info->setEnabled(bool_has_media & editable);
+ // TODO: display a list of all media on the face - use 'identical' flag
+ }
+ else // not all face has media but at least one does.
+ {
+ // seleted faces have not identical value
+ LLFloaterMediaSettings::getInstance()->mMultipleValidMedia = selected_objects->isMultipleTEValue(&func_media_data, default_media_data );
+
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ media_title = multi_media_info_str;
+ }
+ else
+ {
+ // Media data is valid
+ if(media_data_get!=default_media_data)
+ {
+ //TODO: get Meida title
+ //media_title = media_data_get->getTile();
+ media_title = media_data_get.getHomeURL();
+ }
+
+ }
+
+ media_info->setEnabled(TRUE);
+ media_info->setTentative(true);
+ childSetEnabled("media_tex", TRUE);
+ childSetEnabled( "edit_media", TRUE);
+ childSetEnabled( "delete_media", TRUE);
+ childSetEnabled( "add_media", FALSE );
+ }
+ media_info->setText(media_title);
// load values for media settings
updateMediaSettings();
- // if identical is set, all faces are same
- if ( identical )
- {
- // TODO: display a list of all media on the face - use 'identical' flag
- };
+ LLFloaterMediaSettings::initValues(mMediaSettings, editable );
}
@@ -1104,6 +1244,12 @@ bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& re
return false;
}
+void LLFloaterTools::clearMediaSettings()
+{
+ LLFloaterMediaSettings::getInstance();
+ LLFloaterMediaSettings::clearValues(false);
+
+}
//////////////////////////////////////////////////////////////////////////////
//
void LLFloaterTools::updateMediaSettings()
@@ -1116,23 +1262,26 @@ void LLFloaterTools::updateMediaSettings()
LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
// TODO: (CP) refactor this using something clever or boost or both !!
- LLMediaEntry default_media_data;
+ const LLMediaEntry default_media_data;
// controls
U8 value_u8 = default_media_data.getControls();
struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 >
{
+ functor_getter_controls(const LLMediaEntry &entry) : mMediaEntry(entry) {}
+
U8 get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getControls();
- LLMediaEntry default_media_data;
- return default_media_data.getControls();
+ return mMediaEntry.getControls();
};
- } func_controls;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_controls(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_controls, value_u8 );
base_key = std::string( LLMediaEntry::CONTROLS_KEY );
mMediaSettings[ base_key ] = value_u8;
@@ -1142,17 +1291,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = default_media_data.getFirstClickInteract();
struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_first_click(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getFirstClickInteract();
- LLMediaEntry default_media_data;
- return default_media_data.getFirstClickInteract();
+ return mMediaEntry.getFirstClickInteract();
};
- } func_first_click;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_first_click(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_first_click, value_bool );
base_key = std::string( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1162,38 +1314,43 @@ void LLFloaterTools::updateMediaSettings()
value_str = default_media_data.getHomeURL();
struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string >
{
+ functor_getter_home_url(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
std::string get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getHomeURL();
- LLMediaEntry default_media_data;
- return default_media_data.getHomeURL();
+ return mMediaEntry.getHomeURL();
};
- } func_home_url;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_home_url(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_home_url, value_str );
base_key = std::string( LLMediaEntry::HOME_URL_KEY );
mMediaSettings[ base_key ] = value_str;
mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
- llwarns<<"Angela debug : home url string == "<<value_str<<llendl;
// Current URL
value_str = default_media_data.getCurrentURL();
struct functor_getter_current_url : public LLSelectedTEGetFunctor< std::string >
{
- std::string get( LLViewerObject* object, S32 face )
+ functor_getter_current_url(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
+ std::string get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getCurrentURL();
- LLMediaEntry default_media_data;
- return default_media_data.getCurrentURL();
+ return mMediaEntry.getCurrentURL();
};
- } func_current_url;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_current_url(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_current_url, value_str );
base_key = std::string( LLMediaEntry::CURRENT_URL_KEY );
mMediaSettings[ base_key ] = value_str;
@@ -1203,17 +1360,21 @@ void LLFloaterTools::updateMediaSettings()
value_bool = default_media_data.getAutoZoom();
struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool >
{
+
+ functor_getter_auto_zoom(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getAutoZoom();
- LLMediaEntry default_media_data;
- return default_media_data.getAutoZoom();
+ return mMediaEntry.getAutoZoom();
};
- } func_auto_zoom;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_auto_zoom(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_auto_zoom, value_bool );
base_key = std::string( LLMediaEntry::AUTO_ZOOM_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1223,37 +1384,44 @@ void LLFloaterTools::updateMediaSettings()
value_bool = default_media_data.getAutoPlay();
struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_auto_play(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getAutoPlay();
- LLMediaEntry default_media_data;
- return default_media_data.getAutoPlay();
+ return mMediaEntry.getAutoPlay();
};
- } func_auto_play;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_auto_play(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_auto_play, value_bool );
base_key = std::string( LLMediaEntry::AUTO_PLAY_KEY );
mMediaSettings[ base_key ] = value_bool;
mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical;
+
// Auto scale
value_bool = default_media_data.getAutoScale();
struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_auto_scale(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getAutoScale();
- LLMediaEntry default_media_data;
- return default_media_data.getAutoScale();;
+ return mMediaEntry.getAutoScale();;
};
- } func_auto_scale;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_auto_scale(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_auto_scale, value_bool );
base_key = std::string( LLMediaEntry::AUTO_SCALE_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1263,17 +1431,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = default_media_data.getAutoLoop();
struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_auto_loop(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getAutoLoop();
- LLMediaEntry default_media_data;
- return default_media_data.getAutoLoop();
+ return mMediaEntry.getAutoLoop();
};
- } func_auto_loop;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_auto_loop(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_auto_loop, value_bool );
base_key = std::string( LLMediaEntry::AUTO_LOOP_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1283,17 +1454,20 @@ void LLFloaterTools::updateMediaSettings()
value_int = default_media_data.getWidthPixels();
struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int >
{
+ functor_getter_width_pixels(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
int get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getWidthPixels();
- LLMediaEntry default_media_data;
- return default_media_data.getWidthPixels();
+ return mMediaEntry.getWidthPixels();
};
- } func_width_pixels;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_width_pixels(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_width_pixels, value_int );
base_key = std::string( LLMediaEntry::WIDTH_PIXELS_KEY );
mMediaSettings[ base_key ] = value_int;
@@ -1303,17 +1477,20 @@ void LLFloaterTools::updateMediaSettings()
value_int = default_media_data.getHeightPixels();
struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int >
{
- int get( LLViewerObject* object, S32 face )
+ functor_getter_height_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ int get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getHeightPixels();
- LLMediaEntry default_media_data;
- return default_media_data.getHeightPixels();
+ return mMediaEntry.getHeightPixels();
};
- } func_height_pixels;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_height_pixels(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_height_pixels, value_int );
base_key = std::string( LLMediaEntry::HEIGHT_PIXELS_KEY );
mMediaSettings[ base_key ] = value_int;
@@ -1323,17 +1500,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = default_media_data.getAltImageEnable();
struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool >
{
- bool get( LLViewerObject* object, S32 face )
+ functor_getter_enable_alt_image(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
+ bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getAltImageEnable();
- LLMediaEntry default_media_data;
- return default_media_data.getAltImageEnable();
+ return mMediaEntry.getAltImageEnable();
};
- } func_enable_alt_image;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_enable_alt_image(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_enable_alt_image, value_bool );
base_key = std::string( LLMediaEntry::ALT_IMAGE_ENABLE_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1343,17 +1523,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER );
struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool >
{
- bool get( LLViewerObject* object, S32 face )
+ functor_getter_perms_owner_interact(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
+ bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER));
- LLMediaEntry default_media_data;
- return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER );
+ return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_OWNER );
};
- } func_perms_owner_interact;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_perms_owner_interact(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_perms_owner_interact, value_bool );
base_key = std::string( LLPanelContents::PERMS_OWNER_INTERACT_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1363,17 +1546,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER );
struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_perms_owner_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER));
- LLMediaEntry default_media_data;
- return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER );
+ return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_OWNER );
};
- } func_perms_owner_control;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_perms_owner_control(default_media_data);
identical = selected_objects ->getSelectedTEValue( &func_perms_owner_control, value_bool );
base_key = std::string( LLPanelContents::PERMS_OWNER_CONTROL_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1383,17 +1569,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP );
struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_perms_group_interact(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP));
- LLMediaEntry default_media_data;
- return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP );
+ return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_GROUP );
};
- } func_perms_group_interact;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_perms_group_interact(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_perms_group_interact, value_bool );
base_key = std::string( LLPanelContents::PERMS_GROUP_INTERACT_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1403,17 +1592,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP );
struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_perms_group_control(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP));
- LLMediaEntry default_media_data;
- return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP );
+ return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_GROUP );
};
- } func_perms_group_control;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_perms_group_control(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_perms_group_control, value_bool );
base_key = std::string( LLPanelContents::PERMS_GROUP_CONTROL_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1423,17 +1615,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE );
struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_perms_anyone_interact(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE));
- LLMediaEntry default_media_data;
- return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE );
+ return 0 != ( mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_ANYONE );
};
- } func_perms_anyone_interact;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_perms_anyone_interact(default_media_data);
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_perms_anyone_interact, value_bool );
base_key = std::string( LLPanelContents::PERMS_ANYONE_INTERACT_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1443,17 +1638,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE );
struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_perms_anyone_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE));
- LLMediaEntry default_media_data;
- return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE );
+ return 0 != ( mMediaEntry.getPermsControl() & LLMediaEntry::PERM_ANYONE );
};
- } func_perms_anyone_control;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_perms_anyone_control(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_perms_anyone_control, value_bool );
base_key = std::string( LLPanelContents::PERMS_ANYONE_CONTROL_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1463,17 +1661,20 @@ void LLFloaterTools::updateMediaSettings()
value_bool = default_media_data.getWhiteListEnable();
struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool >
{
+ functor_getter_whitelist_enable(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
bool get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getWhiteListEnable();
- LLMediaEntry default_media_data;
- return default_media_data.getWhiteListEnable();
+ return mMediaEntry.getWhiteListEnable();
};
- } func_whitelist_enable;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_whitelist_enable(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_whitelist_enable, value_bool );
base_key = std::string( LLMediaEntry::WHITELIST_ENABLE_KEY );
mMediaSettings[ base_key ] = value_bool;
@@ -1483,17 +1684,20 @@ void LLFloaterTools::updateMediaSettings()
std::vector<std::string> value_vector_str = default_media_data.getWhiteList();
struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector<std::string> >
{
+ functor_getter_whitelist_urls(const LLMediaEntry& entry): mMediaEntry(entry) {}
+
std::vector<std::string> get( LLViewerObject* object, S32 face )
{
if ( object )
if ( object->getTE(face) )
if ( object->getTE(face)->getMediaData() )
return object->getTE(face)->getMediaData()->getWhiteList();
- LLMediaEntry default_media_data;
- return default_media_data.getWhiteList();
+ return mMediaEntry.getWhiteList();
};
- } func_whitelist_urls;
+ const LLMediaEntry & mMediaEntry;
+
+ } func_whitelist_urls(default_media_data);
identical = selected_objects->getSelectedTEValue( &func_whitelist_urls, value_vector_str );
base_key = std::string( LLMediaEntry::WHITELIST_KEY );
mMediaSettings[ base_key ].clear();
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 008c9677ed..ffccf93943 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -74,6 +74,7 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ BOOL canClose();
+ /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void draw();
/*virtual*/ void onFocusReceived();
@@ -105,10 +106,10 @@ public:
void onClickBtnDeleteMedia();
void onClickBtnAddMedia();
void onClickBtnEditMedia();
-
+ void clearMediaSettings();
+ bool selectedMediaEditable();
private:
- void onClose();
void refresh();
void refreshMedia();
void getMediaState();
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 266252efea..98ca33c9cc 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -283,8 +283,6 @@ LLFloaterUIPreview::~LLFloaterUIPreview()
// Perform post-build setup (defined in superclass)
BOOL LLFloaterUIPreview::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterUIPreview::onClose, this, _2));
-
LLPanel* main_panel_tmp = getChild<LLPanel>("main_panel"); // get a pointer to the main panel in order to...
mFileList = main_panel_tmp->getChild<LLScrollListCtrl>("name_list"); // save pointer to file list
// Double-click opens the floater, for convenience
@@ -442,9 +440,9 @@ void LLFloaterUIPreview::onClickExportSchema()
// Close click handler -- delete my displayed floater if it exists
-void LLFloaterUIPreview::onClose(const LLSD& app_quitting)
+void LLFloaterUIPreview::onClose(bool app_quitting)
{
- if(!app_quitting.asBoolean() && mDisplayedFloater)
+ if(!app_quitting && mDisplayedFloater)
{
onClickCloseDisplayedFloater(PRIMARY_FLOATER);
onClickCloseDisplayedFloater(SECONDARY_FLOATER);
diff --git a/indra/newview/llfloateruipreview.h b/indra/newview/llfloateruipreview.h
index b8c378e2e9..2a98c90727 100644
--- a/indra/newview/llfloateruipreview.h
+++ b/indra/newview/llfloateruipreview.h
@@ -96,7 +96,9 @@ public:
std::string getLocStr(S32 ID); // fetches the localization string based on what is selected in the drop-down menu
void displayFloater(BOOL click, S32 ID, bool save = false); // needs to be public so live file can call it when it finds an update
- BOOL postBuild(); // post-build setup (called by superclass' constructor)
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
+
void refreshList(); // refresh list (empty it out and fill it up from scratch)
void addFloaterEntry(const std::string& path); // add a single file's entry to the list of floaters
@@ -116,9 +118,6 @@ public:
typedef std::map<std::string, std::pair<StringListPtr,StringListPtr> > DiffMap;
DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors
-protected:
- void onClose(const LLSD& app_quitting);
-
private:
// XUI elements for this floater
LLScrollListCtrl* mFileList; // scroll list control for file list
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index a7658d90e9..b64257b11d 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -293,11 +293,11 @@ LLFloaterVoiceDeviceSettings::LLFloaterVoiceDeviceSettings(const LLSD& seed)
}
BOOL LLFloaterVoiceDeviceSettings::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterVoiceDeviceSettings::onClose, this));
-
center();
return TRUE;
}
+
+// virtual
void LLFloaterVoiceDeviceSettings::onOpen(const LLSD& key)
{
if(mDevicePanel)
@@ -306,7 +306,8 @@ void LLFloaterVoiceDeviceSettings::onOpen(const LLSD& key)
}
}
-void LLFloaterVoiceDeviceSettings::onClose()
+// virtual
+void LLFloaterVoiceDeviceSettings::onClose(bool app_settings)
{
if(mDevicePanel)
{
diff --git a/indra/newview/llfloatervoicedevicesettings.h b/indra/newview/llfloatervoicedevicesettings.h
index 2565bfad2b..f1603dc414 100644
--- a/indra/newview/llfloatervoicedevicesettings.h
+++ b/indra/newview/llfloatervoicedevicesettings.h
@@ -68,8 +68,9 @@ class LLFloaterVoiceDeviceSettings : public LLFloater
public:
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_settings);
/*virtual*/ void draw();
void apply();
void cancel();
@@ -78,9 +79,7 @@ private:
protected:
static void* createPanelVoiceDeviceSettings(void* user_data);
-
- void onClose();
-
+
protected:
LLPanelVoiceDeviceSettings* mDevicePanel;
};
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 098a5197df..d653d44f8c 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -183,8 +183,6 @@ void* LLFloaterWorldMap::createWorldMapView(void* data)
BOOL LLFloaterWorldMap::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterWorldMap::onClose, this));
-
mTabs = getChild<LLTabContainer>("maptab");
if (!mTabs) return FALSE;
@@ -255,7 +253,8 @@ LLFloaterWorldMap* LLFloaterWorldMap::getInstance()
return LLFloaterReg::getTypedInstance<LLFloaterWorldMap>("world_map");
}
-void LLFloaterWorldMap::onClose()
+// virtual
+void LLFloaterWorldMap::onClose(bool app_quitting)
{
// While we're not visible, discard the overlay images we're using
LLWorldMap::getInstance()->clearImageRefs();
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index f117ea05af..6d5b7543d4 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -65,6 +65,7 @@ public:
BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
static void reloadIcons(void*);
@@ -111,9 +112,7 @@ public:
// teleport to the tracked item, if there is one
void teleport();
-protected:
- void onClose();
-
+protected:
void onGoHome();
void onLandmarkComboPrearrange();
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index dde36ac25b..3e449e2c82 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -78,12 +78,11 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
}
}
- mCloseSignal.connect(boost::bind(&LLIMFloater::onClose, this));
-
LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
}
-void LLIMFloater::onClose()
+// virtual
+void LLIMFloater::onClose(bool app_quitting)
{
LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID);
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index a183212f04..f85a941be3 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -56,6 +56,7 @@ public:
/*virtual*/ void setVisible(BOOL visible);
// LLFloater overrides
+ /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
// override LLFloater's minimization according to EXT-1216
/*virtual*/ void setMinimized(BOOL minimize);
@@ -79,10 +80,6 @@ public:
// called when docked floater's position has been set by chiclet
void setPositioned(bool b) { mPositioned = b; };
- // handler for a CLOSE signal
- void onClose();
-
-
private:
static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 89a885090c..4435bba0ed 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -1052,8 +1052,6 @@ LLFloaterIMPanel::~LLFloaterIMPanel()
BOOL LLFloaterIMPanel::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterIMPanel::onClose, this));
-
mVisibleSignal.connect(boost::bind(&LLFloaterIMPanel::onVisibilityChange, this, _2));
mInputEditor = getChild<LLLineEditor>("chat_editor");
@@ -1610,7 +1608,8 @@ void LLFloaterIMPanel::onInputEditorKeystroke(LLLineEditor* caller, void* userda
}
}
-void LLFloaterIMPanel::onClose()
+// virtual
+void LLFloaterIMPanel::onClose(bool app_quitting)
{
setTyping(FALSE);
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index fb9b28ad16..57379b2c0d 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -198,7 +198,7 @@ public:
// Check typing timeout timer.
/*virtual*/ void draw();
- void onClose();
+ /*virtual*/ void onClose(bool app_quitting);
void onVisibilityChange(const LLSD& new_visibility);
// add target ids to the session.
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 9b75c15597..4046c893c1 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -51,6 +51,7 @@
#include "llcontrol.h" // LLCachedControl
#include "llfloater.h"
#include "llfloaterreg.h"
+#include "llmenubutton.h"
#include "lltooltip.h" // positionViewNearMouse()
#include "lluictrl.h"
@@ -80,6 +81,9 @@ public:
// Because floater is single instance, need to re-parse data on each spawn
// (for example, inspector about same avatar but in different position)
/*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ // When closing they should close their gear menu
+ /*virtual*/ void onClose(bool app_quitting);
// Inspectors close themselves when they lose focus
/*virtual*/ void onFocusLost();
@@ -288,6 +292,12 @@ void LLInspectAvatar::onOpen(const LLSD& data)
updateVolumeSlider();
}
+// virtual
+void LLInspectAvatar::onClose(bool app_quitting)
+{
+ getChild<LLMenuButton>("gear_btn")->hideMenu();
+}
+
//virtual
void LLInspectAvatar::onFocusLost()
{
diff --git a/indra/newview/llinspectobject.cpp b/indra/newview/llinspectobject.cpp
index b0e6273c41..8c38e785e9 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -46,6 +46,7 @@
#include "llcontrol.h" // LLCachedControl
#include "llfloater.h"
#include "llfloaterreg.h"
+#include "llmenubutton.h"
#include "llresmgr.h" // getMonetaryString
#include "llsafehandle.h"
#include "lltextbox.h" // for description truncation
@@ -81,7 +82,7 @@ public:
/*virtual*/ void onOpen(const LLSD& avatar_id);
// Release the selection and do other cleanup
- void onClose();
+ /*virtual*/ void onClose(bool app_quitting);
// Inspectors close themselves when they lose focus
/*virtual*/ void onFocusLost();
@@ -175,8 +176,6 @@ BOOL LLInspectObject::postBuild(void)
LLSelectMgr::getInstance()->mUpdateSignal.connect(
boost::bind(&LLInspectObject::update, this) );
- mCloseSignal.connect( boost::bind(&LLInspectObject::onClose, this) );
-
return TRUE;
}
@@ -250,10 +249,13 @@ void LLInspectObject::onOpen(const LLSD& data)
}
}
-void LLInspectObject::onClose()
+// virtual
+void LLInspectObject::onClose(bool app_quitting)
{
// Release selection to deselect
mObjectSelection = NULL;
+
+ getChild<LLMenuButton>("gear_btn")->hideMenu();
}
//virtual
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index b996c15a7d..26ff219437 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -68,7 +68,9 @@ LLMediaCtrl::Params::Params()
texture_width("texture_width", 1024),
texture_height("texture_height", 1024),
caret_color("caret_color")
-{}
+{
+ tab_stop(false);
+}
LLMediaCtrl::LLMediaCtrl( const Params& p) :
LLPanel( p ),
@@ -903,6 +905,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
};
break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
+ };
+ break;
};
// chain all events to any potential observers of this object.
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
new file mode 100644
index 0000000000..e69c85f245
--- /dev/null
+++ b/indra/newview/llmediadataclient.cpp
@@ -0,0 +1,624 @@
+/**
+ * @file llmediadataclient.cpp
+ * @brief class for queueing up requests for media data
+ *
+ * $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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llmediadataclient.h"
+
+#include <boost/lexical_cast.hpp>
+
+#include "llhttpstatuscodes.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
+#include "lltextureentry.h"
+#include "llviewerregion.h"
+
+//
+// When making a request
+// - obtain the "overall interest score" of the object.
+// This would be the sum of the impls' interest scores.
+// - put the request onto a queue sorted by this score
+// (highest score at the front of the queue)
+// - On a timer, once a second, pull off the head of the queue and send
+// the request.
+// - Any request that gets a 503 still goes through the retry logic
+//
+
+const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s)
+const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs
+const U32 LLMediaDataClient::MAX_RETRIES = 4;
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Request
+//
+//////////////////////////////////////////////////////////////////////////////////////
+/*static*/U32 LLMediaDataClient::Request::sNum = 0;
+
+LLMediaDataClient::Request::Request(const std::string &cap_name,
+ const LLSD& sd_payload,
+ LLMediaDataClientObject *obj,
+ LLMediaDataClient *mdc)
+ : mCapName(cap_name),
+ mPayload(sd_payload),
+ mObject(obj),
+ mNum(++sNum),
+ mRetryCount(0),
+ mMDC(mdc)
+{
+}
+
+LLMediaDataClient::Request::~Request()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL;
+ mMDC = NULL;
+ mObject = NULL;
+}
+
+
+std::string LLMediaDataClient::Request::getCapability() const
+{
+ return getObject()->getCapabilityUrl(getCapName());
+}
+
+// Helper function to get the "type" of request, which just pokes around to
+// discover it.
+LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const
+{
+ if (mCapName == "ObjectMediaNavigate")
+ {
+ return NAVIGATE;
+ }
+ else if (mCapName == "ObjectMedia")
+ {
+ const std::string &verb = mPayload["verb"];
+ if (verb == "GET")
+ {
+ return GET;
+ }
+ else if (verb == "UPDATE")
+ {
+ return UPDATE;
+ }
+ }
+ llassert(false);
+ return GET;
+}
+
+const char *LLMediaDataClient::Request::getTypeAsString() const
+{
+ Type t = getType();
+ switch (t)
+ {
+ case GET:
+ return "GET";
+ break;
+ case UPDATE:
+ return "UPDATE";
+ break;
+ case NAVIGATE:
+ return "NAVIGATE";
+ break;
+ }
+ return "";
+}
+
+
+void LLMediaDataClient::Request::reEnqueue() const
+{
+ // I sure hope this doesn't deref a bad pointer:
+ mMDC->enqueue(this);
+}
+
+F32 LLMediaDataClient::Request::getRetryTimerDelay() const
+{
+ return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY :
+ mMDC->mRetryTimerDelay;
+}
+
+U32 LLMediaDataClient::Request::getMaxNumRetries() const
+{
+ return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries;
+}
+
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
+{
+ s << "<request>"
+ << "<num>" << r.getNum() << "</num>"
+ << "<type>" << r.getTypeAsString() << "</type>"
+ << "<object_id>" << r.getObject()->getID() << "</object_id>"
+ << "<num_retries>" << r.getRetryCount() << "</num_retries>"
+ << "</request> ";
+ return s;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Responder::RetryTimer
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
+ : LLEventTimer(time), mResponder(mdr)
+{
+}
+
+// virtual
+LLMediaDataClient::Responder::RetryTimer::~RetryTimer()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
+ mResponder = NULL;
+}
+
+// virtual
+BOOL LLMediaDataClient::Responder::RetryTimer::tick()
+{
+ // Instead of retrying, we just put the request back onto the queue
+ LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL;
+ mResponder->getRequest()->reEnqueue();
+ // Don't fire again
+ return TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Responder
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
+ : mRequest(request)
+{
+}
+
+LLMediaDataClient::Responder::~Responder()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL;
+ mRequest = NULL;
+}
+
+/*virtual*/
+void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
+{
+ if (status == HTTP_SERVICE_UNAVAILABLE)
+ {
+ F32 retry_timeout = mRequest->getRetryTimerDelay();
+
+ mRequest->incRetryCount();
+
+ if (mRequest->getRetryCount() < mRequest->getMaxNumRetries())
+ {
+ LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+
+ // Start timer (instances are automagically tracked by
+ // InstanceTracker<> and LLEventTimer)
+ new RetryTimer(F32(retry_timeout/*secs*/), this);
+ }
+ else {
+ LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " <<
+ mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
+ }
+ }
+ else {
+ std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason;
+ LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL;
+ }
+}
+
+
+/*virtual*/
+void LLMediaDataClient::Responder::result(const LLSD& content)
+{
+ LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_pretty_print_sd(content) << LL_ENDL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Comparator
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+bool LLMediaDataClient::Comparator::operator() (const request_ptr_t &o1, const request_ptr_t &o2) const
+{
+ if (o2.isNull()) return true;
+ if (o1.isNull()) return false;
+
+ // The score is intended to be a measure of how close an object is or
+ // how much screen real estate (interest) it takes up
+ // Further away = lower score.
+ // Lesser interest = lower score
+ // For instance, here are some cases:
+ // 1: Two items with no impl, closest one wins
+ // 2: Two items with an impl: interest should rule, but distance is
+ // still taken into account (i.e. something really close might take
+ // precedence over a large item far away)
+ // 3: One item with an impl, another without: item with impl wins
+ // (XXX is that what we want?)
+ // Calculate the scores for each.
+ F64 o1_score = Comparator::getObjectScore(o1->getObject());
+ F64 o2_score = Comparator::getObjectScore(o2->getObject());
+
+ // XXX Weird: a higher score should go earlier, but by observation I notice
+ // that this causes further-away objects load first. This is counterintuitive
+ // to the priority_queue Comparator, which states that this function should
+ // return 'true' if o1 should be *before* o2.
+ // In other words, I'd have expected that the following should return
+ // ( o1_score > o2_score).
+ return ( o1_score < o2_score );
+}
+
+// static
+F64 LLMediaDataClient::Comparator::getObjectScore(const LLMediaDataClientObject::ptr_t &obj)
+{
+ // *TODO: make this less expensive?
+ F64 dist = obj->getDistanceFromAvatar() + 0.1; // avoids div by 0
+ // square the distance so that they are in the same "unit magnitude" as
+ // the interest (which is an area)
+ dist *= dist;
+ F64 interest = obj->getTotalMediaInterest() + 1.0;
+
+ return interest/dist;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::PriorityQueue
+// Queue of LLMediaDataClientObject smart pointers to request media for.
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+// dump the queue
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::PriorityQueue &q)
+{
+ int i = 0;
+ std::vector<LLMediaDataClient::request_ptr_t>::const_iterator iter = q.c.begin();
+ std::vector<LLMediaDataClient::request_ptr_t>::const_iterator end = q.c.end();
+ while (iter < end)
+ {
+ s << "\t" << i << "]: " << (*iter)->getObject()->getID().asString();
+ iter++;
+ i++;
+ }
+ return s;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::QueueTimer
+// Queue of LLMediaDataClientObject smart pointers to request media for.
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
+ : LLEventTimer(time), mMDC(mdc)
+{
+ mMDC->setIsRunning(true);
+}
+
+LLMediaDataClient::QueueTimer::~QueueTimer()
+{
+ LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL;
+ mMDC->setIsRunning(false);
+ mMDC = NULL;
+}
+
+// virtual
+BOOL LLMediaDataClient::QueueTimer::tick()
+{
+ if (NULL == mMDC->pRequestQueue)
+ {
+ // Shutting down? stop.
+ LL_DEBUGS("LLMediaDataClient") << "queue gone" << LL_ENDL;
+ return TRUE;
+ }
+
+ LLMediaDataClient::PriorityQueue &queue = *(mMDC->pRequestQueue);
+
+ if (queue.empty())
+ {
+ LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL;
+ return TRUE;
+ }
+
+ LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL;
+
+ // Peel one off of the items from the queue, and execute request
+ request_ptr_t request = queue.top();
+ llassert(!request.isNull());
+ const LLMediaDataClientObject *object = request->getObject();
+ bool performed_request = false;
+ llassert(NULL != object);
+ if (NULL != object && object->hasMedia())
+ {
+ std::string url = request->getCapability();
+ if (!url.empty())
+ {
+ const LLSD &sd_payload = request->getPayload();
+ LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL;
+
+ // Call the subclass for creating the responder
+ LLHTTPClient::post(url, sd_payload, mMDC->createResponder(request));
+ performed_request = true;
+ }
+ else {
+ LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
+ }
+ }
+ else {
+ if (!object->hasMedia())
+ {
+ LL_INFOS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
+ }
+ }
+ bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries;
+ if (performed_request || exceeded_retries) // Try N times before giving up
+ {
+ if (exceeded_retries)
+ {
+ LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "
+ << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;
+ // XXX Should we bring up a warning dialog??
+ }
+ queue.pop();
+ }
+ else {
+ request->incRetryCount();
+ }
+ LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue is now: " << (*(mMDC->pRequestQueue)) << LL_ENDL;
+
+ return queue.empty();
+}
+
+void LLMediaDataClient::startQueueTimer()
+{
+ if (! mQueueTimerIsRunning)
+ {
+ LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
+ // LLEventTimer automagically takes care of the lifetime of this object
+ new QueueTimer(mQueueTimerDelay, this);
+ }
+}
+
+void LLMediaDataClient::stopQueueTimer()
+{
+ mQueueTimerIsRunning = false;
+}
+
+void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
+{
+ if (object.isNull() || ! object->hasMedia()) return;
+
+ // Push the object on the priority queue
+ enqueue(new Request(getCapabilityName(), payload, object, this));
+}
+
+void LLMediaDataClient::enqueue(const Request *request)
+{
+ LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL;
+ // Push the request on the priority queue
+ // Sadly, we have to const-cast because items put into the queue are not const
+ pRequestQueue->push(const_cast<LLMediaDataClient::Request*>(request));
+ LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL;
+ // Start the timer if not already running
+ startQueueTimer();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
+ F32 retry_timer_delay,
+ U32 max_retries)
+ : mQueueTimerDelay(queue_timer_delay),
+ mRetryTimerDelay(retry_timer_delay),
+ mMaxNumRetries(max_retries),
+ mQueueTimerIsRunning(false)
+{
+ pRequestQueue = new PriorityQueue();
+}
+
+LLMediaDataClient::~LLMediaDataClient()
+{
+ stopQueueTimer();
+
+ // This should clear the queue, and hopefully call all the destructors.
+ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<
+ (pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL;
+ delete pRequestQueue;
+ pRequestQueue = NULL;
+}
+
+bool LLMediaDataClient::isEmpty() const
+{
+ return (NULL == pRequestQueue) ? true : pRequestQueue->empty();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLObjectMediaDataClient
+// Subclass of LLMediaDataClient for the ObjectMedia cap
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder *LLObjectMediaDataClient::createResponder(const request_ptr_t &request) const
+{
+ return new LLObjectMediaDataClient::Responder(request);
+}
+
+const char *LLObjectMediaDataClient::getCapabilityName() const
+{
+ return "ObjectMedia";
+}
+
+void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object)
+{
+ LLSD sd_payload;
+ sd_payload["verb"] = "GET";
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ request(object, sd_payload);
+}
+
+void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
+{
+ LLSD sd_payload;
+ sd_payload["verb"] = "UPDATE";
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ LLSD object_media_data;
+ int i = 0;
+ int end = object->getMediaDataCount();
+ for ( ; i < end ; ++i)
+ {
+ object_media_data.append(object->getMediaDataLLSD(i));
+ }
+ sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
+
+ LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_pretty_print_sd(sd_payload) << LL_ENDL;
+
+ request(object, sd_payload);
+}
+
+/*virtual*/
+void LLObjectMediaDataClient::Responder::result(const LLSD& content)
+{
+ const LLMediaDataClient::Request::Type type = getRequest()->getType();
+ llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
+ if (type == LLMediaDataClient::Request::GET)
+ {
+ LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_pretty_print_sd(content) << LL_ENDL;
+
+ // Look for an error
+ if (content.has("error"))
+ {
+ const LLSD &error = content["error"];
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error getting media data for object: code=" <<
+ error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
+
+ // XXX Warn user?
+ }
+ else {
+ // Check the data
+ const LLUUID &object_id = content[LLTextureEntry::OBJECT_ID_KEY];
+ if (object_id != getRequest()->getObject()->getID())
+ {
+ // NOT good, wrong object id!!
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
+ return;
+ }
+
+ // Otherwise, update with object media data
+ getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]);
+ }
+ }
+ else if (type == LLMediaDataClient::Request::UPDATE)
+ {
+ // just do what our superclass does
+ LLMediaDataClient::Responder::result(content);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLObjectMediaNavigateClient
+// Subclass of LLMediaDataClient for the ObjectMediaNavigate cap
+//
+//////////////////////////////////////////////////////////////////////////////////////
+LLMediaDataClient::Responder *LLObjectMediaNavigateClient::createResponder(const request_ptr_t &request) const
+{
+ return new LLObjectMediaNavigateClient::Responder(request);
+}
+
+const char *LLObjectMediaNavigateClient::getCapabilityName() const
+{
+ return "ObjectMediaNavigate";
+}
+
+void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url)
+{
+ LLSD sd_payload;
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ sd_payload[LLMediaEntry::CURRENT_URL_KEY] = url;
+ sd_payload[LLTextureEntry::TEXTURE_INDEX_KEY] = (LLSD::Integer)texture_index;
+ request(object, sd_payload);
+}
+
+/*virtual*/
+void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string& reason)
+{
+ // Bounce back (unless HTTP_SERVICE_UNAVAILABLE, in which case call base
+ // class
+ if (status == HTTP_SERVICE_UNAVAILABLE)
+ {
+ LLMediaDataClient::Responder::error(status, reason);
+ }
+ else {
+ // bounce the face back
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: http code=" << status << LL_ENDL;
+ const LLSD &payload = getRequest()->getPayload();
+ // bounce the face back
+ getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
+ }
+}
+
+/*virtual*/
+void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
+{
+ LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_pretty_print_sd(content) << LL_ENDL;
+
+ if (content.has("error"))
+ {
+ const LLSD &error = content["error"];
+ int error_code = error["code"];
+
+ if (ERROR_PERMISSION_DENIED_CODE == error_code)
+ {
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
+ const LLSD &payload = getRequest()->getPayload();
+ // bounce the face back
+ getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
+ }
+ else {
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" <<
+ error["code"].asString() << ": " << error["message"].asString() << LL_ENDL;
+ }
+ // XXX Warn user?
+ }
+ else {
+ // just do what our superclass does
+ LLMediaDataClient::Responder::result(content);
+ }
+}
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
new file mode 100644
index 0000000000..9d0aa0981e
--- /dev/null
+++ b/indra/newview/llmediadataclient.h
@@ -0,0 +1,309 @@
+/**
+ * @file llmediadataclient.h
+ * @brief class for queueing up requests to the media service
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-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_LLMEDIADATACLIENT_H
+#define LL_LLMEDIADATACLIENT_H
+
+#include "llhttpclient.h"
+#include <queue>
+#include "llrefcount.h"
+#include "llpointer.h"
+#include "lltimer.h"
+
+
+// Link seam for LLVOVolume
+class LLMediaDataClientObject : public LLRefCount
+{
+public:
+ // Get the number of media data items
+ virtual U8 getMediaDataCount() const = 0;
+ // Get the media data at index, as an LLSD
+ virtual LLSD getMediaDataLLSD(U8 index) const = 0;
+ // Get this object's UUID
+ virtual LLUUID getID() const = 0;
+ // Navigate back to previous URL
+ virtual void mediaNavigateBounceBack(U8 index) = 0;
+ // Does this object have media?
+ virtual bool hasMedia() const = 0;
+ // Update the object's media data to the given array
+ virtual void updateObjectMediaData(LLSD const &media_data_array) = 0;
+ // Return the distance from the object to the avatar
+ virtual F64 getDistanceFromAvatar() const = 0;
+ // Return the total "interest" of the media (on-screen area)
+ virtual F64 getTotalMediaInterest() const = 0;
+ // Return the given cap url
+ virtual std::string getCapabilityUrl(const std::string &name) const = 0;
+
+ // smart pointer
+ typedef LLPointer<LLMediaDataClientObject> ptr_t;
+};
+
+// This object creates a priority queue for requests.
+// Abstracts the Cap URL, the request, and the responder
+class LLMediaDataClient : public LLRefCount
+{
+public:
+ LOG_CLASS(LLMediaDataClient);
+
+ const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
+ const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
+ const static U32 MAX_RETRIES;// = 4;
+
+ // Constructor
+ LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES);
+
+ // Make the request
+ void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload);
+
+ F32 getRetryTimerDelay() const { return mRetryTimerDelay; }
+
+ // Returns true iff the queue is empty
+ bool isEmpty() const;
+
+protected:
+ // Destructor
+ virtual ~LLMediaDataClient(); // use unref
+
+ // Request
+ class Request : public LLRefCount
+ {
+ public:
+ enum Type {
+ GET,
+ UPDATE,
+ NAVIGATE
+ };
+
+ Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
+ const std::string &getCapName() const { return mCapName; }
+ const LLSD &getPayload() const { return mPayload; }
+ LLMediaDataClientObject *getObject() const { return mObject; }
+
+ U32 getNum() const { return mNum; }
+
+ U32 getRetryCount() const { return mRetryCount; }
+ void incRetryCount() { mRetryCount++; }
+
+ // Note: may return empty string!
+ std::string getCapability() const;
+
+ Type getType() const;
+ const char *getTypeAsString() const;
+
+ // Re-enqueue thyself
+ void reEnqueue() const;
+
+ F32 getRetryTimerDelay() const;
+ U32 getMaxNumRetries() const;
+
+ public:
+ friend std::ostream& operator<<(std::ostream &s, const Request &q);
+
+ protected:
+ virtual ~Request(); // use unref();
+
+ private:
+ std::string mCapName;
+ LLSD mPayload;
+ LLMediaDataClientObject::ptr_t mObject;
+ // Simple tracking
+ const U32 mNum;
+ static U32 sNum;
+ U32 mRetryCount;
+
+ // Back pointer to the MDC...not a ref!
+ LLMediaDataClient *mMDC;
+ };
+ typedef LLPointer<Request> request_ptr_t;
+
+ // Responder
+ class Responder : public LLHTTPClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request);
+ //If we get back an error (not found, etc...), handle it here
+ virtual void error(U32 status, const std::string& reason);
+ //If we get back a normal response, handle it here. Default just logs it.
+ virtual void result(const LLSD& content);
+
+ const request_ptr_t &getRequest() const { return mRequest; }
+
+ protected:
+ virtual ~Responder();
+
+ private:
+
+ class RetryTimer : public LLEventTimer
+ {
+ public:
+ RetryTimer(F32 time, Responder *);
+ virtual ~RetryTimer();
+ virtual BOOL tick();
+ private:
+ // back-pointer
+ boost::intrusive_ptr<Responder> mResponder;
+ };
+
+ request_ptr_t mRequest;
+ };
+
+protected:
+
+ void enqueue(const Request*);
+
+ // Subclasses must override this factory method to return a new responder
+ virtual Responder *createResponder(const request_ptr_t &request) const = 0;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const = 0;
+
+private:
+
+ // Comparator for PriorityQueue
+ class Comparator
+ {
+ public:
+ bool operator() (const request_ptr_t &o1, const request_ptr_t &o2) const;
+ private:
+ static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
+ };
+
+ // PriorityQueue
+ class PriorityQueue : public std::priority_queue<
+ request_ptr_t,
+ std::vector<request_ptr_t>,
+ Comparator >
+ {
+ public:
+ friend std::ostream& operator<<(std::ostream &s, const PriorityQueue &q);
+ };
+
+ friend std::ostream& operator<<(std::ostream &s, const Request &q);
+ friend std::ostream& operator<<(std::ostream &s, const PriorityQueue &q);
+
+ class QueueTimer : public LLEventTimer
+ {
+ public:
+ QueueTimer(F32 time, LLMediaDataClient *mdc);
+ virtual BOOL tick();
+ protected:
+ virtual ~QueueTimer();
+ private:
+ // back-pointer
+ LLPointer<LLMediaDataClient> mMDC;
+ };
+
+ void startQueueTimer();
+ void stopQueueTimer();
+ void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
+
+ const F32 mQueueTimerDelay;
+ const F32 mRetryTimerDelay;
+ const U32 mMaxNumRetries;
+
+ bool mQueueTimerIsRunning;
+
+ PriorityQueue *pRequestQueue;
+};
+
+
+// MediaDataResponder specific for the ObjectMedia cap
+class LLObjectMediaDataClient : public LLMediaDataClient
+{
+public:
+ LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
+ ~LLObjectMediaDataClient() {}
+
+ void fetchMedia(LLMediaDataClientObject *object);
+ void updateMedia(LLMediaDataClientObject *object);
+
+protected:
+ // Subclasses must override this factory method to return a new responder
+ virtual Responder *createResponder(const request_ptr_t &request) const;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const;
+
+ class Responder : public LLMediaDataClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request)
+ : LLMediaDataClient::Responder(request) {}
+ virtual void result(const LLSD &content);
+ };
+};
+
+
+// MediaDataResponder specific for the ObjectMediaNavigate cap
+class LLObjectMediaNavigateClient : public LLMediaDataClient
+{
+public:
+ // NOTE: from llmediaservice.h
+ static const int ERROR_PERMISSION_DENIED_CODE = 8002;
+
+ LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
+ ~LLObjectMediaNavigateClient() {}
+
+ void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
+
+protected:
+ // Subclasses must override this factory method to return a new responder
+ virtual Responder *createResponder(const request_ptr_t &request) const;
+
+ // Subclasses must override to return a cap name
+ virtual const char *getCapabilityName() const;
+
+ class Responder : public LLMediaDataClient::Responder
+ {
+ public:
+ Responder(const request_ptr_t &request)
+ : LLMediaDataClient::Responder(request) {}
+ virtual void error(U32 status, const std::string& reason);
+ virtual void result(const LLSD &content);
+ private:
+ void mediaNavigateBounceBack();
+ };
+
+};
+
+
+#endif // LL_LLMEDIADATACLIENT_H
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index 599e6b6859..7c8ffa3b94 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -72,11 +72,9 @@ public:
void onNearbyChatContextMenuItemClicked(const LLSD& userdata);
bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
- virtual void onClose (bool app_quitting) { if(app_quitting) destroy(); else setVisible(false); }
+ /*virtual*/ void onOpen (const LLSD& key);
- virtual void onOpen (const LLSD& key);
-
- virtual void draw ();
+ /*virtual*/ void draw ();
private:
void add_timestamped_line(const LLChat& chat, const LLColor4& color);
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index 1ed5fa4357..a03902caba 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -78,11 +78,11 @@ public:
* Profile tabs should close any opened panels here.
*
* Called from LLPanelProfile::onOpen() before opening new profile.
- * See LLPanelpicks::onClose for example. LLPanelPicks closes picture info panel
+ * See LLPanelPicks::onClosePanel for example. LLPanelPicks closes picture info panel
* before new profile is displayed, otherwise new profile will
* be hidden behind picture info panel.
*/
- virtual void onClose() {}
+ virtual void onClosePanel() {}
/**
* Resets controls visibility, state, etc.
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index c61b987b1c..ee0426c7df 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -786,8 +786,8 @@ void LLPanelFace::getState()
childSetEnabled("button align",FALSE);
childSetEnabled("button apply",FALSE);
- childSetEnabled("has media", FALSE);
- childSetEnabled("media info set", FALSE);
+ //childSetEnabled("has media", FALSE);
+ //childSetEnabled("media info set", FALSE);
}
}
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
index be40d6fb5f..a33d9604fe 100644
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -49,6 +49,8 @@
#include "llpanelcontents.h"
#include "llpluginclassmedia.h"
#include "llfloatermediasettings.h"
+#include "llfloatertools.h"
+#include "lltrans.h"
////////////////////////////////////////////////////////////////////////////////
//
@@ -155,43 +157,11 @@ void LLPanelMediaSettingsGeneral::draw()
};
// current URL can change over time.
- updateCurrentURL();
+// updateCurrentURL();
// enable/disable RESRET button depending on permissions
// since this is the same as a navigate action
- U32 owner_mask_on;
- U32 owner_mask_off;
- U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_OWNER,
- &owner_mask_on, &owner_mask_off );
- U32 group_mask_on;
- U32 group_mask_off;
- U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_GROUP,
- &group_mask_on, &group_mask_off );
- U32 everyone_mask_on;
- U32 everyone_mask_off;
- S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_EVERYONE,
- &everyone_mask_on, &everyone_mask_off );
-
- bool user_can_press_reset = false;
-
- // if perms we got back are valid
- if ( valid_owner_perms &&
- valid_group_perms &&
- valid_everyone_perms )
- {
- // if user is allowed to press the RESET button
- if ( ( owner_mask_on & PERM_MODIFY ) ||
- ( group_mask_on & PERM_MODIFY ) ||
- ( group_mask_on & PERM_MODIFY ) )
- {
- user_can_press_reset = true;
- }
- else
- // user is NOT allowed to press the RESET button
- {
- user_can_press_reset = false;
- };
- };
+ bool user_can_press_reset = gFloaterTools->selectedMediaEditable();
// several places modify this widget so we must collect states in one place
if ( reset_button_is_active )
@@ -216,7 +186,7 @@ void LLPanelMediaSettingsGeneral::draw()
////////////////////////////////////////////////////////////////////////////////
// static
-void LLPanelMediaSettingsGeneral::clearValues( void* userdata )
+void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
{
LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
self->mAltImageEnable ->clear();
@@ -230,12 +200,23 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata )
self->mHeightPixels->clear();
self->mHomeURL->clear();
self->mWidthPixels->clear();
+ self->mAltImageEnable ->setEnabled(editable);
+ self->mAutoLoop ->setEnabled(editable);
+ self->mAutoPlay ->setEnabled(editable);
+ self->mAutoScale ->setEnabled(editable);
+ self->mAutoZoom ->setEnabled(editable);
+ self->mControls ->setEnabled(editable);
+ self->mCurrentURL ->setEnabled(editable);
+ self->mFirstClick ->setEnabled(editable);
+ self->mHeightPixels ->setEnabled(editable);
+ self->mHomeURL ->setEnabled(editable);
+ self->mWidthPixels ->setEnabled(editable);
self->mPreviewMedia->unloadMediaSource();
}
////////////////////////////////////////////////////////////////////////////////
// static
-void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings )
+void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ,bool editable)
{
LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
@@ -243,6 +224,29 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_
//llinfos << ll_pretty_print_sd(media_settings) << llendl;
//llinfos << "---------------" << llendl;
+ // IF all the faces have media (or all dont have media)
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ self->mHomeURL ->setText(LLTrans::getString("Multiple Media"));
+ return;
+ }
+
+ }
std::string base_key( "" );
std::string tentative_key( "" );
@@ -293,10 +297,11 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_
static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )->
setValue( media_settings[ base_key ].asInteger() );
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
};
};
-
+
// interrogates controls and updates widgets as required
self->updateMediaPreview();
self->updateCurrentURL();
@@ -322,30 +327,17 @@ void LLPanelMediaSettingsGeneral::updateMediaPreview()
// Helper to set current URL
void LLPanelMediaSettingsGeneral::updateCurrentURL()
{
- if( mPreviewMedia )
+ if( mCurrentURL->getText().empty() )
{
- LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
- if( media_plugin )
- {
- // get current URL from plugin and display
- std::string current_location = media_plugin->getLocation();
- if ( current_location.length() )
- {
- childSetText( "current_url", current_location );
- }
- else
- // current location may be empty so we need to clear it
- {
- const std::string empty_string( "" );
- childSetText( "current_url", empty_string );
- };
- };
- };
+ childSetText( "current_url", mHomeURL->getText() );
+ }
+
}
////////////////////////////////////////////////////////////////////////////////
-void LLPanelMediaSettingsGeneral::onClose()
+// virtual
+void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
{
if(mPreviewMedia)
{
@@ -374,7 +366,7 @@ void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl()
void LLPanelMediaSettingsGeneral::apply( void* userdata )
{
LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
-
+ self->mHomeURL->onCommit();
// build LLSD Fragment
LLSD media_data_general;
self->getValues(media_data_general);
@@ -393,8 +385,7 @@ void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
- // XXX Don't send current URL!
- //fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
+ fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h
index 24678a3a07..5acfa39181 100644
--- a/indra/newview/llpanelmediasettingsgeneral.h
+++ b/indra/newview/llpanelmediasettingsgeneral.h
@@ -48,7 +48,9 @@ class LLPanelMediaSettingsGeneral : public LLPanel
{
public:
BOOL postBuild();
- virtual void draw();
+ /*virtual*/ void draw();
+ /*virtual*/ void onClose(bool app_quitting);
+
static void apply(void*);
void getValues(LLSD &fill_me_in);
@@ -56,14 +58,12 @@ public:
~LLPanelMediaSettingsGeneral();
void setParent( LLFloaterMediaSettings* parent );
- static void initValues( void* userdata, const LLSD& media_settings );
- static void clearValues( void* userdata );
+ static void initValues( void* userdata, const LLSD& media_settings ,bool editable);
+ static void clearValues( void* userdata, bool editable);
void updateMediaPreview();
void updateCurrentURL();
- void onClose();
-
protected:
LLFloaterMediaSettings* mParent;
@@ -74,7 +74,7 @@ private:
LLComboBox* mControls;
LLCheckBoxCtrl* mAutoLoop;
LLCheckBoxCtrl* mFirstClick;
- LLTextureCtrl* mMediaPreview;
+// LLTextureCtrl* mMediaPreview;
LLCheckBoxCtrl* mAutoZoom;
LLCheckBoxCtrl* mAutoPlay;
LLCheckBoxCtrl* mAutoScale;
diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp
index d6a2677f4b..4d84874e7a 100644
--- a/indra/newview/llpanelmediasettingspermissions.cpp
+++ b/indra/newview/llpanelmediasettingspermissions.cpp
@@ -49,7 +49,8 @@
#include "llselectmgr.h"
#include "llmediaentry.h"
#include "llnamebox.h"
-
+#include "lltrans.h"
+#include "llfloatermediasettings.h"
////////////////////////////////////////////////////////////////////////////////
//
LLPanelMediaSettingsPermissions::LLPanelMediaSettingsPermissions() :
@@ -119,7 +120,7 @@ void LLPanelMediaSettingsPermissions::draw()
////////////////////////////////////////////////////////////////////////////////
// static
-void LLPanelMediaSettingsPermissions::clearValues( void* userdata )
+void LLPanelMediaSettingsPermissions::clearValues( void* userdata, bool editable)
{
LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
self->mPermsOwnerInteract->clear();
@@ -128,16 +129,41 @@ void LLPanelMediaSettingsPermissions::clearValues( void* userdata )
self->mPermsGroupControl->clear();
self->mPermsWorldInteract ->clear();
self->mPermsWorldControl ->clear();
-// mPermsGroupName ->setValue(0);
-
+
+ self->mPermsOwnerInteract->setEnabled(editable);
+ self->mPermsOwnerControl ->setEnabled(editable);
+ self->mPermsGroupInteract->setEnabled(editable);
+ self->mPermsGroupControl ->setEnabled(editable);
+ self->mPermsWorldInteract->setEnabled(editable);
+ self->mPermsWorldControl ->setEnabled(editable);
}
////////////////////////////////////////////////////////////////////////////////
// static
-void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& media_settings )
+void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& media_settings , bool editable)
{
LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata;
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
std::string base_key( "" );
std::string tentative_key( "" );
@@ -178,10 +204,17 @@ void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& me
if ( data_set[ i ].ctrl_type == "LLComboBox" )
static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )->
setCurrentByIndex( media_settings[ base_key ].asInteger() );
-
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
};
};
+ self->childSetEnabled("media_perms_label_owner", editable );
+ self->childSetText("media_perms_label_owner", LLTrans::getString("Media Perms Owner") );
+ self->childSetEnabled("media_perms_label_group", editable );
+ self->childSetText("media_perms_label_group", LLTrans::getString("Media Perms Group") );
+ self->childSetEnabled("media_perms_label_anyone", editable );
+ self->childSetText("media_perms_label_anyone", LLTrans::getString("Media Perms Anyone") );
+
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelmediasettingspermissions.h b/indra/newview/llpanelmediasettingspermissions.h
index ce293e07b9..ecc50e3582 100644
--- a/indra/newview/llpanelmediasettingspermissions.h
+++ b/indra/newview/llpanelmediasettingspermissions.h
@@ -55,8 +55,8 @@ class LLPanelMediaSettingsPermissions : public LLPanel
LLPanelMediaSettingsPermissions();
~LLPanelMediaSettingsPermissions();
- static void initValues( void* userdata, const LLSD& media_settings );
- static void clearValues( void* userdata );
+ static void initValues( void* userdata, const LLSD& media_settings, bool editable );
+ static void clearValues( void* userdata, bool editable);
private:
LLCheckBoxCtrl* mPermsOwnerInteract;
diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp
index a4eee82aa9..cea105d7de 100644
--- a/indra/newview/llpanelmediasettingssecurity.cpp
+++ b/indra/newview/llpanelmediasettingssecurity.cpp
@@ -44,7 +44,7 @@
#include "llselectmgr.h"
#include "llmediaentry.h"
#include "llfloaterwhitelistentry.h"
-
+#include "llfloatermediasettings.h"
////////////////////////////////////////////////////////////////////////////////
//
LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity()
@@ -110,10 +110,30 @@ void LLPanelMediaSettingsSecurity::draw()
////////////////////////////////////////////////////////////////////////////////
// static
-void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings )
+void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings , bool editable)
{
LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+ if ( LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo )
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
+ else
+ {
+ if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ self->clearValues(self, editable);
+ // only show multiple
+ return;
+ }
+
+ }
std::string base_key( "" );
std::string tentative_key( "" );
@@ -163,7 +183,7 @@ void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media
++iter;
};
};
-
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
};
};
@@ -171,11 +191,13 @@ void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media
////////////////////////////////////////////////////////////////////////////////
// static
-void LLPanelMediaSettingsSecurity::clearValues( void* userdata )
+void LLPanelMediaSettingsSecurity::clearValues( void* userdata , bool editable)
{
LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
self->mEnableWhiteList->clear();
self->mWhiteListList->deleteAllItems();
+ self->mEnableWhiteList->setEnabled(editable);
+ self->mWhiteListList->setEnabled(editable);
}
////////////////////////////////////////////////////////////////////////////////
// static
diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h
index d77509897d..b7cf67c039 100644
--- a/indra/newview/llpanelmediasettingssecurity.h
+++ b/indra/newview/llpanelmediasettingssecurity.h
@@ -49,8 +49,8 @@ class LLPanelMediaSettingsSecurity : public LLPanel
LLPanelMediaSettingsSecurity();
~LLPanelMediaSettingsSecurity();
- static void initValues( void* userdata, const LLSD& media_settings );
- static void clearValues( void* userdata );
+ static void initValues( void* userdata, const LLSD& media_settings,bool editable );
+ static void clearValues( void* userdata, bool editable);
void addWhiteListItem(const std::string& url);
private:
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index e74afba25a..979e9618da 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -463,7 +463,8 @@ void LLPickItem::processProperties(void *data, EAvatarProcessorType type)
LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
}
-void LLPanelPicks::onClose()
+// virtual
+void LLPanelPicks::onClosePanel()
{
// Toggle off Pick Info panel if it is visible.
if(mPickPanel && mPickPanel->getVisible())
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 7ebdc3089c..18c571c735 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -77,7 +77,7 @@ public:
/**
* Closes LLPanelPick if it is visible.
*/
- /*virtual*/ void onClose();
+ /*virtual*/ void onClosePanel();
private:
void onClickDelete();
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index eb269fabe3..d6be0a9419 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -44,14 +44,16 @@
#include "llqueryflags.h"
#include "llbutton.h"
+#include "llcombobox.h"
#include "lliconctrl.h"
-#include "lllineeditor.h"
#include "llscrollcontainer.h"
#include "lltextbox.h"
+#include "lltrans.h"
#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagent.h"
+#include "llagentui.h"
#include "llavatarpropertiesprocessor.h"
#include "llfloaterworldmap.h"
#include "llinventorymodel.h"
@@ -64,6 +66,16 @@
#include "llviewertexteditor.h"
#include "llworldmap.h"
+//----------------------------------------------------------------------------
+// Aux types and methods
+//----------------------------------------------------------------------------
+
+typedef std::pair<LLUUID, std::string> folder_pair_t;
+
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
+static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
+static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
+
static LLRegisterPanelClassWrapper<LLPanelPlaceInfo> t_place_info("panel_place_info");
LLPanelPlaceInfo::LLPanelPlaceInfo()
@@ -141,11 +153,8 @@ BOOL LLPanelPlaceInfo::postBuild()
mCreated = getChild<LLTextBox>("created");
mTitleEditor = getChild<LLLineEditor>("title_editor");
- mTitleEditor->setCommitCallback(boost::bind(&LLPanelPlaceInfo::onCommitTitleOrNote, this, TITLE));
-
mNotesEditor = getChild<LLTextEditor>("notes_editor");
- mNotesEditor->setCommitCallback(boost::bind(&LLPanelPlaceInfo::onCommitTitleOrNote, this, NOTE));
- mNotesEditor->setCommitOnFocusLost(true);
+ mFolderCombo = getChild<LLComboBox>("folder_combo");
LLScrollContainer* scroll_container = getChild<LLScrollContainer>("scroll_container");
scroll_container->setBorderVisible(FALSE);
@@ -316,6 +325,7 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
LLPanel* landmark_edit_panel = getChild<LLPanel>("landmark_edit_panel");
bool is_info_type_agent = type == AGENT;
+ bool is_info_type_create_landmark = type == CREATE_LANDMARK;
bool is_info_type_landmark = type == LANDMARK;
bool is_info_type_teleport_history = type == TELEPORT_HISTORY;
@@ -329,7 +339,10 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
mLastVisited->setVisible(is_info_type_teleport_history);
landmark_info_panel->setVisible(is_info_type_landmark);
- landmark_edit_panel->setVisible(is_info_type_landmark || type == CREATE_LANDMARK);
+ landmark_edit_panel->setVisible(is_info_type_landmark || is_info_type_create_landmark);
+
+ getChild<LLTextBox>("folder_lable")->setVisible(is_info_type_create_landmark);
+ mFolderCombo->setVisible(is_info_type_create_landmark);
getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent);
@@ -337,6 +350,11 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
{
case CREATE_LANDMARK:
mCurrentTitle = getString("title_create_landmark");
+
+ mTitleEditor->setEnabled(TRUE);
+ mNotesEditor->setEnabled(TRUE);
+
+ populateFoldersList();
break;
case AGENT:
@@ -351,6 +369,11 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
case LANDMARK:
mCurrentTitle = getString("title_landmark");
+
+ mTitleEditor->setEnabled(FALSE);
+ mNotesEditor->setEnabled(FALSE);
+
+ populateFoldersList();
break;
case TELEPORT_HISTORY:
@@ -485,10 +508,9 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
parcel_data.sim_name.c_str(), region_x, region_y, region_z);
mRegionName->setText(name);
}
-
+
if (mInfoType == CREATE_LANDMARK)
{
-
if (parcel_data.name.empty())
{
mTitleEditor->setText(name);
@@ -498,7 +520,15 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mTitleEditor->setText(parcel_data.name);
}
- mNotesEditor->setText(LLStringUtil::null);
+ // FIXME: Creating landmark works only for current agent location.
+ std::string desc;
+ LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, gAgent.getPositionAgent());
+ mNotesEditor->setText(desc);
+
+ if (!LLLandmarkActions::landmarkAlreadyExists())
+ {
+ createLandmark(mFolderCombo->getValue().asUUID());
+ }
}
}
@@ -694,7 +724,6 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel,
&rent_price,
&for_sale,
&dwell);
-
if (for_sale)
{
// Adding "For Sale" flag in remote parcel response format.
@@ -803,52 +832,42 @@ void LLPanelPlaceInfo::updateLastVisitedText(const LLDate &date)
}
}
-void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type)
+void LLPanelPlaceInfo::toggleLandmarkEditMode(BOOL enabled)
{
- LLInventoryItem* item = gInventory.getItem(mLandmarkID);
- if (!item)
- return;
-
- std::string current_value;
- std::string item_value;
- if (type == TITLE)
+ // If switching to edit mode while creating landmark
+ // the "Create Landmark" title remains.
+ if (enabled && mInfoType != CREATE_LANDMARK)
{
- if (mTitleEditor)
- {
- current_value = mTitleEditor->getText();
- item_value = item->getName();
- }
+ mTitle->setText(getString("title_edit_landmark"));
}
else
{
- if (mNotesEditor)
- {
- current_value = mNotesEditor->getText();
- item_value = item->getDescription();
- }
+ mTitle->setText(mCurrentTitle);
}
- LLStringUtil::trim(current_value);
+ mTitleEditor->setEnabled(enabled);
+ mNotesEditor->setReadOnly(!enabled);
+ mFolderCombo->setVisible(enabled);
+ getChild<LLTextBox>("folder_lable")->setVisible(enabled);
- if (!current_value.empty() &&
- item_value != current_value &&
- gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE))
- {
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ // HACK: To change the text color in a text editor
+ // when it was enabled/disabled we set the text once again.
+ mNotesEditor->setText(mNotesEditor->getText());
+}
- if (type == TITLE)
- {
- new_item->rename(current_value);
- }
- else
- {
- new_item->setDescription(current_value);
- }
+const std::string& LLPanelPlaceInfo::getLandmarkTitle() const
+{
+ return mTitleEditor->getText();
+}
- new_item->updateServer(FALSE);
- gInventory.updateItem(new_item);
- gInventory.notifyObservers();
- }
+const std::string LLPanelPlaceInfo::getLandmarkNotes() const
+{
+ return mNotesEditor->getText();
+}
+
+const LLUUID LLPanelPlaceInfo::getLandmarkFolder() const
+{
+ return mFolderCombo->getValue().asUUID();
}
void LLPanelPlaceInfo::createLandmark(const LLUUID& folder_id)
@@ -921,3 +940,91 @@ void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility)
}
}
}
+
+void LLPanelPlaceInfo::populateFoldersList()
+{
+ // Collect all folders that can contain landmarks.
+ LLInventoryModel::cat_array_t cats;
+ collectLandmarkFolders(cats);
+
+ mFolderCombo->removeall();
+
+ // Put the "Landmarks" folder first in list.
+ LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(landmarks_id);
+ if (!cat)
+ {
+ llwarns << "Cannot find the landmarks folder" << llendl;
+ }
+ std::string cat_full_name = getFullFolderName(cat);
+ mFolderCombo->add(cat_full_name, cat->getUUID());
+
+ typedef std::vector<folder_pair_t> folder_vec_t;
+ folder_vec_t folders;
+ // Sort the folders by their full name.
+ for (S32 i = 0; i < cats.count(); i++)
+ {
+ cat = cats.get(i);
+ cat_full_name = getFullFolderName(cat);
+ folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name));
+ }
+ sort(folders.begin(), folders.end(), cmp_folders);
+
+ // Finally, populate the combobox.
+ for (folder_vec_t::const_iterator it = folders.begin(); it != folders.end(); it++)
+ mFolderCombo->add(it->second, LLSD(it->first));
+}
+
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
+{
+ return left.second < right.second;
+}
+
+static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
+{
+ std::string name = cat->getName();
+ LLUUID parent_id;
+
+ // translate category name, if it's right below the root
+ // FIXME: it can throw notification about non existent string in strings.xml
+ if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID())
+ {
+ LLTrans::findString(name, "InvFolder " + name);
+ }
+
+ // we don't want "My Inventory" to appear in the name
+ while ((parent_id = cat->getParentUUID()).notNull() && parent_id != gInventory.getRootFolderID())
+ {
+ cat = gInventory.getCategory(parent_id);
+ name = cat->getName() + "/" + name;
+ }
+
+ return name;
+}
+
+static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
+{
+ LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+
+ // Add descendent folders of the "Landmarks" category.
+ LLInventoryModel::item_array_t items; // unused
+ LLIsType is_category(LLAssetType::AT_CATEGORY);
+ gInventory.collectDescendentsIf(
+ landmarks_id,
+ cats,
+ items,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_category);
+
+ // Add the "My Favorites" category.
+ LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id);
+ if (!favorites_cat)
+ {
+ llwarns << "Cannot find the favorites folder" << llendl;
+ }
+ else
+ {
+ cats.put(favorites_cat);
+ }
+}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 23a845bc20..49aa195490 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -42,6 +42,7 @@
#include "llremoteparcelrequest.h"
class LLButton;
+class LLComboBox;
class LLInventoryItem;
class LLLineEditor;
class LLPanelPick;
@@ -117,18 +118,19 @@ public:
const std::string& first,
const std::string& last);
+ void toggleLandmarkEditMode(BOOL enabled);
+
+ const std::string& getLandmarkTitle() const;
+ const std::string getLandmarkNotes() const;
+ const LLUUID getLandmarkFolder() const;
+
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
private:
- enum LANDMARK_INFO_TYPE
- {
- TITLE,
- NOTE
- };
- void onCommitTitleOrNote(LANDMARK_INFO_TYPE type);
+ void populateFoldersList();
LLUUID mParcelID;
LLUUID mRequestedID;
@@ -182,6 +184,7 @@ private:
LLTextBox* mCreated;
LLLineEditor* mTitleEditor;
LLTextEditor* mNotesEditor;
+ LLComboBox* mFolderCombo;
LLPanel* mScrollingPanel;
LLPanel* mInfoPanel;
LLMediaPanel* mMediaPanel;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 80ecc95afb..35206f54c7 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -40,16 +40,19 @@
#include "lllandmark.h"
#include "llparcel.h"
+#include "llcombobox.h"
+#include "llfiltereditor.h"
#include "llfloaterreg.h"
#include "llnotifications.h"
-#include "llfiltereditor.h"
#include "lltabcontainer.h"
+#include "lltexteditor.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llagent.h"
#include "llavatarpropertiesprocessor.h"
#include "llfloaterworldmap.h"
+#include "llinventorybridge.h"
#include "llinventorymodel.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
@@ -74,9 +77,6 @@ static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history";
// Helper functions
static bool is_agent_in_selected_parcel(LLParcel* parcel);
-static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
-static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
static void onSLURLBuilt(std::string& slurl);
static void setAllChildrenVisible(LLView* view, BOOL visible);
@@ -125,8 +125,8 @@ LLPanelPlaces::LLPanelPlaces()
mItem(NULL),
mPlaceMenu(NULL),
mLandmarkMenu(NULL),
- mLandmarkFoldersMenuHandle(),
- mPosGlobal()
+ mPosGlobal(),
+ isLandmarkEditModeOn(false)
{
mParcelObserver = new LLPlacesParcelObserver(this);
mInventoryObserver = new LLPlacesInventoryObserver(this);
@@ -146,20 +146,12 @@ LLPanelPlaces::~LLPanelPlaces()
LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
- LLView::deleteViewByHandle(mLandmarkFoldersMenuHandle);
-
delete mInventoryObserver;
delete mParcelObserver;
}
BOOL LLPanelPlaces::postBuild()
{
- mCreateLandmarkBtn = getChild<LLButton>("create_landmark_btn");
- mCreateLandmarkBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, LLUUID()));
-
- mFolderMenuBtn = getChild<LLButton>("folder_menu_btn");
- mFolderMenuBtn->setClickedCallback(boost::bind(&LLPanelPlaces::showLandmarkFoldersMenu, this));
-
mTeleportBtn = getChild<LLButton>("teleport_btn");
mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this));
@@ -169,6 +161,18 @@ BOOL LLPanelPlaces::postBuild()
mShareBtn = getChild<LLButton>("share_btn");
//mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this));
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ mSaveBtn = getChild<LLButton>("save_btn");
+ mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this));
+
+ mCancelBtn = getChild<LLButton>("cancel_btn");
+ mCancelBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCancelButtonClicked, this));
+
+ mCloseBtn = getChild<LLButton>("close_btn");
+ mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+
mOverflowBtn = getChild<LLButton>("overflow_btn");
mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
@@ -200,10 +204,18 @@ BOOL LLPanelPlaces::postBuild()
}
mPlaceInfo = getChild<LLPanelPlaceInfo>("panel_place_info");
-
+
LLButton* back_btn = mPlaceInfo->getChild<LLButton>("back_btn");
back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
+ LLLineEditor* title_editor = mPlaceInfo->getChild<LLLineEditor>("title_editor");
+ title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL);
+
+ LLTextEditor* notes_editor = mPlaceInfo->getChild<LLTextEditor>("notes_editor");
+ notes_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
+ LLComboBox* folder_combo = mPlaceInfo->getChild<LLComboBox>("folder_combo");
+ folder_combo->setSelectionCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
return TRUE;
}
@@ -217,6 +229,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
mPlaceInfoType = key["type"].asString();
mPosGlobal.setZero();
+ mItem = NULL;
togglePlaceInfoPanel(TRUE);
updateVerbs();
@@ -227,11 +240,25 @@ void LLPanelPlaces::onOpen(const LLSD& key)
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
{
mPlaceInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
+
+ if (key.has("x") && key.has("y") && key.has("z"))
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ }
+ else
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
+
+ mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal);
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
- LLUUID item_uuid = key["id"].asUUID();
- LLInventoryItem* item = gInventory.getItem(item_uuid);
+ mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+
+ LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
if (!item)
return;
@@ -272,8 +299,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
// Start using LLViewerParcelMgr for land selection if
// information about nearby land is requested.
// Otherwise stop using land selection and deselect land.
- if (mPlaceInfoType == AGENT_INFO_TYPE ||
- mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ if (mPlaceInfoType == AGENT_INFO_TYPE)
{
parcel_mgr->addObserver(mParcelObserver);
parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());
@@ -291,7 +317,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
void LLPanelPlaces::setItem(LLInventoryItem* item)
{
- if (!mPlaceInfo)
+ if (!item)
return;
mItem = item;
@@ -304,7 +330,9 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
return;
}
- mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+ if (!mPlaceInfo)
+ return;
+
mPlaceInfo->displayItemInfo(mItem);
LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(),
@@ -324,6 +352,12 @@ void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark)
landmark->getRegionID(region_id);
landmark->getGlobalPos(mPosGlobal);
mPlaceInfo->displayParcelInfo(region_id, mPosGlobal);
+
+ // Check if item is in agent's inventory and he has the permission to modify it.
+ BOOL is_landmark_editable = mItem.notNull() &&
+ gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) &&
+ mItem->getPermissions().allowModifyBy(gAgent.getID());
+ mEditBtn->setEnabled(is_landmark_editable);
}
void LLPanelPlaces::onFilterEdit(const std::string& search_string)
@@ -436,6 +470,136 @@ void LLPanelPlaces::onShowOnMapButtonClicked()
}
}
+void LLPanelPlaces::onEditButtonClicked()
+{
+ if (!mPlaceInfo || isLandmarkEditModeOn)
+ return;
+
+ isLandmarkEditModeOn = true;
+
+ mPlaceInfo->toggleLandmarkEditMode(TRUE);
+
+ updateVerbs();
+}
+
+void LLPanelPlaces::onSaveButtonClicked()
+{
+ if (!mPlaceInfo || mItem.isNull())
+ return;
+
+ LLAssetType::EType item_type = mItem->getType();
+ if (item_type == LLAssetType::AT_LANDMARK || item_type != LLAssetType::AT_LINK)
+ {
+ // If the item is a link get a linked item
+ if (item_type == LLAssetType::AT_LINK)
+ {
+ mItem = gInventory.getItem(mItem->getAssetUUID());
+ if (mItem.isNull())
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ std::string current_title_value = mPlaceInfo->getLandmarkTitle();
+ std::string item_title_value = mItem->getName();
+ std::string current_notes_value = mPlaceInfo->getLandmarkNotes();
+ std::string item_notes_value = mItem->getDescription();
+
+ LLStringUtil::trim(current_title_value);
+ LLStringUtil::trim(current_notes_value);
+
+ bool is_item_update_needed = false;
+
+ if (!current_title_value.empty() &&
+ (item_title_value != current_title_value || item_notes_value != current_notes_value))
+ {
+ is_item_update_needed = true;
+ }
+
+ LLUUID item_id = mItem->getUUID();
+ LLUUID folder_id = mPlaceInfo->getLandmarkFolder();
+
+ // Check if item is in agent's inventory and he has the permission to modify it.
+ if (!gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) ||
+ !mItem->getPermissions().allowModifyBy(gAgent.getID()))
+ return;
+
+ if(folder_id != mItem->getParentUUID() || is_item_update_needed)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)mItem.get();
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+
+ // If target is the favorites folder we create link to it.
+ if (favorites_id == folder_id)
+ {
+ if (is_item_update_needed)
+ {
+ new_item->rename(current_title_value);
+ new_item->setDescription(current_notes_value);
+ new_item->updateServer(FALSE);
+
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+
+ link_inventory_item(gAgent.getID(),
+ item->getUUID(),
+ folder_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else
+ {
+ if (is_item_update_needed)
+ {
+ new_item->rename(current_title_value);
+ new_item->setDescription(current_notes_value);
+ new_item->updateServer(FALSE);
+ }
+
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ new_item->setParent(folder_id);
+ new_item->updateParentOnServer(FALSE);
+
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ }
+
+ onCancelButtonClicked();
+}
+
+void LLPanelPlaces::onCancelButtonClicked()
+{
+ if (!mPlaceInfo)
+ return;
+
+ if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ {
+ onBackButtonClicked();
+ }
+ else
+ {
+ mPlaceInfo->toggleLandmarkEditMode(FALSE);
+ updateVerbs();
+
+ // Reload the landmark properties.
+ mPlaceInfo->displayItemInfo(mItem);
+ }
+}
+
void LLPanelPlaces::onOverflowButtonClicked()
{
LLToggleableMenu* menu;
@@ -487,7 +651,12 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
std::string item = param.asString();
if (item == "landmark")
{
- onOpen(LLSD().insert("type", CREATE_LANDMARK_INFO_TYPE));
+ LLSD key;
+ key["type"] = CREATE_LANDMARK_INFO_TYPE;
+ key["x"] = mPosGlobal.mdV[VX];
+ key["y"] = mPosGlobal.mdV[VY];
+ key["z"] = mPosGlobal.mdV[VZ];
+ onOpen(key);
}
else if (item == "copy")
{
@@ -523,20 +692,6 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
}
}
-void LLPanelPlaces::onCreateLandmarkButtonClicked(const LLUUID& folder_id)
-{
- if (!mPlaceInfo)
- return;
-
- // To prevent creating duplicate landmarks
- // disable landmark creating buttons until
- // the information on existing landmarks is reloaded.
- mCreateLandmarkBtn->setEnabled(FALSE);
- mFolderMenuBtn->setEnabled(FALSE);
-
- mPlaceInfo->createLandmark(folder_id);
-}
-
void LLPanelPlaces::onBackButtonClicked()
{
if (!mPlaceInfo)
@@ -697,10 +852,14 @@ void LLPanelPlaces::updateVerbs()
bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
bool is_media_panel_visible = mPlaceInfo->isMediaPanelVisible();
- mTeleportBtn->setVisible(!is_create_landmark_visible);
- mShareBtn->setVisible(!is_create_landmark_visible);
- mCreateLandmarkBtn->setVisible(is_create_landmark_visible);
- mFolderMenuBtn->setVisible(is_create_landmark_visible);
+ mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mShareBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mOverflowBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
+ mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
+ mSaveBtn->setVisible(isLandmarkEditModeOn);
+ mCancelBtn->setVisible(isLandmarkEditModeOn);
+ mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
mOverflowBtn->setEnabled(is_place_info_visible && !is_media_panel_visible && !is_create_landmark_visible);
@@ -714,15 +873,6 @@ void LLPanelPlaces::updateVerbs()
!mPosGlobal.isExactlyZero() &&
!LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal));
}
- else if (is_create_landmark_visible)
- {
- // Enable "Create Landmark" only if there is no landmark
- // for the current parcel and agent is inside it.
- bool enable = !LLLandmarkActions::landmarkAlreadyExists() &&
- is_agent_in_selected_parcel(mParcel->getParcel());
- mCreateLandmarkBtn->setEnabled(enable);
- mFolderMenuBtn->setEnabled(enable);
- }
else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
{
mTeleportBtn->setEnabled(TRUE);
@@ -735,131 +885,8 @@ void LLPanelPlaces::updateVerbs()
if (mActivePanel)
mActivePanel->updateVerbs();
}
-}
-
-void LLPanelPlaces::showLandmarkFoldersMenu()
-{
- if (mLandmarkFoldersMenuHandle.isDead())
- {
- LLToggleableMenu::Params menu_p;
- menu_p.name("landmarks_folders_menu");
- menu_p.can_tear_off(false);
- menu_p.visible(false);
- menu_p.scrollable(true);
- menu_p.max_scrollable_items = 10;
-
- LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p);
-
- mLandmarkFoldersMenuHandle = menu->getHandle();
- }
-
- LLToggleableMenu* menu = (LLToggleableMenu*)mLandmarkFoldersMenuHandle.get();
- if(!menu)
- return;
-
- if (!menu->toggleVisibility())
- return;
-
- // Collect all folders that can contain landmarks.
- LLInventoryModel::cat_array_t cats;
- collectLandmarkFolders(cats);
-
- // Sort the folders by their full name.
- folder_vec_t folders;
- S32 count = cats.count();
- for (S32 i = 0; i < count; i++)
- {
- const LLViewerInventoryCategory* cat = cats.get(i);
- std::string cat_full_name = getFullFolderName(cat);
- folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name));
- }
- sort(folders.begin(), folders.end(), cmp_folders);
-
- LLRect btn_rect = mFolderMenuBtn->getRect();
-
- LLRect root_rect = getRootView()->getRect();
-
- // Check it there are changed items or viewer dimensions
- // have changed since last call
- if (mLandmarkFoldersCache.size() == count &&
- mRootViewWidth == root_rect.getWidth() &&
- mRootViewHeight == root_rect.getHeight())
- {
- S32 i;
- for (i = 0; i < count; i++)
- {
- if (mLandmarkFoldersCache[i].second != folders[i].second)
- {
- break;
- }
- }
-
- // Check passed, just show the menu
- if (i == count)
- {
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
-
- menu->setButtonRect(btn_rect, this);
- LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop);
- return;
- }
- }
-
- // If there are changes, store the new viewer dimensions
- // and a list of folders
- mRootViewWidth = root_rect.getWidth();
- mRootViewHeight = root_rect.getHeight();
- mLandmarkFoldersCache = folders;
-
- menu->empty();
-
- // Menu width must not exceed the root view limits,
- // so we assume the space between the left edge of
- // the root view and
- LLRect screen_btn_rect;
- localRectToScreen(btn_rect, &screen_btn_rect);
- S32 free_space = screen_btn_rect.mRight;
- U32 max_width = llmin(LANDMARK_FOLDERS_MENU_WIDTH, free_space);
- for(folder_vec_t::const_iterator it = mLandmarkFoldersCache.begin(); it != mLandmarkFoldersCache.end(); it++)
- {
- const std::string& item_name = it->second;
-
- LLMenuItemCallGL::Params item_params;
- item_params.name(item_name);
- item_params.label(item_name);
-
- item_params.on_click.function(boost::bind(&LLPanelPlaces::onCreateLandmarkButtonClicked, this, it->first));
-
- LLMenuItemCallGL *menu_item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
-
- // *TODO: Use a separate method for menu width calculation.
- // Check whether item name wider than menu
- if (menu_item->getNominalWidth() > max_width)
- {
- S32 chars_total = item_name.length();
- S32 chars_fitted = 1;
- menu_item->setLabel(LLStringExplicit(""));
- S32 label_space = max_width - menu_item->getFont()->getWidth("...") -
- menu_item->getNominalWidth(); // This returns width of menu item with empty label (pad pixels)
-
- while (chars_fitted < chars_total && menu_item->getFont()->getWidth(item_name, 0, chars_fitted) < label_space)
- {
- chars_fitted++;
- }
- chars_fitted--; // Rolling back one char, that doesn't fit
-
- menu_item->setLabel(item_name.substr(0, chars_fitted) + "...");
- }
-
- menu->addChild(menu_item);
- }
-
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
- menu->setButtonRect(btn_rect, this);
- LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop);
+ isLandmarkEditModeOn = false;
}
static bool is_agent_in_selected_parcel(LLParcel* parcel)
@@ -874,70 +901,6 @@ static bool is_agent_in_selected_parcel(LLParcel* parcel)
parcel->getLocalID() == parcel_mgr->getAgentParcel()->getLocalID();
}
-static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
-{
- return left.second < right.second;
-}
-
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
-{
- std::string name = cat->getName();
- LLUUID parent_id;
-
- // translate category name, if it's right below the root
- // FIXME: it can throw notification about non existent string in strings.xml
- if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID())
- {
- LLTrans::findString(name, "InvFolder " + name);
- }
-
- // we don't want "My Inventory" to appear in the name
- while ((parent_id = cat->getParentUUID()).notNull() && parent_id != gInventory.getRootFolderID())
- {
- cat = gInventory.getCategory(parent_id);
- name = cat->getName() + "/" + name;
- }
-
- return name;
-}
-
-static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
-{
- // Add the "Landmarks" category itself.
- LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
- LLViewerInventoryCategory* landmarks_cat = gInventory.getCategory(landmarks_id);
- if (!landmarks_cat)
- {
- llwarns << "Cannot find the landmarks folder" << llendl;
- }
- else
- {
- cats.put(landmarks_cat);
- }
-
- // Add descendent folders of the "Landmarks" category.
- LLInventoryModel::item_array_t items; // unused
- LLIsType is_category(LLAssetType::AT_CATEGORY);
- gInventory.collectDescendentsIf(
- landmarks_id,
- cats,
- items,
- LLInventoryModel::EXCLUDE_TRASH,
- is_category);
-
- // Add the "My Favorites" category.
- LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
- LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id);
- if (!favorites_cat)
- {
- llwarns << "Cannot find the favorites folder" << llendl;
- }
- else
- {
- cats.put(favorites_cat);
- }
-}
-
static void onSLURLBuilt(std::string& slurl)
{
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index f208e91237..0b3b3b5fc3 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -72,6 +72,9 @@ private:
//void onShareButtonClicked();
void onTeleportButtonClicked();
void onShowOnMapButtonClicked();
+ void onEditButtonClicked();
+ void onSaveButtonClicked();
+ void onCancelButtonClicked();
void onOverflowButtonClicked();
void onOverflowMenuItemClicked(const LLSD& param);
void onCreateLandmarkButtonClicked(const LLUUID& folder_id);
@@ -84,8 +87,6 @@ private:
void onAgentParcelChange();
void updateVerbs();
- void showLandmarkFoldersMenu();
-
LLFilterEditor* mFilterEditor;
LLPanelPlacesTab* mActivePanel;
LLTabContainer* mTabContainer;
@@ -94,11 +95,13 @@ private:
LLToggleableMenu* mPlaceMenu;
LLToggleableMenu* mLandmarkMenu;
- LLButton* mCreateLandmarkBtn;
- LLButton* mFolderMenuBtn;
LLButton* mTeleportBtn;
LLButton* mShowOnMapBtn;
LLButton* mShareBtn;
+ LLButton* mEditBtn;
+ LLButton* mSaveBtn;
+ LLButton* mCancelBtn;
+ LLButton* mCloseBtn;
LLButton* mOverflowBtn;
LLPlacesInventoryObserver* mInventoryObserver;
@@ -118,19 +121,7 @@ private:
// Information type currently shown in Place Information panel
std::string mPlaceInfoType;
- // Menu handle for pop-up menu to chose a landmark saving
- // folder when creating a new landmark
- LLHandle<LLView> mLandmarkFoldersMenuHandle;
-
- typedef std::vector<folder_pair_t> folder_vec_t;
-
- // List of folders to choose from when creating a landmark
- folder_vec_t mLandmarkFoldersCache;
-
- // If root view width or height is changed
- // the pop-up menu must be updated
- S32 mRootViewWidth;
- S32 mRootViewHeight;
+ bool isLandmarkEditModeOn;
LLSafeHandle<LLParcelSelection> mParcel;
};
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 3bd2645be3..cda7942c1d 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -102,7 +102,7 @@ void LLPanelProfile::onOpen(const LLSD& key)
{
if (key.has("open_tab_name"))
{
- getTabContainer()[PANEL_PICKS]->onClose();
+ getTabContainer()[PANEL_PICKS]->onClosePanel();
// onOpen from selected panel will be called from onTabSelected callback
getTabCtrl()->selectTabByName(key["open_tab_name"]);
diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp
index 3bda30e0c6..604faf8eb4 100644
--- a/indra/newview/llpreviewanim.cpp
+++ b/indra/newview/llpreviewanim.cpp
@@ -68,8 +68,6 @@ void LLPreviewAnim::endAnimCallback( void *userdata )
// virtual
BOOL LLPreviewAnim::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLPreviewAnim::onClose, this));
-
const LLInventoryItem* item = getItem();
if(item)
{
@@ -181,7 +179,8 @@ void LLPreviewAnim::auditionAnim( void *userdata )
}
}
-void LLPreviewAnim::onClose()
+// virtual
+void LLPreviewAnim::onClose(bool app_quitting)
{
const LLInventoryItem *item = getItem();
diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h
index d24e624c32..616c5789ac 100644
--- a/indra/newview/llpreviewanim.h
+++ b/indra/newview/llpreviewanim.h
@@ -46,10 +46,10 @@ public:
static void auditionAnim( void* userdata );
static void endAnimCallback( void *userdata );
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_quitting);
void activate(e_activation_type type);
protected:
- void onClose();
LLAnimPauseRequest mPauseRequest;
LLUUID mItemID;
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index faca950963..32ed20bd56 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -32,10 +32,10 @@
#include "llviewerprecompiledheaders.h"
-#include <algorithm>
-
#include "llpreviewgesture.h"
+#include <algorithm>
+
// libraries
#include "lldatapacker.h"
#include "lldarray.h"
@@ -260,7 +260,8 @@ BOOL LLPreviewGesture::canClose()
}
}
-void LLPreviewGesture::onClose()
+// virtual
+void LLPreviewGesture::onClose(bool app_quitting)
{
LLGestureManager::instance().stopGesture(mPreviewGesture);
}
@@ -354,7 +355,6 @@ LLPreviewGesture::~LLPreviewGesture()
BOOL LLPreviewGesture::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLPreviewGesture::onClose, this));
mVisibleSignal.connect(boost::bind(&LLPreviewGesture::onVisibilityChange, this, _2));
LLLineEditor* edit;
diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h
index 16ac935775..9d26539453 100644
--- a/indra/newview/llpreviewgesture.h
+++ b/indra/newview/llpreviewgesture.h
@@ -70,11 +70,10 @@ public:
// LLFloater
/*virtual*/ BOOL canClose();
+ /*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void onUpdateSucceeded();
/*virtual*/ void refresh();
-
-
protected:
// Populate various comboboxes
void addModifiers();
@@ -108,7 +107,6 @@ protected:
// "Sound", "Chat", or "Wait"
LLScrollListItem* addStep(const enum EStepType step_type);
- void onClose();
void onVisibilityChange ( const LLSD& new_visibility );
static std::string getLabel(std::vector<std::string> labels);
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 26ac95060f..296502ff16 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -273,11 +273,14 @@ public:
LLViewerObject* getFirstCopyableObject(BOOL get_parent = FALSE);
LLViewerObject* getFirstDeleteableObject();
LLViewerObject* getFirstMoveableObject(BOOL get_parent = FALSE);
+
+ /// Return the object that lead to this selection, possible a child
LLViewerObject* getPrimaryObject() { return mPrimaryObject; }
// iterate through texture entries
template <typename T> bool getSelectedTEValue(LLSelectedTEGetFunctor<T>* func, T& res);
-
+ template <typename T> bool isMultipleTEValue(LLSelectedTEGetFunctor<T>* func, const T& ignore_value);
+
void addNode(LLSelectNode *nodep);
void addNodeAtEnd(LLSelectNode *nodep);
void moveNodeToFront(LLSelectNode *nodep);
@@ -783,5 +786,52 @@ template <typename T> bool LLObjectSelection::getSelectedTEValue(LLSelectedTEGet
return identical;
}
+// Templates
+//-----------------------------------------------------------------------------
+// isMultipleTEValue iterate through all TEs and test for uniqueness
+// with certain return value ignored when performing the test.
+// e.g. when testing if the selection has a unique non-empty homeurl :
+// you can set ignore_value = "" and it will only compare among the non-empty
+// homeUrls and ignore the empty ones.
+//-----------------------------------------------------------------------------
+template <typename T> bool LLObjectSelection::isMultipleTEValue(LLSelectedTEGetFunctor<T>* func, const T& ignore_value)
+{
+ bool have_first = false;
+ T selected_value = T();
+
+ // Now iterate through all TEs to test for sameness
+ bool unique = TRUE;
+ for (iterator iter = begin(); iter != end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ for (S32 te = 0; te < object->getNumTEs(); ++te)
+ {
+ if (!node->isTESelected(te))
+ {
+ continue;
+ }
+ T value = func->get(object, te);
+ if(value == ignore_value)
+ {
+ continue;
+ }
+ if (!have_first)
+ {
+ have_first = true;
+ }
+ else
+ {
+ if (value !=selected_value )
+ {
+ unique = false;
+ return !unique;
+ }
+ }
+ }
+ }
+ return !unique;
+}
+
#endif
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 2bb1e80eb8..c5a92f52d0 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -522,7 +522,7 @@ LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&
contactName->setValue(name);
mCloseBtn = getChild<LLButton>("hide_btn");
- mCloseBtn->setCommitCallback(boost::bind(&LLSysWellWindow::RowPanel::onClose, this));
+ mCloseBtn->setCommitCallback(boost::bind(&LLSysWellWindow::RowPanel::onClosePanel, this));
}
//---------------------------------------------------------------------------------
@@ -531,7 +531,7 @@ LLSysWellWindow::RowPanel::~RowPanel()
}
//---------------------------------------------------------------------------------
-void LLSysWellWindow::RowPanel::onClose()
+void LLSysWellWindow::RowPanel::onClosePanel()
{
gIMMgr->removeSession(mChiclet->getSessionId());
// This row panel will be removed from the list in LLSysWellWindow::sessionRemoved().
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 203b949715..0c3f4d0587 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -137,7 +137,7 @@ private:
void onMouseLeave(S32 x, S32 y, MASK mask);
BOOL handleMouseDown(S32 x, S32 y, MASK mask);
private:
- void onClose();
+ void onClosePanel();
public:
LLIMChiclet* mChiclet;
private:
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 9fc91e2971..43f82e592b 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -102,15 +102,16 @@ public:
virtual ~LLFloaterTexturePicker();
// LLView overrides
- virtual BOOL handleDragAndDrop(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);
- virtual void draw();
- virtual BOOL handleKeyHere(KEY key, MASK mask);
+ /*virtual*/ void draw();
+ /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
// LLFloater overrides
- virtual BOOL postBuild();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onClose(bool app_settings);
// New functions
void setImageID( const LLUUID& image_asset_id);
@@ -130,7 +131,6 @@ public:
void commitIfImmediateSet();
void onFilterEdit(const std::string& search_string );
- void onClose();
static void onBtnSetToDefault( void* userdata );
static void onBtnSelect( void* userdata );
@@ -369,7 +369,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)
return LLFloater::handleKeyHere(key, mask);
}
-void LLFloaterTexturePicker::onClose()
+void LLFloaterTexturePicker::onClose(bool app_quitting)
{
if (mOwner)
{
@@ -381,8 +381,6 @@ void LLFloaterTexturePicker::onClose()
// virtual
BOOL LLFloaterTexturePicker::postBuild()
{
- mCloseSignal.connect(boost::bind(&LLFloaterTexturePicker::onClose, this));
-
LLFloater::postBuild();
if (!mLabel.empty())
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index d9be6b172c..e4a3f8603b 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -308,7 +308,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
//gFloaterView->adjustToFitScreen(this, FALSE);
if (mLineEditor)
{
- mLineEditor->setFocus(TRUE);
mLineEditor->selectAll();
}
if(mDefaultOption >= 0)
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 5525c359fc..beb16c267e 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -70,6 +70,7 @@
#include "llworld.h"
#include "llui.h"
#include "llweb.h"
+#include "pipeline.h" // setHighlightObject
extern BOOL gDebugClicks;
@@ -391,24 +392,24 @@ ECursorType cursor_from_object(LLViewerObject* object)
case CLICK_ACTION_SIT:
if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // not already sitting?
{
- cursor = UI_CURSOR_TOOLSIT;
+ cursor = UI_CURSOR_HAND;
}
break;
case CLICK_ACTION_BUY:
- cursor = UI_CURSOR_TOOLBUY;
+ cursor = UI_CURSOR_HAND;
break;
case CLICK_ACTION_OPEN:
// Open always opens the parent.
if (parent && parent->allowOpen())
{
- cursor = UI_CURSOR_TOOLOPEN;
+ cursor = UI_CURSOR_HAND;
}
break;
case CLICK_ACTION_PAY:
if ((object && object->flagTakesMoney())
|| (parent && parent->flagTakesMoney()))
{
- cursor = UI_CURSOR_TOOLPAY;
+ cursor = UI_CURSOR_HAND;
}
break;
case CLICK_ACTION_PLAY:
@@ -472,7 +473,9 @@ void LLToolPie::selectionPropertiesReceived()
BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
{
mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
-
+
+ // Show screen-space highlight glow effect
+ bool show_highlight = false;
LLViewerObject *parent = NULL;
LLViewerObject *object = mHoverPick.getObject();
@@ -483,24 +486,28 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
if (object && useClickAction(mask, object, parent))
{
+ show_highlight = true;
ECursorType cursor = cursor_from_object(object);
gViewerWindow->setCursor(cursor);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
else if (handleMediaHover(mHoverPick))
{
+ show_highlight = true;
// cursor set by media object
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
else if ((object && !object->isAvatar() && object->usePhysics())
|| (parent && !parent->isAvatar() && parent->usePhysics()))
{
+ show_highlight = true;
gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
else if ( (object && object->flagHandleTouch())
|| (parent && parent->flagHandleTouch()))
{
+ show_highlight = true;
gViewerWindow->setCursor(UI_CURSOR_HAND);
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
}
@@ -519,6 +526,15 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
}
}
+ static LLCachedControl<bool> enable_highlight(
+ gSavedSettings, "RenderHighlightEnable", false);
+ LLDrawable* drawable = NULL;
+ if (enable_highlight && show_highlight && object)
+ {
+ drawable = object->mDrawable;
+ }
+ gPipeline.setHighlightObject(drawable);
+
return TRUE;
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 0b21f3565d..8c46949d70 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -83,7 +83,7 @@
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
#include "llfloateropenobject.h"
-#include "llgivemoney.h"
+#include "llfloaterpay.h"
#include "llfloaterparcel.h"
#include "llfloaterperms.h"
#include "llfloaterpostcard.h"
@@ -195,8 +195,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
LLFloaterReg::add("parcel_info", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterParcelInfo>);
- LLFloaterReg::add("pay_resident", "floater_pay.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPay>);
- LLFloaterReg::add("pay_object", "floater_pay_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPay>);
+ LLFloaterPayUtil::registerFloater();
LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>);
LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 2b972614f1..2f55be8b9c 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -588,7 +588,9 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mHasFocus(false),
mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
mDoNavigateOnLoad(false),
+ mDoNavigateOnLoadRediscoverType(false),
mDoNavigateOnLoadServerRequest(false),
+ mMediaSourceFailedInit(false),
mIsUpdated(false)
{
@@ -664,7 +666,7 @@ void LLViewerMediaImpl::createMediaSource()
{
if(! mMediaURL.empty())
{
- navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest);
+ navigateTo(mMediaURL, mMimeType, mDoNavigateOnLoadRediscoverType, mDoNavigateOnLoadServerRequest);
}
else if(! mMimeType.empty())
{
@@ -703,7 +705,7 @@ 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)
{
std::string plugin_basename = LLMIMETypes::implType(media_type);
-
+
if(plugin_basename.empty())
{
LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
@@ -774,6 +776,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
return false;
}
+ // If we got here, we want to ignore previous init failures.
+ mMediaSourceFailedInit = false;
+
LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight);
if (media_source)
@@ -787,6 +792,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
return true;
}
+ // Make sure the timer doesn't try re-initing this plugin repeatedly until something else changes.
+ mMediaSourceFailedInit = true;
+
return false;
}
@@ -1003,14 +1011,7 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::navigateHome()
{
- mMediaURL = mHomeURL;
- mDoNavigateOnLoad = !mMediaURL.empty();
- mDoNavigateOnLoadServerRequest = false;
-
- if(mMediaSource)
- {
- mMediaSource->loadURI( mHomeURL );
- }
+ navigateTo(mHomeURL, "", true, false);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1025,12 +1026,16 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
setNavState(MEDIANAVSTATE_NONE);
}
- // Always set the current URL.
+ // Always set the current URL and MIME type.
mMediaURL = url;
+ mMimeType = mime_type;
// If the current URL is not null, make the instance do a navigate on load.
mDoNavigateOnLoad = !mMediaURL.empty();
+ // if mime type discovery was requested, we'll need to do it when the media loads
+ mDoNavigateOnLoadRediscoverType = rediscover_type;
+
// and if this was a server request, the navigate on load will also need to be one.
mDoNavigateOnLoadServerRequest = server_request;
@@ -1041,6 +1046,21 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
return;
}
+
+ // If the caller has specified a non-empty MIME type, look that up in our MIME types list.
+ // If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
+ // This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
+ // but the parcel owner has correctly set the MIME type in the parcel media settings.
+
+ if(!mMimeType.empty() && (mMimeType != "none/none"))
+ {
+ std::string plugin_basename = LLMIMETypes::implType(mMimeType);
+ if(!plugin_basename.empty())
+ {
+ // We have a plugin for this mime type
+ rediscover_type = false;
+ }
+ }
if(rediscover_type)
{
@@ -1147,7 +1167,7 @@ bool LLViewerMediaImpl::canNavigateBack()
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::update()
{
- if(mMediaSource == NULL)
+ if(mMediaSource == NULL && !mMediaSourceFailedInit)
{
if(mPriority != LLPluginClassMedia::PRIORITY_UNLOADED)
{
@@ -1374,6 +1394,18 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
{
switch(event)
{
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ // The plugin failed to load properly. Make sure the timer doesn't retry.
+ mMediaSourceFailedInit = true;
+
+ // TODO: may want a different message for this case?
+ LLSD args;
+ args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
+ LLNotifications::instance().add("MediaPluginFailed", args);
+ }
+ break;
+
case MEDIA_EVENT_PLUGIN_FAILED:
{
LLSD args;
@@ -1422,7 +1454,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
- setNavState(MEDIANAVSTATE_NONE);
}
break;
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index c9ba5841e9..37aabcf2d6 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -278,7 +278,9 @@ public:
bool mHasFocus;
LLPluginClassMedia::EPriority mPriority;
bool mDoNavigateOnLoad;
+ bool mDoNavigateOnLoadRediscoverType;
bool mDoNavigateOnLoadServerRequest;
+ bool mMediaSourceFailedInit;
private:
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index f9377ab37b..1b1b7cedb1 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -304,7 +304,11 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
BOOL retval = FALSE;
if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia())
{
- mMediaImpl->getMediaPlugin()->scrollEvent(x, y, clicks);
+ // the scrollEvent() API's x and y are not the same as handleScrollWheel's x and y.
+ // The latter is the position of the mouse at the time of the event
+ // The former is the 'scroll amount' in x and y, respectively.
+ // All we have for 'scroll amount' here is 'clicks', and no mask.
+ mMediaImpl->getMediaPlugin()->scrollEvent(0, clicks, /*mask*/0);
retval = TRUE;
}
return retval;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index d95992412f..dde7b1c7ee 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -111,6 +111,7 @@
#include "llfloaterlandholdings.h"
#include "llfloatermap.h"
#include "llfloateropenobject.h"
+#include "llfloaterpay.h"
#include "llfloaterperms.h"
#include "llfloaterpostprocess.h"
#include "llfloaterpreference.h"
@@ -129,7 +130,6 @@
#include "llavataractions.h"
#include "lllandmarkactions.h"
#include "llmemoryview.h"
-#include "llgivemoney.h"
#include "llgroupmgr.h"
#include "lltooltip.h"
#include "llhudeffecttrail.h"
@@ -567,6 +567,15 @@ void init_menus()
gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
+#if !MEM_TRACK_MEM
+ // Don't display the Memory console menu if the feature is turned off
+ LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
+ if (memoryMenu)
+ {
+ memoryMenu->setVisible(FALSE);
+ }
+#endif
+
gMenuBarView->createJumpKeys();
// Let land based option enable when parcel changes
@@ -5405,7 +5414,7 @@ class LLAvatarAddContact : public view_listener_t
}
};
-bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle)
+bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection)
{
S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
@@ -5413,7 +5422,7 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec
gAgent.clearBusy();
}
- LLViewerObject* objectp = handle->getPrimaryObject();
+ LLViewerObject* objectp = selection->getPrimaryObject();
// Show avatar's name if paying attachment
if (objectp && objectp->isAttachment())
@@ -5428,14 +5437,14 @@ bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjec
{
if (objectp->isAvatar())
{
- const BOOL is_group = FALSE;
- LLFloaterPay::payDirectly(&give_money,
+ const bool is_group = false;
+ LLFloaterPayUtil::payDirectly(&give_money,
objectp->getID(),
is_group);
}
else
{
- LLFloaterPay::payViaObject(&give_money, objectp->getID());
+ LLFloaterPayUtil::payViaObject(&give_money, selection);
}
}
return false;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 2e8580907e..aa662b713e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -98,6 +98,7 @@
#include "llnotifications.h"
#include "llnotify.h"
#include "llpanelgrouplandmoney.h"
+#include "llpanelplaces.h"
#include "llrecentpeople.h"
#include "llselectmgr.h"
#include "llsidetray.h"
@@ -138,7 +139,6 @@
#include "llkeythrottle.h"
#include "llgroupactions.h"
#include "llagentui.h"
-#include "llsidetray.h"
#include "llpanelblockedlist.h"
#include "llpanelplaceinfo.h"
@@ -907,14 +907,15 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name)
LLInventoryCategory* parent_folder = gInventory.getCategory(item->getParentUUID());
LLSD args;
args["LANDMARK_NAME"] = item->getName();
- args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unnkown");
+ args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown");
LLNotifications::instance().add("LandmarkCreated", args);
-
- // Open new landmark for editing in Places panel.
- LLSD key;
- key["type"] = "landmark";
- key["id"] = item->getUUID();
- LLSideTray::getInstance()->showPanel("panel_places", key);
+
+ // Created landmark is passed to Places panel to allow its editing.
+ LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", LLSD()));
+ if (panel)
+ {
+ panel->setItem(item);
+ }
}
break;
case LLAssetType::AT_TEXTURE:
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 05011a1568..1f4f1322fd 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -47,7 +47,6 @@
#include "llframetimer.h"
#include "llinventory.h"
#include "llmaterialtable.h"
-#include "llmediadataresponder.h"
#include "llmutelist.h"
#include "llnamevalue.h"
#include "llprimitive.h"
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index a3f9c839a0..9bcdcbf9ad 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -226,11 +226,13 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
media_height,
media_auto_scale,
media_loop);
- sMediaImpl->navigateTo(media_url);
+ sMediaImpl->navigateTo(media_url, mime_type, true);
}
}
else
{
+ LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;
+
// There is no media impl, make a new one
sMediaImpl = LLViewerMedia::newMediaImpl(
placeholder_texture_id,
@@ -238,7 +240,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
media_height,
media_auto_scale,
media_loop);
- sMediaImpl->navigateTo(media_url);
+ sMediaImpl->navigateTo(media_url, mime_type, true);
}
LLFirstUse::useMedia();
@@ -544,6 +546,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
};
break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ {
+ LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
+ };
+ break;
};
}
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 6401389c8f..3c1ac3d571 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6921,7 +6921,8 @@ void LLVoiceClient::notifyFriendObservers()
void LLVoiceClient::lookupName(const LLUUID &id)
{
- gCacheName->get(id, FALSE, &LLVoiceClient::onAvatarNameLookup);
+ BOOL is_group = FALSE;
+ gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
}
//static
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e69779b2dc..1704f63376 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -46,7 +46,6 @@
#include "llvolumemessage.h"
#include "material_codes.h"
#include "message.h"
-#include "llmediadataresponder.h"
#include "llpluginclassmedia.h" // for code in the mediaEvent handler
#include "object_flags.h"
#include "llagentconstants.h"
@@ -69,7 +68,7 @@
#include "pipeline.h"
#include "llsdutil.h"
#include "llmediaentry.h"
-#include "llmediadatafetcher.h"
+#include "llmediadataclient.h"
#include "llagent.h"
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
@@ -86,10 +85,63 @@ F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
F32 LLVOVolume::sDistanceFactor = 1.0f;
S32 LLVOVolume::sNumLODChanges = 0;
+LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
+LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");
static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
+// Implementation class of LLMediaDataClientObject. See llmediadataclient.h
+class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
+{
+public:
+ LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {}
+ LLMediaDataClientObjectImpl() { mObject = NULL; }
+
+ virtual U8 getMediaDataCount() const
+ { return mObject->getNumTEs(); }
+
+ virtual LLSD getMediaDataLLSD(U8 index) const
+ {
+ LLSD result;
+ LLTextureEntry *te = mObject->getTE(index);
+ if (NULL != te)
+ {
+ llassert((te->getMediaData() != NULL) == te->hasMedia());
+ if (te->getMediaData() != NULL)
+ {
+ result = te->getMediaData()->asLLSD();
+ }
+ }
+ return result;
+ }
+
+ virtual LLUUID getID() const
+ { return mObject->getID(); }
+
+ virtual void mediaNavigateBounceBack(U8 index)
+ { mObject->mediaNavigateBounceBack(index); }
+
+ virtual bool hasMedia() const
+ { return mObject->hasMedia(); }
+
+ virtual void updateObjectMediaData(LLSD const &data)
+ { mObject->updateObjectMediaData(data); }
+
+ virtual F64 getDistanceFromAvatar() const
+ { return mObject->getRenderPosition().length(); }
+
+ virtual F64 getTotalMediaInterest() const
+ { return mObject->getTotalMediaInterest(); }
+
+ virtual std::string getCapabilityUrl(const std::string &name) const
+ { return mObject->getRegion()->getCapability(name); }
+
+private:
+ LLPointer<LLVOVolume> mObject;
+};
+
+
LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLViewerObject(id, pcode, regionp),
mVolumeImpl(NULL)
@@ -133,13 +185,19 @@ LLVOVolume::~LLVOVolume()
// static
void LLVOVolume::initClass()
{
- LLMediaDataFetcher::initClass();
+ // gSavedSettings better be around
+ const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
+ const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
+ const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
+ sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries);
+ sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries);
}
// static
void LLVOVolume::cleanupClass()
{
- LLMediaDataFetcher::cleanupClass();
+ sObjectMediaClient = NULL;
+ sObjectMediaNavigateClient = NULL;
}
U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
@@ -316,13 +374,23 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
}
}
}
- if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) {
- // If the media changed at all, request new media data
- if(mMedia)
+ if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED))
+ {
+ // If only the media URL changed, and it isn't a media version URL,
+ // ignore it
+ if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) &&
+ mMedia && ! mMedia->mMediaURL.empty() &&
+ ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) )
{
- llinfos << "Media URL: " << mMedia->mMediaURL << llendl;
+ // If the media changed at all, request new media data
+ LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
+ ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
+ requestMediaDataUpdate();
}
- requestMediaDataUpdate();
+ else {
+ LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
+ ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
+ }
}
// ...and clean up any media impls
cleanUpMediaImpls();
@@ -1621,7 +1689,7 @@ bool LLVOVolume::hasMedia() const
void LLVOVolume::requestMediaDataUpdate()
{
- LLMediaDataFetcher::fetchMedia(this);
+ sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this));
}
void LLVOVolume::cleanUpMediaImpls()
@@ -1700,6 +1768,72 @@ void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool m
// << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
}
+void LLVOVolume::mediaNavigateBounceBack(U8 texture_index)
+{
+ // Find the media entry for this navigate
+ const LLMediaEntry* mep = NULL;
+ viewer_media_t impl = getMediaImpl(texture_index);
+ LLTextureEntry *te = getTE(texture_index);
+ if(te)
+ {
+ mep = te->getMediaData();
+ }
+
+ if (mep && impl)
+ {
+ std::string url = mep->getCurrentURL();
+ if (url.empty())
+ {
+ url = mep->getHomeURL();
+ }
+ if (! url.empty())
+ {
+ LL_INFOS("LLMediaDataClient") << "bouncing back to URL: " << url << LL_ENDL;
+ impl->navigateTo(url, "", false, true);
+ }
+ }
+}
+
+bool LLVOVolume::hasNavigatePermission(const LLMediaEntry* media_entry)
+{
+ // NOTE: This logic duplicates the logic in the server (in particular, in llmediaservice.cpp).
+ if (NULL == media_entry ) return false; // XXX should we assert here?
+
+ // The agent has permissions to navigate if:
+ // - agent has edit permissions, or
+ // - world permissions are on, or
+ // - group permissions are on, and agent_id is in the group, or
+ // - agent permissions are on, and agent_id is the owner
+
+ if (permModify())
+ {
+ return true;
+ }
+
+ U8 media_perms = media_entry->getPermsInteract();
+
+ // World permissions
+ if (0 != (media_perms & LLMediaEntry::PERM_ANYONE))
+ {
+ return true;
+ }
+
+ // Group permissions
+ else if (0 != (media_perms & LLMediaEntry::PERM_GROUP) && permGroupOwner())
+ {
+ return true;
+ }
+
+ // Owner permissions
+ else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner())
+ {
+ return true;
+ }
+
+ return false;
+
+}
+
void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
{
switch(event)
@@ -1733,6 +1867,10 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
{
block_navigation = true;
}
+ if (!block_navigation && !hasNavigatePermission(mep))
+ {
+ block_navigation = true;
+ }
}
else
{
@@ -1744,29 +1882,14 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
llinfos << "blocking navigate to URI " << new_location << llendl;
// "bounce back" to the current URL from the media entry
- // NOTE: the only way block_navigation can be true is if we found the media entry, so we're guaranteed here that mep is not NULL.
- impl->navigateTo(mep->getCurrentURL());
+ mediaNavigateBounceBack(face_index);
}
else
{
llinfos << "broadcasting navigate with URI " << new_location << llendl;
- // Post the navigate to the cap
- std::string cap = getRegion()->getCapability("ObjectMediaNavigate");
- if(cap.empty())
- {
- // XXX *TODO: deal with no cap! It may happen! (retry?)
- LL_WARNS("Media") << "Can't broadcast navigate event -- ObjectMediaNavigate cap is not available" << LL_ENDL;
- return;
- }
-
- // If we got here, the cap is available. Index through all faces that have this media and send the navigate message.
- LLSD sd;
- sd["object_id"] = mID;
- sd["current_url"] = new_location;
- sd["texture_index"] = face_index;
- LLHTTPClient::post(cap, sd, new LLMediaDataResponder("ObjectMediaNavigate", sd, this));
+ sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location);
}
}
break;
@@ -1790,29 +1913,9 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
}
-void LLVOVolume::sendMediaDataUpdate() const
+void LLVOVolume::sendMediaDataUpdate()
{
- std::string url = getRegion()->getCapability("ObjectMedia");
- if (!url.empty())
- {
- LLSD sd_payload;
- sd_payload["verb"] = "UPDATE";
- sd_payload[LLTextureEntry::OBJECT_ID_KEY] = mID;
- LLSD object_media_data;
- for (int i=0; i < getNumTEs(); i++) {
- LLTextureEntry *texture_entry = getTE(i);
- llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia());
- const LLSD &media_data =
- (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD();
- object_media_data.append(media_data);
- }
- sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
-
- llinfos << "Sending media data: " << getID() << " " << ll_pretty_print_sd(sd_payload) << llendl;
-
- LLHTTPClient::post(url, sd_payload, new LLMediaDataResponder("ObjectMedia", sd_payload, this));
- }
- // XXX *TODO: deal with no cap! It may happen! (retry?)
+ sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this));
}
void LLVOVolume::removeMediaImpl(S32 texture_index)
@@ -1905,6 +2008,22 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
return NULL;
}
+F64 LLVOVolume::getTotalMediaInterest() const
+{
+ F64 interest = (F64)0.0;
+ int i = 0;
+ const int end = getNumTEs();
+ for ( ; i < end; ++i)
+ {
+ const viewer_media_t &impl = getMediaImpl(i);
+ if (!impl.isNull())
+ {
+ interest += impl->getInterest();
+ }
+ }
+ return interest;
+}
+
S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id)
{
S32 end = (S32)mMediaImplList.size() ;
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 9a79b620d5..90dfa2204b 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -45,6 +45,8 @@
class LLViewerTextureAnim;
class LLDrawPool;
class LLSelectNode;
+class LLObjectMediaDataClient;
+class LLObjectMediaNavigateClient;
typedef std::vector<viewer_media_t> media_list_t;
@@ -231,17 +233,29 @@ public:
BOOL canBeFlexible() const;
BOOL setIsFlexible(BOOL is_flexible);
- void updateObjectMediaData(const LLSD &media_data_duples);
+ // Functions that deal with media, or media navigation
+
+ // Update this object's media data with the given media data array
+ // (typically this is only called upon a response from a server request)
+ void updateObjectMediaData(const LLSD &media_data_array);
+
+ // Bounce back media at the given index to its current URL (or home URL, if current URL is empty)
+ void mediaNavigateBounceBack(U8 texture_index);
+
+ // Returns whether or not this object has permission to navigate the given media entry
+ bool hasNavigatePermission(const LLMediaEntry* media_entry);
+
void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event);
// Sync the given media data with the impl and the given te
void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent);
// Send media data update to the simulator.
- void sendMediaDataUpdate() const;
+ void sendMediaDataUpdate();
viewer_media_t getMediaImpl(U8 face_id) const;
S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id);
+ F64 getTotalMediaInterest() const;
bool hasMedia() const;
@@ -283,6 +297,9 @@ public:
static F32 sLODFactor; // LOD scale factor
static F32 sDistanceFactor; // LOD distance factor
+ static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
+ static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient;
+
protected:
static S32 sNumLODChanges;
diff --git a/indra/newview/res/toolbuy.cur b/indra/newview/res/toolbuy.cur
deleted file mode 100644
index c61cd76bef..0000000000
--- a/indra/newview/res/toolbuy.cur
+++ /dev/null
Binary files differ
diff --git a/indra/newview/res/toolopen.cur b/indra/newview/res/toolopen.cur
deleted file mode 100644
index 8408f7c7eb..0000000000
--- a/indra/newview/res/toolopen.cur
+++ /dev/null
Binary files differ
diff --git a/indra/newview/res/toolsit.cur b/indra/newview/res/toolsit.cur
deleted file mode 100644
index 60b0e773e5..0000000000
--- a/indra/newview/res/toolsit.cur
+++ /dev/null
Binary files differ
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index 87a8bd5787..4ac48c1857 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -123,10 +123,6 @@ TOOLPICKOBJECT3 CURSOR "toolpickobject3.cur"
ARROWCOPY CURSOR "arrowcop.cur"
ARROWDRAGMULTI CURSOR "llarrowdragmulti.cur"
ARROWCOPYMULTI CURSOR "arrowcopmulti.cur"
-TOOLSIT CURSOR "toolsit.cur"
-TOOLBUY CURSOR "toolbuy.cur"
-TOOLPAY CURSOR "toolpay.cur"
-TOOLOPEN CURSOR "toolopen.cur"
TOOLPIPETTE CURSOR "toolpipette.cur"
TOOLPLAY CURSOR "toolplay.cur"
TOOLPAUSE CURSOR "toolpause.cur"
@@ -138,8 +134,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,0,0
- PRODUCTVERSION 2,0,0,0
+ FILEVERSION 2,0,0,2639
+ PRODUCTVERSION 2,0,0,2639
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -156,12 +152,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Linden Lab"
VALUE "FileDescription", "Second Life"
- VALUE "FileVersion", "2.0.0.0"
+ VALUE "FileVersion", "2.0.0.2639"
VALUE "InternalName", "Second Life"
- VALUE "LegalCopyright", "Copyright 2001-2008, Linden Research, Inc."
+ VALUE "LegalCopyright", "Copyright � 2001-2008, Linden Research, Inc."
VALUE "OriginalFilename", "SecondLife.exe"
VALUE "ProductName", "Second Life"
- VALUE "ProductVersion", "2.0.0.0"
+ VALUE "ProductVersion", "2.0.0.2639"
END
END
BLOCK "VarFileInfo"
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index f106796cd9..2c09689ec6 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -384,12 +384,12 @@
<texture name="TaskPanel_BG" file_name="taskpanel/TaskPanel_BG.png" preload="false" scale.left="4" scale.top="146" scale.right="146" scale.bottom="4" />
<texture name="TaskPanel_Tab_Unselected" file_name="taskpanel/TaskPanel_Tab_Over.png" preload="false" scale.left="5" scale.top="30" scale.right="36" scale.bottom="5" />
- <texture name="TextField_Search_Disabled" file_name="widgets/TextField_Search_Disabled.png" preload="true" scale.left="4" scale.top="18" scale.right="252" scale.bottom="4" />
- <texture name="TextField_Off" file_name="widgets/TextField_Off.png" preload="true" scale.left="4" scale.top="18" scale.right="252" scale.bottom="4" />
- <texture name="TextField_Search_Active" file_name="widgets/TextField_Search_Active.png" preload="true" scale.left="4" scale.top="18" scale.right="252" scale.bottom="4" />
- <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="4" scale.top="18" scale.right="252" scale.bottom="4" />
- <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="4" scale.top="18" scale.right="252" scale.bottom="4" />
- <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="4" scale.top="18" scale.right="252" scale.bottom="4" />
+ <texture name="TextField_Search_Disabled" file_name="widgets/TextField_Search_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Off" file_name="widgets/TextField_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Active" file_name="widgets/TextField_Search_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
<texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
<texture name="Toast" file_name="windows/Toast.png" preload="true" />
@@ -513,11 +513,6 @@
<texture name="toggle_button_off" file_name="toggle_button_off.png" preload="true" />
<texture name="toggle_button_selected" file_name="toggle_button_selected.png" preload="true" />
-<!--TODO: REPLACE CODE REFERENCE TO THIS ART WITH Icon_Minimize_Background above -->
- <texture name="minimize_inactive.tga" preload="true" />
- <texture name="minimize.tga" preload="true" />
- <texture name="minimize_pressed.tga" preload="true" />
-
<texture name="sm_rounded_corners_simple.tga" scale.left="4" scale.top="4" scale.bottom="4" scale.right="4" />
<texture name="rounded_square.tga" file_name="rounded_square.j2c" preload="true" scale.left="16" scale.top="16" scale.right="112" scale.bottom="16" />
diff --git a/indra/newview/skins/default/xui/da/floater_camera.xml b/indra/newview/skins/default/xui/da/floater_camera.xml
index 0eb090d2e4..c52f7ab832 100644
--- a/indra/newview/skins/default/xui/da/floater_camera.xml
+++ b/indra/newview/skins/default/xui/da/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Roter kamera omkring fokus
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Zoom kamera mod fokus
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Flyt kamera op og ned, til venstre og højre
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Flyt kamera op og ned, til venstre og højre"/>
+ <joystick_zoom name="zoom" tool_tip="Zoom kamera mod fokus"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/da/floater_color_picker.xml b/indra/newview/skins/default/xui/da/floater_color_picker.xml
index e6cc5774ed..c8e1fc813b 100644
--- a/indra/newview/skins/default/xui/da/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/da/floater_color_picker.xml
@@ -26,6 +26,6 @@
Nuværende Farve:
</text>
<text name="(Drag below to save.)">
- (Træk ned og gem.)
+ (Træk ned og gem)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_camera.xml b/indra/newview/skins/default/xui/de/floater_camera.xml
index 198b5b07f2..f44db713d8 100644
--- a/indra/newview/skins/default/xui/de/floater_camera.xml
+++ b/indra/newview/skins/default/xui/de/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater">
- <string name="rotate_tooltip">
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
Kamera um Fokus drehen
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Kamera auf Fokus zoomen
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Kamera nach oben, unten, links und rechts bewegen
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Kamera nach oben, unten, links und rechts bewegen"/>
+ <joystick_zoom name="zoom" tool_tip="Kamera auf Fokus zoomen"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_color_picker.xml b/indra/newview/skins/default/xui/de/floater_color_picker.xml
index f53a1135dc..fa2f616249 100644
--- a/indra/newview/skins/default/xui/de/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/de/floater_color_picker.xml
@@ -27,6 +27,6 @@
</text>
<text name="(Drag below to save.)">
(Nach unten ziehen,
- um zu speichern.)
+ um zu speichern)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
index 3ab5c18300..e1f8011cbe 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -55,14 +55,13 @@
width="220">
Type part of a person&apos;s name:
</text>
- <text_editor
+ <line_editor
bevel_style="none"
border_style="line"
border.border_thickness="0"
commit_on_focus_lost="false"
follows="left|top|right"
height="23"
- layout="topleft"
left_delta="0"
name="Edit"
top_pad="0"
@@ -85,38 +84,7 @@
top="52"
width="132" />
</panel>
- <panel
- border="true"
- height="150"
- label="Calling Cards"
- layout="topleft"
- left_delta="-1"
- name="CallingCardsPanel"
- top_delta="134"
- width="135">
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="10"
- name="InstructSelectCallingCard"
- top="8"
- width="220">
- Select a calling card:
- </text>
- <inventory_panel
- allow_multi_select="false"
- border="true"
- follows="left|top|right|bottom"
- height="110"
- layout="topleft"
- left_delta="0"
- name="InventoryPanel"
- top_pad="7"
- width="115" />
- </panel>
+
<panel
border="none"
height="150"
@@ -188,8 +156,8 @@
<button
follows="right|bottom"
height="23"
- label="Ok"
- label_selected="Ok"
+ label="OK"
+ label_selected="OK"
name="Select"
top_pad="3"
left="46"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 053215f8ae..c65206d629 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -2688,7 +2688,7 @@
height="18"
layout="topleft"
left="20"
- max_length="63"
+ read_only="true"
name="media_info"
select_on_focus="true"
top_delta="12"
diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
index 0eb2c5e1be..4f501b65f3 100644
--- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
@@ -1,24 +1,24 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- can_minimize="false"
- height="108"
- layout="topleft"
- name="whitelist_entry"
- width="390">
-
- <text type="string" length="1" bottom="20" follows="top|left" height="15" layout="topleft"
- left="10" name="media_label" top="20">
- Enter a URL or URL pattern to add to the list of allowed domains
- </text>
-
- <line_editor bottom_delta="40" enabled="true" follows="left|top" font="SansSerif"
- height="20" left="10" name="whitelist_entry"
- tool_tip="Enter a URL or URL pattern to White List"
- width="350" />
-
- <button follows="top|left" height="20" font="SansSerifSmall" label="OK"
- layout="topleft" left="10" name="ok_btn" bottom_delta="28" width="64" />
-
- <button follows="top|left" height="20" font="SansSerifSmall" label="Cancel"
- layout="topleft" left_pad="5" name="cancel_btn" bottom_delta="0" width="64" />
-</floater>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_minimize="false"
+ height="108"
+ layout="topleft"
+ name="whitelist_entry"
+ width="390">
+
+ <text type="string" length="1" bottom="20" follows="top|left" height="15" layout="topleft"
+ left="10" name="media_label" top="20">
+ Enter a URL or URL pattern to add to the list of allowed domains
+ </text>
+
+ <line_editor bottom_delta="40" enabled="true" follows="left|top" font="SansSerif"
+ height="20" left="10" name="whitelist_entry"
+ tool_tip="Enter a URL or URL pattern to White List"
+ width="350" />
+
+ <button follows="top|left" height="20" font="SansSerifSmall" label="OK"
+ layout="topleft" left="10" name="ok_btn" bottom_delta="28" width="64" />
+
+ <button follows="top|left" height="20" font="SansSerifSmall" label="Cancel"
+ layout="topleft" left_pad="5" name="cancel_btn" bottom_delta="0" width="64" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index b44acebbcf..1af07c35be 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -5,16 +5,16 @@
-->
<floater
bevel_style="in"
- bg_alpha_color="PanelDefaultBackgroundColor"
+ bg_opaque_color="MouseGray"
can_close="false"
can_minimize="false"
- height="190"
+ height="138"
layout="topleft"
name="inspect_avatar"
single_instance="true"
sound_flags="0"
visible="true"
- width="300">
+ width="245">
<!-- Allowed fields include:
[BORN_ON] ("12/3/2008")
[SL_PROFILE] (Second Life profile),
@@ -36,107 +36,116 @@
Partner: [PARTNER]
</string>
<text
- follows="left|top|right|bottom"
- font="SansSerifHugeBold"
- height="70"
- left="10"
+ follows="all"
+ font="SansSerifLargeBold"
+ height="18"
+ left="8"
name="user_name"
+ top="5"
text_color="white"
- top="20"
use_ellipses="true"
- value="Test Name"
- width="280"
- word_wrap="true" />
- <text
- follows="left|top|right|bottom"
- font="SansSerifBig"
- height="20"
- left="10"
- name="user_subtitle"
- text_color="white"
- top="45"
- width="150" />
+ value="Grumpity ProductEngine"
+ width="240"
+ word_wrap="false" />
<!-- Leave text fields blank so it doesn't flash when data arrives off the network -->
<text
- follows="left|top|right|bottom"
- height="20"
- left="10"
+ follows="all"
+ height="16"
+ left="8"
+ value="Grumpity ProductEngine moose moose"
name="user_details"
- text_color="white"
- top="85"
- width="290"
- word_wrap="true" />
+ top_pad="0"
+ width="170"
+ use_ellipses="true"
+ word_wrap="false" />
<text
- follows="left|top|right|bottom"
- height="20"
- left="10"
+ follows="all"
+ font="SansSerifSmallBold"
+ text_color="White"
+ height="18"
+ left="8"
+ name="user_subtitle"
+ use_ellipses="true"
+ top_pad="0"
+ width="170" />
+ <text
+ follows="all"
+ height="16"
+ left="8"
name="user_partner"
- text_color="white"
- top="105"
- width="290"
- word_wrap="true" />
- <avatar_icon
- follows="left|top|right|bottom"
- height="60"
- left="230"
- mouse_opaque="true"
- name="avatar_icon"
- top="15"
- width="60" />
+ top_pad="8"
+ width="240"
+ use_ellipses="true"
+ word_wrap="false" />
<slider
follows="top|left"
- height="30"
+ height="23"
increment="0.05"
- left="20"
+ left="1"
max_val="0.95"
min_val="0.05"
name="volume_slider"
show_text="false"
tool_tip="Voice Volume"
- top="125"
+ top_pad="0"
value="0.5"
- width="240" />
+ width="150" />
<button
- follows="left|top|right|bottom"
+ follows="all"
height="16"
- image_disabled="icn_speaker_dark.tga"
- image_disabled_selected="icn_speaker-muted_dark.tga"
- image_hover_selected="icn_speaker-muted_dark.tga"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ image_disabled="Inv_Sound"
+ image_disabled_selected="Inv_Sound"
+ image_hover_selected="Inv_Sound"
+ image_selected="Inv_Sound"
+ image_unselected="Inv_Sound"
is_toggle="true"
- left="265"
+ left_pad="0"
+ top_delta="4"
name="mute_btn"
picture_style="true"
- top="132"
- width="32" />
+ width="16" />
+ <avatar_icon
+ follows="all"
+ height="38"
+ right="-25"
+ bevel_style="in"
+ border_style="line"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="24"
+ width="38" />
<button
follows="top|left"
- font="SansSerif"
- height="20"
+ height="18"
+ image_disabled="ForwardArrow_Disabled"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
+ layout="topleft"
+ name="view_profile_btn"
+ picture_style="true"
+ right="-8"
+ top="35"
+ left_delta="110"
+ tab_stop="false"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="23"
label="Add Friend"
- left="10"
+ left="8"
+ top="246"
name="add_friend_btn"
- top_pad="10"
- width="105" />
- <button
- follows="top|left"
- font="SansSerif"
- height="20"
- label="View Profile"
- left_delta="110"
- name="view_profile_btn"
- top_delta="0"
- width="105" />
+ width="100" />
<menu_button
follows="top|left"
- height="20"
- image_overlay="windows\Icon_Gear_Foreground.png"
- image_overlay_alignment="center"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
menu_filename="menu_inspect_avatar_gear.xml"
name="gear_btn"
picture_style="true"
- top_delta="0"
- left_delta="110"
- width="60"/>
+ right="-10"
+ top="249"
+ width="18" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
index cc56f630b0..97df28aa30 100644
--- a/indra/newview/skins/default/xui/en/inspect_object.xml
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -17,8 +17,8 @@
width="300">
<string name="Creator">By [CREATOR]</string>
<string name="CreatorAndOwner">
-By [CREATOR]
-Owned by [OWNER]
+by [CREATOR]
+owner [OWNER]
</string>
<!-- *TODO: Might need to change to [AMOUNT] if icon contains "L$" -->
<string name="Price">L$[AMOUNT]</string>
@@ -28,57 +28,59 @@ Owned by [OWNER]
<text
follows="all"
font="SansSerifLargeBold"
- height="20"
+ height="16"
left="8"
name="object_name"
- text_color="white"
- top="8"
+ text_color="White"
+ top="5"
use_ellipses="true"
value="Test Object Name That Is Really Long"
- width="268" />
+ width="291" />
<text
follows="all"
font="SansSerif"
height="30"
- left="10"
+ left="8"
name="object_creator"
top_pad="0"
- width="280">
-By Longavatarname Johnsonlongstonnammer
-Owned by James Linden
- </text>
- <text
- follows="all"
- height="45"
- left="100"
- name="object_description"
- top_pad="4"
- width="200"
- word_wrap="true">
-This is a really long description for an object being as how it is at least 80 characters in length and maybe more like 120 at this point. Who knows, really?
+ use_ellipses="true"
+ width="275">
+by Longavatarname Johnsonlongstonnammer
+owner James Linden
</text>
<!-- *TODO: Replace this icon -->
<icon
name="price_icon"
- image_name="Favorite_Star_Active"
- left="5"
+ image_name="Icon_For_Sale"
+ left="7"
width="16"
height="16"
- top="79"
+ top="52"
follows="left|top"
/>
<text
follows="all"
font="SansSerifSmallBold"
- height="45"
- left="22"
+ height="16"
+ left_pad="5"
name="price_text"
text_color="white"
- top="80"
+ top="54"
font_shadow="none"
- width="80">
+ width="150">
L$300,000
</text>
+ <text
+ follows="all"
+ height="30"
+ left="8"
+ name="object_description"
+ top_pad="0"
+ width="291"
+ use_ellipses="true"
+ word_wrap="true">
+This is a really long description for an object being as how it is at least 80 characters in length and maybe more like 120 at this point. Who knows, really?
+ </text>
<!-- Overlapping buttons for all default actions. Show "Buy" if
for sale, "Sit" if can sit, etc. -->
<button
@@ -88,7 +90,7 @@ L$300,000
label="Buy"
left="10"
name="buy_btn"
- top="116"
+ top="114"
width="100" />
<button
follows="top|left"
@@ -136,27 +138,30 @@ L$300,000
top_delta="0"
width="100" />
<!-- non-overlapping buttons here -->
- <menu_button
+ <menu_button
follows="top|left"
- height="23"
- image_overlay="Icon_Gear_Foreground"
- image_overlay_alignment="center"
- right="-8"
- menu_filename="menu_inspect_object_gear.xml"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ menu_filename="menu_inspect_avatar_gear.xml"
name="gear_btn"
picture_style="true"
- top_delta="0"
- width="30" />
- <button
+ right="-10"
+ top_delta="5"
+ width="18" />
+ <button
follows="top|left"
- height="22"
- image_overlay="TabIcon_Close_Off"
+ height="18"
+ image_disabled="ForwardArrow_Disabled"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
layout="topleft"
name="more_info_btn"
picture_style="true"
- right="-8"
- top="7"
+ right="-5"
+ top="20"
left_delta="110"
tab_stop="false"
- width="20" />
+ width="18" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/language_settings.xml b/indra/newview/skins/default/xui/en/language_settings.xml
index 71418d446a..c523185034 100644
--- a/indra/newview/skins/default/xui/en/language_settings.xml
+++ b/indra/newview/skins/default/xui/en/language_settings.xml
@@ -6,7 +6,13 @@
<string name="MicrosoftLocale">english</string>
<string name="DarwinLocale">C</string>
<string name="LinuxLocale">C</string>
-
+
+ <!-- Note: for plural nouns, see strings.xml. For example:
+ AgeYearsA = singular,
+ AgeYearsB = plural,
+ AgeYearsC = plural for non-English languages like Russian
+ For example, LLTrans::getCountString("AgeYears", 3) is plural form B
+ in English and form C in Russian -->
<!--
datetimeToCodes["wkday"] = "%a"; // Thu
datetimeToCodes["weekday"] = "%A"; // Thursday
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 2c77f61da6..b0839ce255 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -361,18 +361,6 @@
</menu_item_call>
</menu>
<menu_item_check
- label="Search"
- layout="topleft"
- name="Search"
- shortcut="control|F">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="search" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="search" />
- </menu_item_check>
- <menu_item_check
label="World Map"
layout="topleft"
name="World Map"
@@ -1072,6 +1060,18 @@
name="Shortcuts"
tear_off="true"
visible="false">
+ <menu_item_check
+ label="Search"
+ layout="topleft"
+ name="Search"
+ shortcut="control|F">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="search" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="search" />
+ </menu_item_check>
<menu_item_call
enabled="false"
label="Release Keys"
@@ -2503,7 +2503,6 @@
tear_off="true">
<menu_item_check
label="Axes"
- layout="topleft"
name="Axes">
<menu_item_check.on_check
function="CheckControl"
@@ -2514,7 +2513,6 @@
</menu_item_check>
<menu_item_check
label="Tangent Basis"
- layout="topleft"
name="Tangent Basis">
<menu_item_check.on_check
function="CheckControl"
@@ -2525,7 +2523,6 @@
</menu_item_check>
<menu_item_call
label="Selected Texture Info Basis"
- layout="topleft"
name="Selected Texture Info Basis"
shortcut="control|alt|shift|T">
<menu_item_call.on_click
@@ -2533,7 +2530,6 @@
</menu_item_call>
<menu_item_check
label="Wireframe"
- layout="topleft"
name="Wireframe"
shortcut="control|shift|R">
<menu_item_check.on_check
@@ -2544,7 +2540,6 @@
</menu_item_check>
<menu_item_check
label="Object-Object Occlusion"
- layout="topleft"
name="Object-Object Occlusion"
shortcut="control|shift|O">
<menu_item_check.on_check
@@ -2558,7 +2553,6 @@
</menu_item_check>
<menu_item_check
label="Framebuffer Objects"
- layout="topleft"
name="Framebuffer Objects">
<menu_item_check.on_check
function="CheckControl"
@@ -2571,7 +2565,6 @@
</menu_item_check>
<menu_item_check
label="Deferred Rendering"
- layout="topleft"
name="Deferred Rendering">
<menu_item_check.on_check
function="CheckControl"
@@ -2584,7 +2577,6 @@
</menu_item_check>
<menu_item_check
label="Global Illumintation"
- layout="topleft"
name="Global Illumination">
<menu_item_check.on_check
function="CheckControl"
@@ -2595,10 +2587,11 @@
<menu_item_check.on_enable
function="Advanced.EnableRenderDeferredGI" />
</menu_item_check>
-
+
+ <menu_item_separator />
+
<menu_item_check
label="Debug GL"
- layout="topleft"
name="Debug GL">
<menu_item_check.on_check
function="CheckControl"
@@ -2609,7 +2602,6 @@
</menu_item_check>
<menu_item_check
label="Debug Pipeline"
- layout="topleft"
name="Debug Pipeline">
<menu_item_check.on_check
function="CheckControl"
@@ -2620,7 +2612,6 @@
</menu_item_check>
<menu_item_check
label="Fast Alpha"
- layout="topleft"
name="Fast Alpha">
<menu_item_check.on_check
function="CheckControl"
@@ -2631,7 +2622,6 @@
</menu_item_check>
<menu_item_check
label="Animation Textures"
- layout="topleft"
name="Animation Textures">
<menu_item_check.on_check
function="CheckControl"
@@ -2642,7 +2632,6 @@
</menu_item_check>
<menu_item_check
label="Disable Textures"
- layout="topleft"
name="Disable Textures">
<menu_item_check.on_check
function="Advanced.CheckDisableTextures"
@@ -2652,7 +2641,6 @@
</menu_item_check>
<menu_item_check
label="Texture Atlas"
- layout="topleft"
name="Texture Atlas">
<menu_item_check.on_check
function="Advanced.CheckTextureAtlas"
@@ -2662,7 +2650,6 @@
</menu_item_check>
<menu_item_check
label="Render Attached Lights"
- layout="topleft"
name="Render Attached Lights">
<menu_item_check.on_check
function="CheckControl"
@@ -2673,7 +2660,6 @@
</menu_item_check>
<menu_item_check
label="Render Attached Particles"
- layout="topleft"
name="Render Attached Particles">
<menu_item_check.on_check
function="CheckControl"
@@ -2682,6 +2668,16 @@
function="Advanced.HandleAttchedLightParticles"
parameter="RenderAttachedParticles" />
</menu_item_check>
+ <menu_item_check
+ label="Hover Highlight Objects"
+ name="Hover Highlight Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderHighlightEnable" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderHighlightEnable" />
+ </menu_item_check>
</menu>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 829c2e02d8..f141a909a8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -761,7 +761,7 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now?
name="url"
openexternally = "1">
- http://join/secondlife.com/
+ http://join.secondlife.com/
</url>
<usetemplate
name="okcancelbuttons"
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
index 1e7ca7aa3f..f1e2560356 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
@@ -64,7 +64,7 @@
<web_browser
border_visible="false"
- bottom_delta="-120"
+ bottom_delta="-133"
follows="top|left"
left="120"
name="preview_media"
@@ -83,7 +83,7 @@
</text>
<text
- bottom_delta="-20"
+ bottom_delta="-5"
follows="top|left"
height="15"
left="10"
@@ -161,39 +161,92 @@
radio_style="false"
width="150" />
- <check_box bottom_delta="-25" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Use Default Alternative Image" left="10" mouse_opaque="true"
- name="alt_image_enable" radio_style="false" width="150" />
+ <check_box
+ bottom_delta="-25"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Use Default Alternative Image"
+ left="10"
+ mouse_opaque="true"
+ name="alt_image_enable"
+ radio_style="false"
+ width="150" />
- <check_box bottom_delta="-25" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Auto Play Media" left="10" mouse_opaque="true"
- name="auto_play" radio_style="false" width="150" />
- <text bottom_delta="-14" follows="top|left" height="15" left="30" width="340"
- enabled="false" name="">
+ <check_box
+ bottom_delta="-25"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Auto Play Media"
+ left="10"
+ mouse_opaque="true"
+ name="auto_play"
+ radio_style="false"
+ width="150" />
+
+ <text
+ bottom_delta="-14"
+ follows="top|left"
+ height="15"
+ left="30"
+ width="340"
+ enabled="false"
+ name="meida_setting_note">
Note: Residents can override this setting
</text>
- <check_box bottom_delta="-25" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Auto Scale Media on Face of Object" left="10" mouse_opaque="true"
- name="auto_scale" radio_style="false" width="150" />
- <text bottom_delta="-20" follows="top|left" height="15" left="30" name="">
+ <check_box
+ bottom_delta="-25"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Auto Scale Media on Face of Object"
+ left="10"
+ mouse_opaque="true"
+ name="auto_scale"
+ radio_style="false"
+ width="150" />
+
+ <text
+ bottom_delta="-20"
+ follows="top|left"
+ height="15"
+ left="30"
+ name="">
Size:
</text>
- <spinner bottom_delta="0"
- decimal_digits="0" enabled="true" follows="left|top" height="16"
- increment="1" initial_val="256" label="" label_width="0"
- left_delta="40" max_val="2000" min_val="0" mouse_opaque="true"
- name="width_pixels" width="50" />
+
+ <spinner
+ bottom_delta="0"
+ decimal_digits="0"
+ enabled="true"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_val="256"
+ label=""
+ label_width="0"
+ left_delta="40"
+ max_val="2048"
+ min_val="0"
+ mouse_opaque="true"
+ name="width_pixels"
+ width="50" />
+
<text bottom_delta="0" follows="top|left" height="15" left_delta="60" name="">
X
</text>
<spinner bottom_delta="0"
decimal_digits="0" enabled="true" follows="left|top" height="16"
increment="1" initial_val="256" label="" label_width="0"
- left_delta="20" max_val="2000" min_val="0" mouse_opaque="true"
+ left_delta="20" max_val="2048" min_val="0" mouse_opaque="true"
name="height_pixels" width="50" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
index f11364874a..0cc1406d62 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
@@ -1,49 +1,137 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel border="true" enabled="true" follows="left|top|right|bottom"
- height="500" label="Controls" left="102" mouse_opaque="true"
- name="Media settings for controls" width="365">
+<panel
+ border="true"
+ enabled="true"
+ follows="left|top|right|bottom"
+ height="500"
+ label="Controls"
+ left="102"
+ mouse_opaque="true"
+ name="Media settings for controls"
+ width="365">
- <text bottom_delta="-50" follows="top|left" height="15" left="10" name="" enabled="false">
+ <text
+ bottom_delta="-50"
+ follows="top|left"
+ height="15"
+ left="10"
+ name="media_perms_label_owner"
+ enabled="false">
Owner
</text>
- <check_box bottom_delta="-22" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Disable Navigation &amp; Interactivity" left="30" mouse_opaque="true"
- name="perms_owner_interact" radio_style="false" width="250" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Disable Navigation &amp; Interactivity"
+ left="30"
+ mouse_opaque="true"
+ name="perms_owner_interact"
+ radio_style="false"
+ width="250" />
- <check_box bottom_delta="-22" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Hide Control Bar" left="30" mouse_opaque="true"
- name="perms_owner_control" radio_style="false" width="250" />
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Hide Control Bar"
+ left="30"
+ mouse_opaque="true"
+ name="perms_owner_control"
+ radio_style="false"
+ width="250" />
- <text bottom_delta="-36" follows="top|left" height="15" left="10" name="perms_group_name_label" enabled="false">
+ <text
+ bottom_delta="-36"
+ follows="top|left"
+ height="15"
+ left="10"
+ name="media_perms_label_group"
+ enabled="false">
Group
</text>
- <name_box bottom_delta="-5" enabled="false" follows="left|top" font="SansSerif"
- height="20" left="60" name="perms_group_name"
- value =""
- width="200" />
- <check_box bottom_delta="-22" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Disable Navigation &amp; Interactivity" left="30" mouse_opaque="true"
- name="perms_group_interact" radio_style="false" width="250" />
+
+ <name_box
+ bottom_delta="-5"
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ height="20" left="60"
+ name="perms_group_name"
+ value =""
+ width="200" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Disable Navigation &amp; Interactivity"
+ left="30"
+ mouse_opaque="true"
+ name="perms_group_interact"
+ radio_style="false"
+ width="250" />
- <check_box bottom_delta="-22" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Hide Control Bar" left="30" mouse_opaque="true"
- name="perms_group_control" radio_style="false" width="250" />
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Hide Control Bar"
+ left="30"
+ mouse_opaque="true"
+ name="perms_group_control"
+ radio_style="false"
+ width="250" />
- <text bottom_delta="-36" follows="top|left" height="15" left="10" name="" enabled="false">
+ <text
+ bottom_delta="-36"
+ follows="top|left"
+ height="15"
+ left="10"
+ name="media_perms_label_anyone"
+ enabled="false">
Anyone
</text>
- <check_box bottom_delta="-22" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Disable Navigation &amp; Interactivity" left="30" mouse_opaque="true"
- name="perms_anyone_interact" radio_style="false" width="250" />
+
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Disable Navigation &amp; Interactivity"
+ left="30"
+ mouse_opaque="true"
+ name="perms_anyone_interact"
+ radio_style="false"
+ width="250" />
- <check_box bottom_delta="-22" enabled="true" follows="left|top" font="SansSerifSmall"
- height="16" initial_value="false"
- label="Hide Control Bar" left="30" mouse_opaque="true"
- name="perms_anyone_control" radio_style="false" width="250" />
+ <check_box
+ bottom_delta="-22"
+ enabled="true"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Hide Control Bar"
+ left="30"
+ mouse_opaque="true"
+ name="perms_anyone_control"
+ radio_style="false"
+ width="250" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 8b9fe2cf77..696e0b3c33 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -60,7 +60,7 @@
left="5"
name="teleport_btn"
top="0"
- width="90" />
+ width="70" />
<button
follows="bottom|left"
font="SansSerifSmallBold"
@@ -70,7 +70,7 @@
left_pad="5"
name="map_btn"
top="0"
- width="80" />
+ width="50" />
<button
enabled="false"
follows="bottom|left"
@@ -83,40 +83,54 @@
top="0"
width="60" />
<button
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="edit_btn"
+ top="0"
+ width="50" />
+ <button
follows="bottom|right"
font="SansSerifSmallBold"
height="25"
label="▼"
layout="topleft"
- left_pad="5"
name="overflow_btn"
+ right="-10"
top="0"
width="30" />
<button
- follows="bottom|left"
+ follows="bottom|right"
font="SansSerifSmallBold"
height="25"
- image_disabled="widgets/SegmentedBtn_Left_Disabled.png"
- image_selected="widgets/SegmentedBtn_Left_Selected.png"
- image_unselected="widgets/SegmentedBtn_Left_Off.png"
- label="Create"
+ label="Close"
layout="topleft"
- left="5"
- name="create_landmark_btn"
+ name="close_btn"
+ right="-10"
top="0"
- width="70" />
+ width="60" />
<button
- follows="bottom|left"
+ follows="bottom|right"
font="SansSerifSmallBold"
height="25"
- image_disabled="widgets/ComboButton_Disabled.png"
- image_selected="widgets/ComboButton_Selected.png"
- image_unselected="widgets/ComboButton_Off.png"
- label="▼"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-10"
+ top="0"
+ width="60" />
+ <button
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Save"
layout="topleft"
- left_pad="0"
- name="folder_menu_btn"
+ name="save_btn"
+ right="-75"
top="0"
- width="20" />
+ width="60" />
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
index 3b1b049ff2..9845a9eb78 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml
@@ -4,7 +4,7 @@
bottom="0"
follows="left|top|right"
height="30"
- width="305"
+ width="333"
layout="topleft"
left="0"
name="sidetray_tab_panel">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 3a5347fe12..d124a4cdfa 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -44,23 +44,12 @@
<!-- Tooltip, lltooltipview.cpp -->
- <!-- *TODO: Most of these are now unused, eliminate them -->
<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
<string name="TooltipOwner">Owner:</string> <!-- Owner name follows -->
<string name="TooltipPublic">Public</string> <!-- Public permissions on an object -->
<string name="TooltipIsGroup">(Group)</string> <!-- The name before this text is that of a group -->
- <string name="TooltipFlagScript">Script</string>
- <string name="TooltipFlagPhysics">Physics</string>
- <string name="TooltipFlagTouch">Touch</string>
- <string name="TooltipFlagL$">L$</string>
- <string name="TooltipFlagDropInventory">Drop Inventory</string>
- <string name="TooltipFlagPhantom">Phantom</string>
- <string name="TooltipFlagTemporary">Temporary</string>
- <string name="TooltipFlagRightClickMenu">(Right-click for menu)</string>
- <string name="TooltipFreeToCopy">Free to copy</string>
<string name="TooltipForSaleL$">For Sale: L$[AMOUNT]</string> <!-- L$ version -->
- <string name="TooltipForSaleMsg">For Sale: [MESSAGE]</string> <!-- Message (RetrievingData) -->
<string name="TooltipFlagGroupBuild">Group Build</string>
<string name="TooltipFlagNoBuild">No Build</string>
<string name="TooltipFlagNoEdit">Group Build</string>
@@ -1940,16 +1929,23 @@ this texture in your inventory
<string name="DaysOld">[AGEDAYS] old</string>
<string name="TodayOld">Joined today</string>
- <!-- AgeYearsA = singular, AgeYearsB = plural, see logic in
- LLTrans::getCountString() -->
+ <!-- AgeYearsA = singular,
+ AgeYearsB = plural,
+ AgeYearsC = plural for non-English languages like Russian
+ For example, LLTrans::getCountString("AgeYears", 3) is plural form B
+ in English and form C in Russian -->
<string name="AgeYearsA">[COUNT] year</string>
<string name="AgeYearsB">[COUNT] years</string>
+ <string name="AgeYearsC">[COUNT] years</string>
<string name="AgeMonthsA">[COUNT] month</string>
<string name="AgeMonthsB">[COUNT] months</string>
+ <string name="AgeMonthsC">[COUNT] months</string>
<string name="AgeWeeksA">[COUNT] week</string>
<string name="AgeWeeksB">[COUNT] weeks</string>
+ <string name="AgeWeeksC">[COUNT] weeks</string>
<string name="AgeDaysA">[COUNT] day</string>
<string name="AgeDaysB">[COUNT] days</string>
+ <string name="AgeDaysC">[COUNT] days</string>
<!-- Account types, see LLAvatarPropertiesProcessor -->
<string name="AcctTypeResident">Resident</string>
@@ -2177,6 +2173,9 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
<string name="'">'</string>
<string name="---">---</string>
+ <!-- media -->
+ <string name="Multiple Media">Multiple Media</string>
+
<!-- OSMessageBox messages -->
<string name="MBCmdLineError">
An error was found parsing the command line.
@@ -2246,225 +2245,585 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
</string>
<!-- Avatar Shape Information -->
- <string name="Attached Earlobes">Attached Earlobes</string>
- <string name="Arm Length">Arm Length</string>
- <string name="Back Bangs Down">Back Bangs Down</string>
- <string name="Back Bangs Up">Back Bangs Up</string>
- <string name="Back Hair Down">Back Hair Down</string>
- <string name="Back Hair Up">Back Hair Up</string>
- <string name="Belly Size">Belly Size</string>
- <string name="Blonde Hair">Blonde Hair</string>
- <string name="Big Eyeball">Big Eyeball</string>
- <string name="Big Hair Back">Big Hair: Back</string>
- <string name="Big Hair Front">Big Hair: Front</string>
- <string name="Big Hair Top">Big Hair: Top</string>
- <string name="Body Fat">Body Fat</string>
- <string name="Body Thickness">Body Thickness</string>
- <string name="Breast Buoyancy">Breast Buoyancy</string>
- <string name="Breast Cleavage">Breast Cleavage</string>
- <string name="Breast Size">Breast Size</string>
- <string name="Bridge Width">Bridge Width</string>
- <string name="Brow Size">Brow Size</string>
- <string name="Butt Size">Butt Size</string>
- <string name="Cheek Bones">Cheek Bones</string>
- <string name="Chest Size">Chest Size</string>
- <string name="Chin Angle">Chin Angle</string>
- <string name="Chin Cleft">Chin Cleft</string>
- <string name="Chin Depth">Chin Depth</string>
- <string name="Chin-Neck">Chin-Neck</string>
- <string name="Collar Back">Collar Back</string>
- <string name="Collar Front">Collar Front</string>
- <string name="Crooked Nose">Crooked Nose</string>
- <string name="Cuff Flare">Cuff Flare</string>
- <string name="Ear Angle">Ear Angle</string>
- <string name="Ear Size">Ear Size</string>
- <string name="Ear Tips">Ear Tips</string>
- <string name="Egg Head">Egg Head</string>
- <string name="Eye Bags">Eye Bags</string>
- <string name="Eye Color">Eye Color</string>
- <string name="Eye Depth">Eye Depth</string>
- <string name="Eye Lightness">Eye Lightness</string>
- <string name="Eye Opening">Eye Opening</string>
- <string name="Eye Pop">Eye Pop</string>
- <string name="Eye Size">Eye Size</string>
- <string name="Eye Spacing">Eye Spacing</string>
- <string name="Eyeball Size">Eyeball Size</string>
- <string name="Eyebrow Arc">Eyebrow Arc</string>
- <string name="Eyebrow Height">Eyebrow Height</string>
- <string name="Eyebrow Points">Eyebrow Points</string>
- <string name="Eyelash Length">Eyelash Length</string>
- <string name="Eyeliner">Eyeliner</string>
- <string name="Eyeliner Color">Eyeliner Color</string>
- <string name="Face Shear">Face Shear</string>
- <string name="Facial Definitionr">Facial Definition</string>
- <string name="Fat Head">Fat Head</string>
- <string name="Fat Lower Lip">Fat Lower Lip</string>
- <string name="Fat Torso">Fat Torso</string>
- <string name="Fat Upper Lip">Fat Upper Lip</string>
- <string name="Foot Size">Foot Size</string>
- <string name="Freckles">Freckles</string>
- <string name="Front Bangs Down">Front Bangs Down</string>
- <string name="Front Bangs Up">Front Bangs Up</string>
- <string name="Front Hair Down">Front Hair Down</string>
- <string name="Front Hair Up">Front Hair Up</string>
- <string name="Forehead Angle">Forehead Angle</string>
- <string name="Full Hair Sides">Full Hair Sides</string>
- <string name="Glove Fingers">Glove Fingers</string>
- <string name="Glove Length">Glove Length</string>
- <string name="Hair Thickess">Hair Thickess</string>
- <string name="Hair Tilted Left">Hair Tilted Left</string>
- <string name="Hair Tilted Right">Hair Tilted Right</string>
- <string name="Hair Volume">Hair: Volume</string>
- <string name="Hand Size">Hand Size</string>
- <string name="Head Length">Head Length</string>
- <string name="Head Shape">Head Shape</string>
- <string name="Head Size">Head Size</string>
- <string name="Head Stretch">Head Stretch</string>
- <string name="Heel Height">Heel Height</string>
- <string name="Heel Shape">Heel Shape</string>
- <string name="Height">Height</string>
- <string name="Hip Width">Hip Width</string>
- <string name="Hip Length">Hip Length</string>
- <string name="Inner Eye Corner">Inner Eye Corner</string>
- <string name="Jacket Length">Jacket Length</string>
- <string name="Jacket Wrinkles">Jacket Wrinkles</string>
- <string name="Jowls">Jowls</string>
- <string name="Jaw Angle">Jaw Angle</string>
- <string name="Jaw Jut">Jaw Jut</string>
- <string name="Jaw Shape">Jaw Shape</string>
- <string name="Knee Angle">Knee Angle</string>
- <string name="Left Part">Left Part</string>
- <string name="Leg Muscles">Leg Muscles</string>
- <string name="Leg Length">Leg Length</string>
- <string name="Lip Cleft">Lip Cleft</string>
- <string name="Lip Cleft Depth">Lip Cleft Depth</string>
- <string name="Lip Fullness">Lip Fullness</string>
- <string name="Lip Pinkness">Lip Pinkness</string>
- <string name="Lip Ratio">Lip Ratio</string>
- <string name="Lip Thickness">Lip Thickness</string>
- <string name="Lip Width">Lip Width</string>
- <string name="Longcuffs">Longcuffs</string>
- <string name="Love Handles">Love Handles</string>
- <string name="Lower Bridge">Lower Bridge</string>
- <string name="Lower Cheeks">Lower Cheeks</string>
- <string name="Middle Part">Middle Part</string>
- <string name="Mouth Corner">Mouth Corner</string>
- <string name="Mouth Position">Mouth Position</string>
- <string name="Nail Polish">Nail Polish</string>
- <string name="Nail Polish Color">Nail Polish Color</string>
- <string name="Neck Length">Neck Length</string>
- <string name="Neck Thickness">Neck Thickness</string>
- <string name="Nose Size">Nose Size</string>
- <string name="Nose Thickness">Nose Thickness</string>
- <string name="Nose Tip Angle">Nose Tip Angle</string>
- <string name="Nose Tip Shape">Nose Tip Shape</string>
- <string name="Nose Width">Nose Width</string>
- <string name="Nostril Division">Nostril Division</string>
- <string name="Nostril Width">Nostril Width</string>
- <string name="Open Front">Open Front</string>
- <string name="Lipstick Color">Lipstick Color</string>
- <string name="Lipstick">Lipstick</string>
- <string name="Lipgloss">Lipgloss</string>
- <string name="Blush">Blush</string>
- <string name="Blush Color">Blush Color</string>
- <string name="Blush Opacity">Blush Opacity</string>
- <string name="Inner Shadow">Inner Shadow</string>
- <string name="In Shdw Color">Inner Shadow Color</string>
- <string name="In Shdw Opacity">Inner Shadow Opacity</string>
- <string name="Body Definition">Body Definition</string>
- <string name="Body Freckles">Body Freckles</string>
- <string name="Facial Definition">Facial Definition</string>
- <string name="Hair Front">Hair: Front</string>
- <string name="Hair Sides">Hair: Sides</string>
- <string name="Hair Back">Hair: Back</string>
- <string name="Front Fringe">Front Fringe</string>
- <string name="Side Fringe">Side Fringe</string>
- <string name="Back Fringe">Back Fringe</string>
- <string name="Hair Sweep">Hair Sweep</string>
- <string name="Pigtails">Pigtails</string>
- <string name="Ponytail">Ponytail</string>
- <string name="Hair Tilt">Hair Tilt</string>
- <string name="Eyebrow Size">Eyebrow Size</string>
- <string name="Eyebrow Density">Eyebrow Density</string>
- <!-- string name="Hair Thickess">Hair Thickess</string Need a second string for Body Parts > Hair > Facial? -->
- <string name="Sideburns">Sideburns</string>
- <string name="Moustache">Moustache</string>
- <string name="Soulpatch">Soulpatch</string>
- <string name="Chin Curtains">Chin Curtains</string>
- <string name="Outer Eye Corner">Outer Eye Corner</string>
- <string name="Outer Shadow">Outer Shadow</string>
- <string name="Out Shdw Opacity">Outer Shadow Opacity</string>
- <string name="Out Shdw Color">Outer Shadow Color</string>
- <string name="Package">Package</string>
- <string name="Pants Crotch">Pants Crotch</string>
- <string name="Pants Fit">Pants Fit</string>
- <string name="Pants Length">Pants Length</string>
- <string name="Pants Waist">Pants Waist</string>
- <string name="Pants Wrinkles">Pants Wrinkles</string>
- <string name="Part Bangs">Part Bangs</string>
- <string name="Pectorals">Pectorals</string>
- <string name="Platform Height">Platform Height</string>
- <string name="Platform Width">Platform Width</string>
- <string name="Pigment">Pigment</string>
- <string name="Puffy Eyelids">Puffy Eyelids</string>
- <string name="Rainbow Color">Rainbow Color</string>
- <string name="Red Hair">Red Hair</string>
- <string name="Right Part">Right Part</string>
- <string name="Round Forehead">Round Forehead</string>
- <string name="Rosy Complexion">Rosy Complexion</string>
- <string name="Ruddiness">Ruddiness</string>
- <string name="Rumpled Hair">Rumpled Hair</string>
- <string name="Saddle Bags">Saddle Bags</string>
- <string name="Scrawny Leg">Scrawny Leg</string>
- <string name="Shear Back">Shear Back</string>
- <string name="Shear Face">Shear Face</string>
- <string name="Shear Front">Shear Front</string>
- <string name="Shift Mouth">Shift Mouth</string>
- <string name="Shirt Bottom">Shirt Bottom</string>
- <string name="Shirt Fit">Shirt Fit</string>
- <string name="Shirt Wrinkles">Shirt Wrinkles</string>
- <string name="Shoe Height">Shoe Height</string>
- <string name="Shoulders">Shoulders</string>
- <string name="Side Bangs Down">Side Bangs Down</string>
- <string name="Side Bangs Up">Side Bangs Up</string>
- <string name="Sides Hair Down">Sides Hair Down</string>
- <string name="Sides Hair Up">Sides Hair Up</string>
- <string name="Skirt Fit">Skirt Fit</string>
- <string name="Skirt Length">Skirt Length</string>
- <string name="Slanted Forehead">Slanted Forehead</string>
- <string name="Sleeve Length">Sleeve Length</string>
- <string name="Sleeve Looseness">Sleeve Looseness</string>
- <string name="Slit Back">Slit: Back</string>
- <string name="Slit Front">Slit: Front</string>
- <string name="Slit Left">Slit: Left</string>
- <string name="Slit Right">Slit: Right</string>
- <string name="Socks Length">Socks Length</string>
- <string name="Spiked Hair">Spiked Hair</string>
- <string name="Squash/Stretch Head">Squash/Stretch Head</string>
- <string name="Swept Back Hair">Swept Back Hair</string>
- <string name="Swept Forward Hair">Swept Forward Hair</string>
- <string name="Taper Back">Taper Back</string>
- <string name="Taper Front">Taper Front</string>
- <string name="Toe Shape">Toe Shape</string>
- <string name="Toe Thickness">Toe Thickness</string>
- <string name="Toe Length">Toe Length</string>
- <string name="Torso Length">Torso Length</string>
- <string name="Torso Muscles">Torso Muscles</string>
- <string name="Torso Scrawny">Torso Scrawny</string>
- <string name="Upper Bridge">Upper Bridge</string>
- <string name="Upper Cheeks">Upper Cheeks</string>
- <string name="Upper Chin Cleft">Upper Chin Cleft</string>
- <string name="Upper Eyelid Fold">Upper Eyelid Fold</string>
- <string name="Waist Height">Waist Height</string>
- <string name="White Hair">White Hair</string>
- <string name="big belly skirt">big belly skirt</string>
- <string name="bigbutt skirt">bigbutt skirt</string>
- <string name="bustle skirt">Bustle Skirt</string>
- <string name="legs skirt">legs skirt</string>
- <string name="loose skirt">loose skirt</string>
- <string name="poofy skirt">poofy skirt</string>
- <string name="tight skirt">tight skirt</string>
- <string name="wrinkles">Wrinkles</string>
+<string name="5 O'Clock Shadow">5 O'Clock Shadow</string>
+<string name="5 O'Clock Shadow bump">5 O'Clock Shadow bump</string>
+<string name="All White">All White</string>
+<string name="Anime Eyes">Anime Eyes</string>
+<string name="Arced">Arced</string>
+<string name="Arm Length">Arm Length</string>
+<string name="Attached">Attached</string>
+<string name="Attached Earlobes">Attached Earlobes</string>
+<string name="BELLY">BELLY</string>
+<string name="Back Bangs">Back Bangs</string>
+<string name="Back Bangs Down">Back Bangs Down</string>
+<string name="Back Bangs Up">Back Bangs Up</string>
+<string name="Back Fringe">Back Fringe</string>
+<string name="Back Hair">Back Hair</string>
+<string name="Back Hair Down">Back Hair Down</string>
+<string name="Back Hair Up">Back Hair Up</string>
+<string name="Baggy">Baggy</string>
+<string name="Bangs">Bangs</string>
+<string name="Bangs Down">Bangs Down</string>
+<string name="Bangs Up">Bangs Up</string>
+<string name="Beady Eyes">Beady Eyes</string>
+<string name="Belly Size">Belly Size</string>
+<string name="Big">Big</string>
+<string name="Big Butt">Big Butt</string>
+<string name="Big Eyeball">Big Eyeball</string>
+<string name="Big Hair Back">Big Hair Back</string>
+<string name="Big Hair Front">Big Hair Front</string>
+<string name="Big Hair Top">Big Hair Top</string>
+<string name="Big Head">Big Head</string>
+<string name="Big Pectorals">Big Pectorals</string>
+<string name="Big Spikes">Big Spikes</string>
+<string name="Black">Black</string>
+<string name="Blonde">Blonde</string>
+<string name="Blonde Hair">Blonde Hair</string>
+<string name="Blush">Blush</string>
+<string name="Blush Color">Blush Color</string>
+<string name="Blush Opacity">Blush Opacity</string>
+<string name="Body Definition">Body Definition</string>
+<string name="Body Fat">Body Fat</string>
+<string name="Body Freckles">Body Freckles</string>
+<string name="Body Thick">Body Thick</string>
+<string name="Body Thickness">Body Thickness</string>
+<string name="Body Thin">Body Thin</string>
+<string name="Bottom">Bottom</string>
+<string name="Bottom Left">Bottom Left</string>
+<string name="Bottom Right">Bottom Right</string>
+<string name="Bottom bump">Bottom bump</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 Size">Breast Size</string>
+<string name="Bridge Width">Bridge Width</string>
+<string name="Broad">Broad</string>
+<string name="Brow Size">Brow Size</string>
+<string name="Bug Eyes">Bug Eyes</string>
+<string name="Bugged Eyes">Bugged Eyes</string>
+<string name="Bulbous">Bulbous</string>
+<string name="Bulbous Nose">Bulbous Nose</string>
+<string name="Bump base">Bump base</string>
+<string name="Bump upperdef">Bump upperdef</string>
+<string name="Bushy Eyebrows">Bushy Eyebrows</string>
+<string name="Bushy Hair">Bushy Hair</string>
+<string name="Butt Size">Butt Size</string>
+<string name="CHEST">CHEST</string>
+<string name="Center">Center</string>
+<string name="Center 2">Center 2</string>
+<string name="Chaplin">Chaplin</string>
+<string name="Cheek Bones">Cheek Bones</string>
+<string name="Chest">Chest</string>
+<string name="Chest Size">Chest Size</string>
+<string name="Chin">Chin</string>
+<string name="Chin Angle">Chin Angle</string>
+<string name="Chin Cleft">Chin Cleft</string>
+<string name="Chin Curtains">Chin Curtains</string>
+<string name="Chin Curtains bump">Chin Curtains bump</string>
+<string name="Chin Depth">Chin Depth</string>
+<string name="Chin Heavy">Chin Heavy</string>
+<string name="Chin In">Chin In</string>
+<string name="Chin Out">Chin Out</string>
+<string name="Chin-Neck">Chin-Neck</string>
+<string name="Clear">Clear</string>
+<string name="Cleft">Cleft</string>
+<string name="Close Set Eyes">Close Set Eyes</string>
+<string name="Closed">Closed</string>
+<string name="Closed Back">Closed Back</string>
+<string name="Closed Front">Closed Front</string>
+<string name="Closed Left">Closed Left</string>
+<string name="Closed Right">Closed Right</string>
+<string name="Coin Purse">Coin Purse</string>
+<string name="Collar Back">Collar Back</string>
+<string name="Collar Back Height Cloth">Collar Back Height Cloth</string>
+<string name="Collar Back Shadow Height">Collar Back Shadow Height</string>
+<string name="Collar Back bump">Collar Back bump</string>
+<string name="Collar Front">Collar Front</string>
+<string name="Collar Front Height Cloth">Collar Front Height Cloth</string>
+<string name="Collar Front Shadow Height">Collar Front Shadow Height</string>
+<string name="Collar Front bump">Collar Front bump</string>
+<string name="Corner Down">Corner Down</string>
+<string name="Corner Normal">Corner Normal</string>
+<string name="Corner Up">Corner Up</string>
+<string name="Creased">Creased</string>
+<string name="Crooked Nose">Crooked Nose</string>
+<string name="Cropped Hair">Cropped Hair</string>
+<string name="Cuff Flare">Cuff Flare</string>
+<string name="Dark">Dark</string>
+<string name="Dark Green">Dark Green</string>
+<string name="Darker">Darker</string>
+<string name="Deep">Deep</string>
+<string name="Default Heels">Default Heels</string>
+<string name="Default Toe">Default Toe</string>
+<string name="Dense">Dense</string>
+<string name="Dense hair">Dense hair</string>
+<string name="Double Chin">Double Chin</string>
+<string name="Downturned">Downturned</string>
+<string name="Duffle Bag">Duffle Bag</string>
+<string name="Ear Angle">Ear Angle</string>
+<string name="Ear Size">Ear Size</string>
+<string name="Ear Tips">Ear Tips</string>
+<string name="Egg Head">Egg Head</string>
+<string name="Eye Bags">Eye Bags</string>
+<string name="Eye Color">Eye Color</string>
+<string name="Eye Depth">Eye Depth</string>
+<string name="Eye Lightness">Eye Lightness</string>
+<string name="Eye Opening">Eye Opening</string>
+<string name="Eye Pop">Eye Pop</string>
+<string name="Eye Size">Eye Size</string>
+<string name="Eye Spacing">Eye Spacing</string>
+<string name="Eyeball Size">Eyeball Size</string>
+<string name="Eyebrow Arc">Eyebrow Arc</string>
+<string name="Eyebrow Density">Eyebrow Density</string>
+<string name="Eyebrow Density Bump">Eyebrow Density Bump</string>
+<string name="Eyebrow Height">Eyebrow Height</string>
+<string name="Eyebrow Points">Eyebrow Points</string>
+<string name="Eyebrow Size">Eyebrow Size</string>
+<string name="Eyebrow Size Bump">Eyebrow Size Bump</string>
+<string name="Eyelash Length">Eyelash Length</string>
+<string name="Eyeliner">Eyeliner</string>
+<string name="Eyeliner Color">Eyeliner Color</string>
+<string name="Eyes Back">Eyes Back</string>
+<string name="Eyes Bugged">Eyes Bugged</string>
+<string name="Eyes Forward">Eyes Forward</string>
+<string name="Eyes Long Head">Eyes Long Head</string>
+<string name="Eyes Shear Left Up">Eyes Shear Left Up</string>
+<string name="Eyes Shear Right Up">Eyes Shear Right Up</string>
+<string name="Eyes Short Head">Eyes Short Head</string>
+<string name="Eyes Spread">Eyes Spread</string>
+<string name="Eyes Sunken">Eyes Sunken</string>
+<string name="Eyes Together">Eyes Together</string>
+<string name="Face Shear">Face Shear</string>
+<string name="Facial Definition">Facial Definition</string>
+<string name="Far Set Eyes">Far Set Eyes</string>
+<string name="Fat">Fat</string>
+<string name="Fat Head">Fat Head</string>
+<string name="Fat Lips">Fat Lips</string>
+<string name="Fat Lower">Fat Lower</string>
+<string name="Fat Lower Lip">Fat Lower Lip</string>
+<string name="Fat Torso">Fat Torso</string>
+<string name="Fat Upper">Fat Upper</string>
+<string name="Fat Upper Lip">Fat Upper Lip</string>
+<string name="Female">Female</string>
+<string name="Fingerless">Fingerless</string>
+<string name="Fingers">Fingers</string>
+<string name="Flared Cuffs">Flared Cuffs</string>
+<string name="Flat">Flat</string>
+<string name="Flat Butt">Flat Butt</string>
+<string name="Flat Head">Flat Head</string>
+<string name="Flat Toe">Flat Toe</string>
+<string name="Foot Size">Foot Size</string>
+<string name="Forehead Angle">Forehead Angle</string>
+<string name="Forehead Heavy">Forehead Heavy</string>
+<string name="Freckles">Freckles</string>
+<string name="Front Bangs Down">Front Bangs Down</string>
+<string name="Front Bangs Up">Front Bangs Up</string>
+<string name="Front Fringe">Front Fringe</string>
+<string name="Front Hair">Front Hair</string>
+<string name="Front Hair Down">Front Hair Down</string>
+<string name="Front Hair Up">Front Hair Up</string>
+<string name="Full Back">Full Back</string>
+<string name="Full Eyeliner">Full Eyeliner</string>
+<string name="Full Front">Full Front</string>
+<string name="Full Hair Sides">Full Hair Sides</string>
+<string name="Full Sides">Full Sides</string>
+<string name="Glossy">Glossy</string>
+<string name="Glove Fingers">Glove Fingers</string>
+<string name="Glove Fingers bump">Glove Fingers bump</string>
+<string name="Glove Length">Glove Length</string>
+<string name="Glove Length bump">Glove Length bump</string>
+<string name="HEAD">HEAD</string>
+<string name="Hair">Hair</string>
+<string name="Hair Back">Hair Back</string>
+<string name="Hair Front">Hair Front</string>
+<string name="Hair Sides">Hair Sides</string>
+<string name="Hair Sweep">Hair Sweep</string>
+<string name="Hair Thickess">Hair Thickess</string>
+<string name="Hair Thickness">Hair Thickness</string>
+<string name="Hair Tilt">Hair Tilt</string>
+<string name="Hair Tilted Left">Hair Tilted Left</string>
+<string name="Hair Tilted Right">Hair Tilted Right</string>
+<string name="Hair Volume">Hair Volume</string>
+<string name="Hand Size">Hand Size</string>
+<string name="Handlebars">Handlebars</string>
+<string name="Head Length">Head Length</string>
+<string name="Head Shape">Head Shape</string>
+<string name="Head Size">Head Size</string>
+<string name="Head Stretch">Head Stretch</string>
+<string name="Heel Height">Heel Height</string>
+<string name="Heel Shape">Heel Shape</string>
+<string name="Height">Height</string>
+<string name="High">High</string>
+<string name="High Heels">High Heels</string>
+<string name="High Jaw">High Jaw</string>
+<string name="High Platforms">High Platforms</string>
+<string name="High and Tight">High and Tight</string>
+<string name="Higher">Higher</string>
+<string name="Hip Length">Hip Length</string>
+<string name="Hip Width">Hip Width</string>
+<string name="In">In</string>
+<string name="In Shdw Color">In Shdw Color</string>
+<string name="In Shdw Opacity">In Shdw Opacity</string>
+<string name="Inner Eye Corner">Inner Eye Corner</string>
+<string name="Inner Eye Shadow">Inner Eye Shadow</string>
+<string name="Inner Shadow">Inner Shadow</string>
+<string name="Jacket Collar Back bump">Jacket Collar Back bump</string>
+<string name="Jacket Collar Front bump">Jacket Collar Front bump</string>
+<string name="Jacket Length">Jacket Length</string>
+<string name="Jacket Sleeve Length bump">Jacket Sleeve Length bump</string>
+<string name="Jacket Wrinkles">Jacket Wrinkles</string>
+<string name="Jaw Angle">Jaw Angle</string>
+<string name="Jaw Jut">Jaw Jut</string>
+<string name="Jaw Shape">Jaw Shape</string>
+<string name="Join">Join</string>
+<string name="Jowls">Jowls</string>
+<string name="Knee Angle">Knee Angle</string>
+<string name="Knock Kneed">Knock Kneed</string>
+<string name="L Forearm">L Forearm</string>
+<string name="L Lower Leg">L Lower Leg</string>
+<string name="L Upper Arm">L Upper Arm</string>
+<string name="L Upper Leg">L Upper Leg</string>
+
+<string name="Large">Large</string>
+<string name="Large Hands">Large Hands</string>
+<string name="Left">Left</string>
+<string name="Left Ear">Left Ear</string>
+<string name="Left Eyeball">Left Eyeball</string>
+<string name="Left Foot">Left Foot</string>
+<string name="Left Hand">Left Hand</string>
+<string name="Left Hip">Left Hip</string>
+<string name="Left Part">Left Part</string>
+<string name="Left Pec">Left Pec</string>
+<string name="Left Shoulder">Left Shoulder</string>
+<string name="Leg Length">Leg Length</string>
+<string name="Leg Muscles">Leg Muscles</string>
+<string name="Less">Less</string>
+<string name="Less Body Fat">Less Body Fat</string>
+<string name="Less Curtains">Less Curtains</string>
+<string name="Less Freckles">Less Freckles</string>
+<string name="Less Full">Less Full</string>
+<string name="Less Gravity">Less Gravity</string>
+<string name="Less Love">Less Love</string>
+<string name="Less Muscles">Less Muscles</string>
+<string name="Less Muscular">Less Muscular</string>
+<string name="Less Rosy">Less Rosy</string>
+<string name="Less Round">Less Round</string>
+<string name="Less Saddle">Less Saddle</string>
+<string name="Less Square">Less Square</string>
+<string name="Less Volume">Less Volume</string>
+<string name="Less soul">Less soul</string>
+<string name="Light">Light</string>
+<string name="Lighter">Lighter</string>
+<string name="Lip Cleft">Lip Cleft</string>
+<string name="Lip Cleft Depth">Lip Cleft Depth</string>
+<string name="Lip Fullness">Lip Fullness</string>
+<string name="Lip Pinkness">Lip Pinkness</string>
+<string name="Lip Ratio">Lip Ratio</string>
+<string name="Lip Thickness">Lip Thickness</string>
+<string name="Lip Width">Lip Width</string>
+<string name="Lipgloss">Lipgloss</string>
+<string name="Lipstick">Lipstick</string>
+<string name="Lipstick Color">Lipstick Color</string>
+<string name="Long">Long</string>
+<string name="Long Head">Long Head</string>
+<string name="Long Hips">Long Hips</string>
+<string name="Long Legs">Long Legs</string>
+<string name="Long Neck">Long Neck</string>
+<string name="Long Pigtails">Long Pigtails</string>
+<string name="Long Ponytail">Long Ponytail</string>
+<string name="Long Torso">Long Torso</string>
+<string name="Long arms">Long arms</string>
+<string name="Longcuffs">Longcuffs</string>
+<string name="Loose Lower Clothing">Loose Lower Clothing</string>
+<string name="Loose Pants">Loose Pants</string>
+<string name="Loose Shirt">Loose Shirt</string>
+<string name="Loose Sleeves">Loose Sleeves</string>
+<string name="Loose Upper Clothing">Loose Upper Clothing</string>
+<string name="Love Handles">Love Handles</string>
+<string name="Low">Low</string>
+<string name="Low Heels">Low Heels</string>
+<string name="Low Jaw">Low Jaw</string>
+<string name="Low Platforms">Low Platforms</string>
+<string name="Low and Loose">Low and Loose</string>
+<string name="Lower">Lower</string>
+<string name="Lower Bridge">Lower Bridge</string>
+<string name="Lower Cheeks">Lower Cheeks</string>
+<string name="Lower Clothes Shading">Lower Clothes Shading</string>
+<string name="Male">Male</string>
+<string name="Middle Part">Middle Part</string>
+<string name="More">More</string>
+<string name="More Blush">More Blush</string>
+<string name="More Body Fat">More Body Fat</string>
+<string name="More Curtains">More Curtains</string>
+<string name="More Eyeshadow">More Eyeshadow</string>
+<string name="More Freckles">More Freckles</string>
+<string name="More Full">More Full</string>
+<string name="More Gravity">More Gravity</string>
+<string name="More Lipstick">More Lipstick</string>
+<string name="More Love">More Love</string>
+<string name="More Lower Lip">More Lower Lip</string>
+<string name="More Muscles">More Muscles</string>
+<string name="More Muscular">More Muscular</string>
+<string name="More Rosy">More Rosy</string>
+<string name="More Round">More Round</string>
+<string name="More Saddle">More Saddle</string>
+<string name="More Sloped">More Sloped</string>
+<string name="More Square">More Square</string>
+<string name="More Upper Lip">More Upper Lip</string>
+<string name="More Vertical">More Vertical</string>
+<string name="More Volume">More Volume</string>
+<string name="More soul">More soul</string>
+<string name="Moustache">Moustache</string>
+<string name="Moustache bump">Moustache bump</string>
+<string name="Mouth">Mouth</string>
+<string name="Mouth Corner">Mouth Corner</string>
+<string name="Mouth Position">Mouth Position</string>
+<string name="Mowhawk">Mowhawk</string>
+<string name="Muscular">Muscular</string>
+<string name="Mutton Chops">Mutton Chops</string>
+<string name="NECK">NECK</string>
+<string name="Nail Polish">Nail Polish</string>
+<string name="Nail Polish Color">Nail Polish Color</string>
+<string name="Narrow">Narrow</string>
+<string name="Narrow Back">Narrow Back</string>
+<string name="Narrow Front">Narrow Front</string>
+<string name="Narrow Lips">Narrow Lips</string>
+<string name="Natural">Natural</string>
+<string name="Neck Length">Neck Length</string>
+<string name="Neck Thickness">Neck Thickness</string>
+<string name="No Blush">No Blush</string>
+<string name="No Eyeliner">No Eyeliner</string>
+<string name="No Eyeshadow">No Eyeshadow</string>
+<string name="No Heels">No Heels</string>
+<string name="No Lipgloss">No Lipgloss</string>
+<string name="No Lipstick">No Lipstick</string>
+<string name="No Part">No Part</string>
+<string name="No Polish">No Polish</string>
+<string name="No Red">No Red</string>
+<string name="No Spikes">No Spikes</string>
+<string name="No White">No White</string>
+<string name="No Wrinkles">No Wrinkles</string>
+<string name="None">None</string>
+<string name="Normal Lower">Normal Lower</string>
+<string name="Normal Upper">Normal Upper</string>
+<string name="Nose">Nose</string>
+<string name="Nose Left">Nose Left</string>
+<string name="Nose Right">Nose Right</string>
+<string name="Nose Size">Nose Size</string>
+<string name="Nose Thickness">Nose Thickness</string>
+<string name="Nose Tip Angle">Nose Tip Angle</string>
+<string name="Nose Tip Shape">Nose Tip Shape</string>
+<string name="Nose Width">Nose Width</string>
+<string name="Nostril Division">Nostril Division</string>
+<string name="Nostril Width">Nostril Width</string>
+<string name="NotHair">NotHair</string>
+<string name="Old">Old</string>
+<string name="Opaque">Opaque</string>
+<string name="Open">Open</string>
+<string name="Open Back">Open Back</string>
+<string name="Open Front">Open Front</string>
+<string name="Open Left">Open Left</string>
+<string name="Open Right">Open Right</string>
+<string name="Orange">Orange</string>
+<string name="Out">Out</string>
+<string name="Out Shdw Color">Out Shdw Color</string>
+<string name="Out Shdw Opacity">Out Shdw Opacity</string>
+<string name="Outer Eye Corner">Outer Eye Corner</string>
+<string name="Outer Eye Shadow">Outer Eye Shadow</string>
+<string name="Outer Shadow">Outer Shadow</string>
+<string name="Overbite">Overbite</string>
+<string name="PELVIS">PELVIS</string>
+<string name="Package">Package</string>
+<string name="Painted Nails">Painted Nails</string>
+<string name="Pale">Pale</string>
+<string name="Pants Crotch">Pants Crotch</string>
+<string name="Pants Fit">Pants Fit</string>
+<string name="Pants Length">Pants Length</string>
+<string name="Pants Length Cloth">Pants Length Cloth</string>
+<string name="Pants Length Shadow">Pants Length Shadow</string>
+<string name="Pants Waist">Pants Waist</string>
+<string name="Pants Wrinkles">Pants Wrinkles</string>
+<string name="Part">Part</string>
+<string name="Part Bangs">Part Bangs</string>
+<string name="Pectorals">Pectorals</string>
+<string name="Pelvis">Pelvis</string>
+<string name="Pigment">Pigment</string>
+<string name="Pigtails">Pigtails</string>
+<string name="Pink">Pink</string>
+<string name="Pinker">Pinker</string>
+<string name="Platform Height">Platform Height</string>
+<string name="Platform Width">Platform Width</string>
+<string name="Pointy">Pointy</string>
+<string name="Pointy Heels">Pointy Heels</string>
+<string name="Pointy Toe">Pointy Toe</string>
+<string name="Ponytail">Ponytail</string>
+<string name="Poofy Skirt">Poofy Skirt</string>
+<string name="Pop Left Eye">Pop Left Eye</string>
+<string name="Pop Right Eye">Pop Right Eye</string>
+<string name="Puffy">Puffy</string>
+<string name="Puffy Eyelids">Puffy Eyelids</string>
+<string name="R Forearm">R Forearm</string>
+<string name="R Lower Leg">R Lower Leg</string>
+<string name="R Upper Arm">R Upper Arm</string>
+<string name="R Upper Leg">R Upper Leg</string>
+<string name="Rainbow Color">Rainbow Color</string>
+<string name="Red Hair">Red Hair</string>
+<string name="Red Skin">Red Skin</string>
+<string name="Regular">Regular</string>
+<string name="Regular Muscles">Regular Muscles</string>
+<string name="Right">Right</string>
+<string name="Right Ear">Right Ear</string>
+<string name="Right Eyeball">Right Eyeball</string>
+<string name="Right Foot">Right Foot</string>
+<string name="Right Hand">Right Hand</string>
+<string name="Right Hip">Right Hip</string>
+<string name="Right Part">Right Part</string>
+<string name="Right Pec">Right Pec</string>
+<string name="Right Shoulder">Right Shoulder</string>
+<string name="Rosy Complexion">Rosy Complexion</string>
+<string name="Round">Round</string>
+<string name="Round Forehead">Round Forehead</string>
+<string name="Ruddiness">Ruddiness</string>
+<string name="Ruddy">Ruddy</string>
+<string name="Rumpled Hair">Rumpled Hair</string>
+<string name="Saddle Bags">Saddle Bags</string>
+<string name="Saddlebags">Saddlebags</string>
+<string name="Scrawny">Scrawny</string>
+<string name="Scrawny Leg">Scrawny Leg</string>
+<string name="Separate">Separate</string>
+<string name="Shading">Shading</string>
+<string name="Shadow hair">Shadow hair</string>
+<string name="Shallow">Shallow</string>
+<string name="Shear Back">Shear Back</string>
+<string name="Shear Face">Shear Face</string>
+<string name="Shear Front">Shear Front</string>
+<string name="Shear Left">Shear Left</string>
+<string name="Shear Left Up">Shear Left Up</string>
+<string name="Shear Right">Shear Right</string>
+<string name="Shear Right Up">Shear Right Up</string>
+<string name="Sheared Back">Sheared Back</string>
+<string name="Sheared Front">Sheared Front</string>
+<string name="Shift Left">Shift Left</string>
+<string name="Shift Mouth">Shift Mouth</string>
+<string name="Shift Right">Shift Right</string>
+<string name="Shirt Bottom">Shirt Bottom</string>
+<string name="Shirt Bottom Cloth">Shirt Bottom Cloth</string>
+<string name="Shirt Fit">Shirt Fit</string>
+<string name="Shirt Shadow Bottom">Shirt Shadow Bottom</string>
+<string name="Shirt Wrinkles">Shirt Wrinkles</string>
+<string name="Shoe Height">Shoe Height</string>
+<string name="Shoe Height bump">Shoe Height bump</string>
+<string name="Short">Short</string>
+<string name="Short Arms">Short Arms</string>
+<string name="Short Legs">Short Legs</string>
+<string name="Short Neck">Short Neck</string>
+<string name="Short Pigtails">Short Pigtails</string>
+<string name="Short Ponytail">Short Ponytail</string>
+<string name="Short Sideburns">Short Sideburns</string>
+<string name="Short Torso">Short Torso</string>
+<string name="Short hips">Short hips</string>
+<string name="Shoulders">Shoulders</string>
+<string name="Side Bangs">Side Bangs</string>
+<string name="Side Bangs Down">Side Bangs Down</string>
+<string name="Side Bangs Up">Side Bangs Up</string>
+<string name="Side Fringe">Side Fringe</string>
+<string name="Sideburns">Sideburns</string>
+<string name="Sideburns bump">Sideburns bump</string>
+<string name="Sides Hair">Sides Hair</string>
+<string name="Sides Hair Down">Sides Hair Down</string>
+<string name="Sides Hair Up">Sides Hair Up</string>
+<string name="Skinny">Skinny</string>
+<string name="Skinny Neck">Skinny Neck</string>
+<string name="Skirt Fit">Skirt Fit</string>
+<string name="Skirt Length">Skirt Length</string>
+<string name="Skull">Skull</string>
+<string name="Slanted Forehead">Slanted Forehead</string>
+<string name="Sleeve Length">Sleeve Length</string>
+<string name="Sleeve Length Cloth">Sleeve Length Cloth</string>
+<string name="Sleeve Length Shadow">Sleeve Length Shadow</string>
+<string name="Sleeve Length bump">Sleeve Length bump</string>
+<string name="Sleeve Looseness">Sleeve Looseness</string>
+<string name="Slit Back">Slit Back</string>
+<string name="Slit Front">Slit Front</string>
+<string name="Slit Left">Slit Left</string>
+<string name="Slit Right">Slit Right</string>
+<string name="Small">Small</string>
+<string name="Small Hands">Small Hands</string>
+<string name="Small Head">Small Head</string>
+<string name="Smooth">Smooth</string>
+<string name="Smooth Hair">Smooth Hair</string>
+<string name="Socks Length">Socks Length</string>
+<string name="Socks Length bump">Socks Length bump</string>
+<string name="Some">Some</string>
+<string name="Soulpatch">Soulpatch</string>
+<string name="Soulpatch bump">Soulpatch bump</string>
+<string name="Sparse">Sparse</string>
+<string name="Spiked Hair">Spiked Hair</string>
+<string name="Spine">Spine</string>
+<string name="Square">Square</string>
+<string name="Square Toe">Square Toe</string>
+<string name="Squash Head">Squash Head</string>
+<string name="Squash/Stretch Head">Squash/Stretch Head</string>
+<string name="Stomach">Stomach</string>
+<string name="Stretch Head">Stretch Head</string>
+<string name="Sunken">Sunken</string>
+<string name="Sunken Chest">Sunken Chest</string>
+<string name="Sunken Eyes">Sunken Eyes</string>
+<string name="Sweep Back">Sweep Back</string>
+<string name="Sweep Forward">Sweep Forward</string>
+<string name="Swept Back">Swept Back</string>
+<string name="Swept Back Hair">Swept Back Hair</string>
+<string name="Swept Forward">Swept Forward</string>
+<string name="Swept Forward Hair">Swept Forward Hair</string>
+<string name="Tall">Tall</string>
+<string name="Taper Back">Taper Back</string>
+<string name="Taper Front">Taper Front</string>
+<string name="Thick Heels">Thick Heels</string>
+<string name="Thick Neck">Thick Neck</string>
+<string name="Thick Toe">Thick Toe</string>
+<string name="Thickness">Thickness</string>
+<string name="Thin">Thin</string>
+<string name="Thin Eyebrows">Thin Eyebrows</string>
+<string name="Thin Lips">Thin Lips</string>
+<string name="Thin Nose">Thin Nose</string>
+<string name="Tight Chin">Tight Chin</string>
+<string name="Tight Cuffs">Tight Cuffs</string>
+<string name="Tight Pants">Tight Pants</string>
+<string name="Tight Shirt">Tight Shirt</string>
+<string name="Tight Skirt">Tight Skirt</string>
+<string name="Tight Sleeves">Tight Sleeves</string>
+<string name="Tilt Left">Tilt Left</string>
+<string name="Tilt Right">Tilt Right</string>
+<string name="Toe Shape">Toe Shape</string>
+<string name="Toe Thickness">Toe Thickness</string>
+<string name="Top">Top</string>
+<string name="Top Left">Top Left</string>
+<string name="Top Right">Top Right</string>
+<string name="Torso Length">Torso Length</string>
+<string name="Torso Muscles">Torso Muscles</string>
+<string name="Torso Scrawny">Torso Scrawny</string>
+<string name="Unattached">Unattached</string>
+<string name="Uncreased">Uncreased</string>
+<string name="Underbite">Underbite</string>
+<string name="Unnatural">Unnatural</string>
+<string name="Upper Bridge">Upper Bridge</string>
+<string name="Upper Cheeks">Upper Cheeks</string>
+<string name="Upper Chin Cleft">Upper Chin Cleft</string>
+<string name="Upper Clothes Shading">Upper Clothes Shading</string>
+<string name="Upper Eyelid Fold">Upper Eyelid Fold</string>
+<string name="Upturned">Upturned</string>
+<string name="Very Red">Very Red</string>
+<string name="Waist Height">Waist Height</string>
+<string name="Waist Height Cloth">Waist Height Cloth</string>
+<string name="Waist Height Shadow">Waist Height Shadow</string>
+<string name="Well-Fed">Well-Fed</string>
+<string name="White Hair">White Hair</string>
+<string name="Wide">Wide</string>
+<string name="Wide Back">Wide Back</string>
+<string name="Wide Front">Wide Front</string>
+<string name="Wide Lips">Wide Lips</string>
+<string name="Wild">Wild</string>
+<string name="Wrinkles">Wrinkles</string>
<!-- Favorites Bar -->
<string name="location_ctrl_add_landmark">Add to My Landmarks</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/combo_box.xml b/indra/newview/skins/default/xui/en/widgets/combo_box.xml
index d7369d0726..0dbca318b6 100644
--- a/indra/newview/skins/default/xui/en/widgets/combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/combo_box.xml
@@ -20,7 +20,9 @@
image_unselected="DropDown_Off"
image_selected="DropDown_Selected"
image_disabled="DropDown_Disabled" />
- <combo_box.combo_list bg_writeable_color="MenuDefaultBgColor" />
+ <combo_box.combo_list bg_writeable_color="MenuDefaultBgColor"
+ background_visible="true"
+ />
<combo_box.combo_editor name="Combo Text Entry"
select_on_focus="true"
font="SansSerifSmall" />
diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
index e470f42d36..6381dce1d6 100644
--- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
+++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
@@ -2,6 +2,7 @@
<expandable_text
max_height="300" >
<textbox
+ more_label="More"
follows="left|top"
name="text"
use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml
index 824a815a99..4520768216 100644
--- a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml
+++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml
@@ -12,7 +12,7 @@
draw_stripes="true"
scroll_bar_bg_visible="false"
scroll_bar_bg_color="black"
- background_visible="false"
+ background_visible="true"
heading_height="23"
draw_border="false"
draw_heading="false" />
diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml
index f0127a9d5a..5914c21b2b 100644
--- a/indra/newview/skins/default/xui/en/widgets/text.xml
+++ b/indra/newview/skins/default/xui/en/widgets/text.xml
@@ -18,4 +18,5 @@
border_visible="false"
hover="false"
text_color="LabelTextColor"
- v_pad="-1"/>
+ v_pad="-1"
+ max_length="4096"/>
diff --git a/indra/newview/skins/default/xui/es/floater_camera.xml b/indra/newview/skins/default/xui/es/floater_camera.xml
index 0246f0d440..3aeb4e5771 100644
--- a/indra/newview/skins/default/xui/es/floater_camera.xml
+++ b/indra/newview/skins/default/xui/es/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Girar la cámara alrededor de lo enfocado
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Hacer zoom con la cámara en lo enfocado
- </string>
- <string name="move_tooltip">
- Mover la cámara arriba y abajo, izquierda y derecha.
- </string>
+ </floater.string>
+ <floater.string name="move_tooltip">
+ Mover la cámara arriba y abajo, izquierda y derecha
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Mover la cámara arriba y abajo, izquierda y derecha"/>
+ <joystick_zoom name="zoom" tool_tip="Hacer zoom con la cámara en lo enfocado"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_color_picker.xml b/indra/newview/skins/default/xui/es/floater_color_picker.xml
index c220c48cb0..616c373d18 100644
--- a/indra/newview/skins/default/xui/es/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/es/floater_color_picker.xml
@@ -26,6 +26,6 @@
</text>
<text name="(Drag below to save.)">
(Arrástrelo abajo
- para guardarlo.)
+ para guardarlo)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_camera.xml b/indra/newview/skins/default/xui/fr/floater_camera.xml
index 9f280b7265..8ea640853f 100644
--- a/indra/newview/skins/default/xui/fr/floater_camera.xml
+++ b/indra/newview/skins/default/xui/fr/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater">
- <string name="rotate_tooltip">
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
Faire tourner la caméra autour du point central
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Zoomer en direction du point central
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Déplacer la caméra vers le haut et le bas, la gauche et la droite
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Déplacer la caméra vers le haut et le bas, la gauche et la droite"/>
+ <joystick_zoom name="zoom" tool_tip="Zoomer en direction du point central"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_color_picker.xml b/indra/newview/skins/default/xui/fr/floater_color_picker.xml
index adab86dac0..94bcad070e 100644
--- a/indra/newview/skins/default/xui/fr/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/fr/floater_color_picker.xml
@@ -27,6 +27,6 @@
</text>
<text left="8" name="(Drag below to save.)" width="114">
(Faire glisser dessous
-pour enregistrer.)
+pour enregistrer)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_camera.xml b/indra/newview/skins/default/xui/it/floater_camera.xml
index 9655ed2211..823be8f4a1 100644
--- a/indra/newview/skins/default/xui/it/floater_camera.xml
+++ b/indra/newview/skins/default/xui/it/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Ruota la telecamera Intorno all&apos;Inquadratura
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Avvicina la telecamera nell&apos;inquadratura
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Muovi la telecamera su e giù e a sinistra e destra
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Muovi la telecamera su e giù e a sinistra e destra"/>
+ <joystick_zoom name="zoom" tool_tip="Avvicina la telecamera nell&apos;inquadratura"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_color_picker.xml b/indra/newview/skins/default/xui/it/floater_color_picker.xml
index 93188c29ac..1e6d7bc3f0 100644
--- a/indra/newview/skins/default/xui/it/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/it/floater_color_picker.xml
@@ -33,6 +33,6 @@
</text>
<text name="(Drag below to save.)">
(Trascina qui sotto
- per salvare.)
+ per salvare)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_camera.xml b/indra/newview/skins/default/xui/ja/floater_camera.xml
index 46e7b1990d..bb87b194a4 100644
--- a/indra/newview/skins/default/xui/ja/floater_camera.xml
+++ b/indra/newview/skins/default/xui/ja/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater">
- <string name="rotate_tooltip">
+<floater name="camera_floater">
+ <floater.string name="rotate_tooltip">
フォーカスを中心にカメラを回転
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
フォーカスに向けてカメラをズーム
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
カメラを上下左右に移動
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="カメラを上下左右に移動"/>
+ <joystick_zoom name="zoom" tool_tip="フォーカスに向けてカメラをズーム"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_camera.xml b/indra/newview/skins/default/xui/nl/floater_camera.xml
index a6b843a0a2..81a3ed8a58 100644
--- a/indra/newview/skins/default/xui/nl/floater_camera.xml
+++ b/indra/newview/skins/default/xui/nl/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Roteer camera rond focus
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Zoom camera naar focus
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Beweeg camera omhoog en omlaag, links en rechts
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Beweeg camera omhoog en omlaag, links en rechts"/>
+ <joystick_zoom name="zoom" tool_tip="Zoom camera naar focus"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_color_picker.xml b/indra/newview/skins/default/xui/nl/floater_color_picker.xml
index 25294e17e2..a357e874f7 100644
--- a/indra/newview/skins/default/xui/nl/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/nl/floater_color_picker.xml
@@ -26,6 +26,6 @@
</text>
<text name="(Drag below to save.)">
(Sleep naar beneden
- om op te slaan.)
+ om op te slaan)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_camera.xml b/indra/newview/skins/default/xui/pl/floater_camera.xml
index 24da91c081..5957018144 100755
--- a/indra/newview/skins/default/xui/pl/floater_camera.xml
+++ b/indra/newview/skins/default/xui/pl/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Obracaj kamerę wokół obiektu
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Najedź kamerą w kierunku obiektu
- </string>
- <string name="move_tooltip">
+ </floater.string>
+ <floater.string name="move_tooltip">
Poruszaj kamerą w dół/górę oraz w prawo/lewo
- </string>
+ </floater.string>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Poruszaj kamerą w dół/górę oraz w prawo/lewo"/>
+ <joystick_zoom name="zoom" tool_tip="Najedź kamerą w kierunku obiektu"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_color_picker.xml b/indra/newview/skins/default/xui/pl/floater_color_picker.xml
index a380423cdf..d6ffe1837a 100755
--- a/indra/newview/skins/default/xui/pl/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/pl/floater_color_picker.xml
@@ -26,6 +26,6 @@
Obecny Kolor:
</text>
<text name="(Drag below to save.)">
- (Przeciągnij tutaj.)
+ (Przeciągnij tutaj)
</text>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_camera.xml b/indra/newview/skins/default/xui/pt/floater_camera.xml
index 4dc6997606..b61e261148 100644
--- a/indra/newview/skins/default/xui/pt/floater_camera.xml
+++ b/indra/newview/skins/default/xui/pt/floater_camera.xml
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="move floater" title="">
- <string name="rotate_tooltip">
+<floater name="camera_floater" title="">
+ <floater.string name="rotate_tooltip">
Girar a Câmera ao redor do Foco
- </string>
- <string name="zoom_tooltip">
+ </floater.string>
+ <floater.string name="zoom_tooltip">
Aproximar a Câmera in direção ao Foco
- </string>
- <string name="move_tooltip">
- Mover a Câmera Para Cima e Para Baixo, Para a Esquerda e Para a Direita
- </string>
+ </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>
+ <panel name="controls">
+ <joystick_track name="cam_track_stick" tool_tip="Mover a Câmera para Cima e para Baixo, para a Esquerda e para a Direita"/>
+ <joystick_zoom name="zoom" tool_tip="Aproximar a Câmera in direção ao Foco"/>
+ </panel>
</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_color_picker.xml b/indra/newview/skins/default/xui/pt/floater_color_picker.xml
index 95dd53ccd4..76da972b5d 100644
--- a/indra/newview/skins/default/xui/pt/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/pt/floater_color_picker.xml
@@ -27,6 +27,6 @@
</text>
<text name="(Drag below to save.)">
(Arraste abaixo
- para salvar.)
+ para salvar)
</text>
</floater>
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
new file mode 100644
index 0000000000..135c5ab501
--- /dev/null
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -0,0 +1,481 @@
+/**
+ * @file llmediadataclient_test.cpp
+ * @brief LLMediaDatClient tests
+ *
+ * $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$
+ */
+
+#include <iostream>
+#include "../test/lltut.h"
+
+#include "llsdserialize.h"
+#include "llerrorcontrol.h"
+#include "llhttpstatuscodes.h"
+
+#include "../llmediadataclient.h"
+#include "../llvovolume.h"
+
+#include "../../llprimitive/llmediaentry.cpp"
+#include "../../llprimitive/lltextureentry.cpp"
+#include "../../llmessage/tests/llcurl_stub.cpp"
+
+#include <boost/lexical_cast.hpp>
+
+#define VALID_OBJECT_ID "3607d5c4-644b-4a8a-871a-8b78471af2a2"
+#define VALID_OBJECT_ID_1 "11111111-1111-1111-1111-111111111111"
+#define VALID_OBJECT_ID_2 "22222222-2222-2222-2222-222222222222"
+#define VALID_OBJECT_ID_3 "33333333-3333-3333-3333-333333333333"
+#define VALID_OBJECT_ID_4 "44444444-4444-4444-4444-444444444444"
+
+#define FAKE_OBJECT_MEDIA_CAP_URL "foo_ObjectMedia"
+#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL "foo_ObjectMediaNavigate"
+#define FAKE_OBJECT_MEDIA_CAP_URL_503 "foo_ObjectMedia_503"
+#define FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR "foo_ObjectMediaNavigate_ERROR"
+
+#define MEDIA_DATA "\
+<array> \
+<string>foo</string> \
+<string>bar</string> \
+<string>baz</string> \
+</array>"
+
+#define _DATA_URLS(ID,DIST,INT,URL1,URL2) " \
+<llsd> \
+ <map> \
+ <key>uuid</key> \
+ <string>" ID "</string> \
+ <key>distance</key> \
+ <real>" DIST "</real> \
+ <key>interest</key> \
+ <real>" INT "</real> \
+ <key>cap_urls</key> \
+ <map> \
+ <key>ObjectMedia</key> \
+ <string>" URL1 "</string> \
+ <key>ObjectMediaNavigate</key> \
+ <string>" URL2 "</string> \
+ </map> \
+ <key>media_data</key> \
+ " MEDIA_DATA " \
+ </map> \
+</llsd>"
+
+#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
+
+const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0");
+
+#define STR(I) boost::lexical_cast<std::string>(I)
+
+#define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" << \
+"================================================================================\n" << \
+"===================================== TEST " #N " ===================================\n" << \
+"================================================================================\n" << LL_ENDL;
+
+LLSD *gPostRecords = NULL;
+
+// stubs:
+void LLHTTPClient::post(
+ const std::string& url,
+ const LLSD& body,
+ LLHTTPClient::ResponderPtr responder,
+ const LLSD& headers,
+ const F32 timeout)
+{
+ LLSD record;
+ record["url"] = url;
+ record["body"] = body;
+ record["headers"] = headers;
+ record["timeout"] = timeout;
+ gPostRecords->append(record);
+
+ // Magic URL that triggers a 503:
+ if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
+ {
+ responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
+ }
+ else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)
+ {
+ LLSD result;
+ LLSD error;
+ error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
+ result["error"] = error;
+ responder->result(result);
+ }
+ else {
+ responder->result(LLSD());
+ }
+}
+
+const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
+
+class LLMediaDataClientObjectTest : public LLMediaDataClientObject
+{
+public:
+ LLMediaDataClientObjectTest(const char *data)
+ {
+ std::istringstream d(data);
+ LLSDSerialize::fromXML(mRep, d);
+ mNumBounceBacks = 0;
+
+ // std::cout << ll_pretty_print_sd(mRep) << std::endl;
+ // std::cout << "ID: " << getID() << std::endl;
+ }
+ LLMediaDataClientObjectTest(const LLSD &rep)
+ : mRep(rep), mNumBounceBacks(0) {}
+ ~LLMediaDataClientObjectTest()
+ { LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
+
+ virtual U8 getMediaDataCount() const
+ { return mRep["media_data"].size(); }
+ virtual LLSD getMediaDataLLSD(U8 index) const
+ { return mRep["media_data"][(LLSD::Integer)index]; }
+ virtual LLUUID getID() const
+ { return mRep["uuid"]; }
+ virtual void mediaNavigateBounceBack(U8 index)
+ {
+ mNumBounceBacks++;
+ }
+
+ virtual bool hasMedia() const
+ { return mRep.has("media_data"); }
+
+ virtual void updateObjectMediaData(LLSD const &media_data_array)
+ { mRep["media_data"] = media_data_array; }
+
+ virtual F64 getDistanceFromAvatar() const
+ { return (LLSD::Real)mRep["distance"]; }
+
+ virtual F64 getTotalMediaInterest() const
+ { return (LLSD::Real)mRep["interest"]; }
+
+ virtual std::string getCapabilityUrl(const std::string &name) const
+ { return mRep["cap_urls"][name]; }
+
+ int getNumBounceBacks() const
+ { return mNumBounceBacks; }
+
+private:
+ LLSD mRep;
+ int mNumBounceBacks;
+};
+
+
+namespace tut
+{
+ struct mediadataclient
+ {
+ mediadataclient() {
+ gPostRecords = &mLLSD;
+
+// LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+// LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG);
+// LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);
+ }
+ LLSD mLLSD;
+ };
+
+ typedef test_group<mediadataclient> mediadataclient_t;
+ typedef mediadataclient_t::object mediadataclient_object_t;
+ tut::mediadataclient_t tut_mediadataclient("mediadataclient");
+
+ void ensure(const std::string &msg, int value, int expected)
+ {
+ std::string m = msg;
+ m += " value: " + STR(value);
+ m += ", expected: " + STR(expected);
+ ensure(m, value == expected);
+ }
+
+ void ensure(const std::string &msg, const std::string & value, const std::string & expected)
+ {
+ std::string m = msg;
+ m += " value: " + value;
+ m += ", expected: " + expected;
+ ensure(m, value == expected);
+ }
+
+ void ensure(const std::string &msg, const LLUUID & value, const LLUUID & expected)
+ {
+ std::string m = msg;
+ m += " value: " + value.asString();
+ m += ", expected: " + expected.asString();
+ ensure(m, value == expected);
+ }
+
+ void ensure_llsd(const std::string &msg, const LLSD & value, const char *expected)
+ {
+ LLSD expected_llsd;
+ std::istringstream e(expected);
+ LLSDSerialize::fromXML(expected_llsd, e);
+
+ std::string value_str = ll_pretty_print_sd(value);
+ std::string expected_str = ll_pretty_print_sd(expected_llsd);
+ std::string m = msg;
+ m += " value: " + value_str;
+ m += ", expected: " + expected_str;
+ ensure(m, value_str == expected_str);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<1>()
+ {
+ //
+ // Test fetchMedia()
+ //
+ LOG_TEST(1);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ int num_refs_start = o->getNumRefs();
+ {
+ // queue time w/ no delay ensures that LLEventTimer::updateClass() will hit the tick()
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(0,0,4);
+ mdc->fetchMedia(o);
+
+ // Make sure no posts happened yet...
+ ensure("post records", gPostRecords->size(), 0);
+
+ LLEventTimer::updateClass();
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+ ensure("post GET", (*gPostRecords)[0]["body"]["verb"], "GET");
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ // Make sure everyone's destroyed properly
+ ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<2>()
+ {
+ //
+ // Test updateMedia()
+ //
+ LOG_TEST(2);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ {
+ // queue time w/ no delay ensures that LLEventTimer::updateClass() will hit the tick()
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(0,0,4);
+ mdc->updateMedia(o);
+ ensure("post records", gPostRecords->size(), 0);
+ LLEventTimer::updateClass();
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+ ensure("post UPDATE", (*gPostRecords)[0]["body"]["verb"], "UPDATE");
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure_llsd("post data llsd", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
+ "<llsd>" MEDIA_DATA "</llsd>");
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ ensure("REF COUNT", o->getNumRefs(), 1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<3>()
+ {
+ //
+ // Test navigate()
+ //
+ LOG_TEST(3);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+ {
+ LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(0,0,4);
+ const char *TEST_URL = "http://example.com";
+ mdc->navigate(o, 0, TEST_URL);
+ ensure("post records", gPostRecords->size(), 0);
+ LLEventTimer::updateClass();
+
+ // ensure no bounce back
+ ensure("bounce back", dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(), 0);
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL);
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
+ ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("REF COUNT", o->getNumRefs(), 1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<4>()
+ {
+ //
+ // Test queue ordering
+ //
+ LOG_TEST(4);
+
+ LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_1,"3.0","1.0"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_3,"2.0","1.0"));
+ {
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(0,0,4);
+ const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
+ mdc->fetchMedia(o1);
+ mdc->fetchMedia(o2);
+ mdc->fetchMedia(o3);
+
+ // Make sure no posts happened yet...
+ ensure("post records", gPostRecords->size(), 0);
+
+ // tick 3 times...
+ LLEventTimer::updateClass();
+ ensure("post records", gPostRecords->size(), 1);
+ LLEventTimer::updateClass();
+ ensure("post records", gPostRecords->size(), 2);
+ LLEventTimer::updateClass();
+ ensure("post records", gPostRecords->size(), 3);
+
+ for( int i=0; i < 3; i++ )
+ {
+ ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL);
+ ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
+ ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(),
+ LLUUID(ORDERED_OBJECT_IDS[i]));
+ }
+
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("refcount of o1", o1->getNumRefs(), 1);
+ ensure("refcount of o2", o2->getNumRefs(), 1);
+ ensure("refcount of o3", o3->getNumRefs(), 1);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+
+ template<> template<>
+ void mediadataclient_object_t::test<5>()
+ {
+ //
+ // Test fetchMedia() getting a 503 error
+ //
+ LOG_TEST(5);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
+ _DATA_URLS(VALID_OBJECT_ID,
+ "1.0",
+ "1.0",
+ FAKE_OBJECT_MEDIA_CAP_URL_503,
+ FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
+ int num_refs_start = o->getNumRefs();
+ {
+ const int NUM_RETRIES = 5;
+ LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(0,0,NUM_RETRIES);
+
+ // This should generate a retry
+ mdc->fetchMedia(o);
+
+ // Make sure no posts happened yet...
+ ensure("post records before", gPostRecords->size(), 0);
+
+ // Once, causes retry
+ // Second, fires retry timer
+ // Third, fires queue timer again
+ for (int i=0; i<NUM_RETRIES; ++i)
+ {
+ LLEventTimer::updateClass();
+ ensure("post records " + STR(i), gPostRecords->size(), i+1);
+ LLEventTimer::updateClass();
+ }
+
+ // Do some extre pumps to make sure no other timer work occurs.
+ LLEventTimer::updateClass();
+ LLEventTimer::updateClass();
+ LLEventTimer::updateClass();
+
+ // Make sure there were 2 posts
+ ensure("post records after", gPostRecords->size(), NUM_RETRIES);
+ for (int i=0; i<NUM_RETRIES; ++i)
+ {
+ ensure("[" + STR(i) + "] post url", (*gPostRecords)[i]["url"], FAKE_OBJECT_MEDIA_CAP_URL_503);
+ ensure("[" + STR(i) + "] post GET", (*gPostRecords)[i]["body"]["verb"], "GET");
+ ensure("[" + STR(i) + "] post object id", (*gPostRecords)[i]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ }
+ ensure("queue empty", mdc->isEmpty());
+ }
+
+ // Make sure everyone's destroyed properly
+ ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+ }
+
+ template<> template<>
+ void mediadataclient_object_t::test<6>()
+ {
+ //
+ // Test navigate() with a bounce back
+ //
+ LOG_TEST(6);
+
+ LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
+ _DATA_URLS(VALID_OBJECT_ID,
+ "1.0",
+ "1.0",
+ FAKE_OBJECT_MEDIA_CAP_URL,
+ FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
+ {
+ LLPointer<LLObjectMediaNavigateClient> mdc = new LLObjectMediaNavigateClient(0,0,4);
+ const char *TEST_URL = "http://example.com";
+ mdc->navigate(o, 0, TEST_URL);
+ ensure("post records", gPostRecords->size(), 0);
+ LLEventTimer::updateClass();
+
+ // ensure bounce back
+ ensure("bounce back",
+ dynamic_cast<LLMediaDataClientObjectTest*>(static_cast<LLMediaDataClientObject*>(o))->getNumBounceBacks(),
+ 1);
+
+ ensure("post records", gPostRecords->size(), 1);
+ ensure("post url", (*gPostRecords)[0]["url"], FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR);
+ ensure("post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID));
+ ensure("post data", (*gPostRecords)[0]["body"][LLTextureEntry::TEXTURE_INDEX_KEY], 0);
+ ensure("post data", (*gPostRecords)[0]["body"][LLMediaEntry::CURRENT_URL_KEY], TEST_URL);
+ ensure("queue empty", mdc->isEmpty());
+ }
+ ensure("REF COUNT", o->getNumRefs(), 1);
+ }
+
+
+}
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index d3b0a2e47e..a670db699e 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -269,8 +269,8 @@ class WindowsManifest(ViewerManifest):
# For google-perftools tcmalloc allocator.
if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
- self.path("libtcmalloc_minimal.dll")
- self.end_prefix()
+ self.path("libtcmalloc_minimal.dll")
+ self.end_prefix()
def nsi_file_commands(self, install=True):
@@ -393,6 +393,8 @@ class WindowsManifest(ViewerManifest):
# We use the Unicode version of NSIS, available from
# http://www.scratchpaper.com/
NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe'
+ if not os.path.exists(NSIS_path):
+ NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe')
self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile))
# self.remove(self.dst_path_of(tempfile))
# If we're on a build machine, sign the code using our Authenticode certificate. JC
@@ -538,7 +540,7 @@ class DarwinManifest(ViewerManifest):
# make sure we don't have stale files laying about
self.remove(sparsename, finalname)
- self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 400 -layout SPUD' % {
+ self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 500 -layout SPUD' % {
'sparse':sparsename,
'vol':volname})
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 463eedb4fd..98ad8af02d 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -14,6 +14,7 @@ include(LScript)
include(Linking)
include(Tut)
include(Boost)
+include(GoogleMock)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -24,6 +25,7 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
set(test_SOURCE_FILES
@@ -126,6 +128,7 @@ target_link_libraries(test
${LLXML_LIBRARIES}
${LSCRIPT_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
${APRICONV_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
@@ -145,12 +148,18 @@ endif (WINDOWS)
get_target_property(TEST_EXE test LOCATION)
+SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(TEST_LD_CMD
+ ${CMAKE_COMMAND}
+ -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
+ -DTEST_CMD:STRING="${TEST_CMD}"
+ -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
+ )
+
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
- COMMAND ${TEST_EXE}
- ARGS
- --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt
- --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
+ COMMAND ${TEST_LD_CMD}
DEPENDS test
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "C++ unit tests"
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 2f50d872ee..721e9da917 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,6 +54,11 @@
# include "ctype_workaround.h"
#endif
+#ifndef LL_WINDOWS
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#endif
+
namespace tut
{
std::string sSourceDir;
@@ -235,6 +240,11 @@ void wouldHaveCrashed(const std::string& message)
int main(int argc, char **argv)
{
+ // The following line must be executed to initialize Google Mock
+ // (and Google Test) before running the tests.
+#ifndef LL_WINDOWS
+ ::testing::InitGoogleMock(&argc, argv);
+#endif
LLError::initForApplication(".");
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index 7869763302..f9568a9b5d 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -2033,6 +2033,10 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
case MEDIA_EVENT_PLUGIN_FAILED:
std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << std::endl;
break;
+
+ case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
+ std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl;
+ break;
}
}
diff --git a/install.xml b/install.xml
index 6366b3104b..7c8fc5ae69 100644
--- a/install.xml
+++ b/install.xml
@@ -48,7 +48,7 @@
<key>copyright</key>
<string>Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga</string>
<key>description</key>
- <string>The Simple DirectMedia Layer libraries are used for handling input and basic window/GL setup on the Linux client.</string>
+ <string>The Simple DirectMedia Layer libraries are used for handling input and basic window/GL setup on the Linux client. Packages also include cursors.</string>
<key>license</key>
<string>lgpl</string>
<key>packages</key>
@@ -56,23 +56,23 @@
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>7b07e7121a3623b2553ed36fb9024b40</string>
+ <string>40b8a63b553d91304588fba6796d7cc1</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-darwin-20080818.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-darwin-20091006.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>25f8a8fc4ea94169fe6222571b8d5e55</string>
+ <string>298fd8a3351f6a8d757d205a1e9ad82f</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.12-linux-20081222c.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.12-linux-20091006.tar.bz2</uri>
</map>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>149626b0c10d7eb8b9f9be96b5318218</string>
+ <string>33bb17ecbef6cdadff533d97135f3a56</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-windows-20080613.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-windows-20091006.tar.bz2</uri>
</map>
</map>
</map>
@@ -578,6 +578,39 @@
</map>
</map>
</map>
+ <key>googlemock</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright 2008, Google Inc.</string>
+ <key>description</key>
+ <string>Google C++ Mocking Framework (or Google Mock for short) is a library for writing and using C++ mock classes.</string>
+ <key>license</key>
+ <string>bsd</string>
+ <key>packages</key>
+ <map>
+ <key>darwin</key>
+ <map>
+ <key>md5sum</key>
+ <string>4863e9fea433d0a4be761ea5d3e8346a</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-darwin-20090626.tar.bz2</uri>
+ </map>
+ <key>linux</key>
+ <map>
+ <key>md5sum</key>
+ <string>877dabecf84339690191c6115c76366e</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-linux32-20090527.tar.bz2</uri>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>md5sum</key>
+ <string>be37695d9f26552aec81c8e97ded0212</string>
+ <key>url</key>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-windows-20090529.tar.bz2</uri>
+ </map>
+ </map>
+ </map>
<key>google-perftools</key>
<map>
<key>copyright</key>
diff --git a/scripts/install.py b/scripts/install.py
index 6278fba16c..78b8880b95 100755
--- a/scripts/install.py
+++ b/scripts/install.py
@@ -64,7 +64,6 @@ def add_indra_lib_path():
base_dir = add_indra_lib_path()
import copy
-import md5
import optparse
import os
import platform
@@ -75,7 +74,12 @@ import tempfile
import urllib2
import urlparse
-from sets import Set as set, ImmutableSet as frozenset
+try:
+ # Python 2.6
+ from hashlib import md5
+except ImportError:
+ # Python 2.5 and earlier
+ from md5 import new as md5
from indra.base import llsd
from indra.util import helpformatter
@@ -106,7 +110,7 @@ class InstallFile(object):
return "ifile{%s:%s}" % (self.pkgname, self.url)
def _is_md5sum_match(self):
- hasher = md5.new(file(self.filename, 'rb').read())
+ hasher = md5(file(self.filename, 'rb').read())
if hasher.hexdigest() == self.md5sum:
return True
return False
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 0ddd0dbcdb..f0c6780938 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -5288,6 +5288,10 @@ version 2.0
{ AgentLegacyAccess U8 }
{ AgentMaxAccess U8 }
}
+ {
+ AgentInfo Variable
+ { Flags U32 }
+ }
}
// ChildAgentAlive
diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py
index 9081941521..ee1ce69a15 100755
--- a/scripts/update_version_files.py
+++ b/scripts/update_version_files.py
@@ -241,23 +241,17 @@ def main():
if update_server:
server_version = new_version
else:
- # Assume we're updating just the build number
- cl = '%s info "%s"' % (svn, src_root)
- status, output = _getstatusoutput(cl)
- if verbose:
- print
- print "svn info output:"
- print "----------------"
- print output
-
- branch_match = svn_branch_re.search(output)
- revision_match = svn_revision_re.search(output)
- if not branch_match or not revision_match:
- print "Failed to execute svn info, output follows:"
- print output
+
+ if llversion.using_svn():
+ revision = llversion.get_svn_revision()
+ branch = llversion.get_svn_branch()
+ elif llversion.using_hg():
+ revision = llversion.get_hg_changeset()
+ branch = llversion.get_hg_repo()
+ else:
+ print >>sys.stderr, "ERROR: could not determine revision and branch"
return -1
- branch = branch_match.group(1)
- revision = revision_match.group(1)
+
if skip_on_branch_re and skip_on_branch_re.match(branch):
print "Release Candidate Build, leaving version files untouched."
return 0